ttmg-pack 0.0.8 → 0.0.9

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/CHANGELOG.md CHANGED
@@ -43,6 +43,11 @@
43
43
  ## 0.0.8
44
44
 
45
45
  ODR 相关功能
46
+
46
47
  - 支持 ODR 打包
47
48
  - 支持 ODR 下载
48
49
  - 支持 ODR 配置写入
50
+
51
+ ## 0.0.9
52
+
53
+ 拆分 debug 功能 和 build 功能
@@ -0,0 +1,19 @@
1
+ const path = require('path');
2
+ const { debugPkgs } = require('../dist/index.js');
3
+ const baseDir = path.join(process.cwd(), '__TEST__');
4
+
5
+ // const dirName = 'PuzzleBlink';
6
+ const dirName = 'Bird';
7
+ // const dirName = "LayaTest";
8
+
9
+ (async () => {
10
+ await debugPkgs({
11
+ entry: path.join(baseDir, dirName, 'src'),
12
+ output: path.join(baseDir, dirName, 'output'),
13
+ rules: {
14
+ mainPackageSizeLimit: 199 * 1024 * 1024,
15
+ projectSizeLimit: 164 * 1024 * 1024,
16
+ subpackageSizeLimit: 10 * 1024 * 1024,
17
+ },
18
+ });
19
+ })();
@@ -0,0 +1,19 @@
1
+ const path = require('path');
2
+ const { buildPkgs } = require('../dist/index.js');
3
+ const baseDir = path.join(process.cwd(), '__TEST__');
4
+
5
+ // const dirName = 'PuzzleBlink';
6
+ const dirName = 'Bird';
7
+ // const dirName = "LayaTest";
8
+
9
+ (async () => {
10
+ await buildPkgs({
11
+ entry: path.join(baseDir, dirName, 'src'),
12
+ output: path.join(baseDir, dirName, 'output'),
13
+ rules: {
14
+ mainPackageSizeLimit: 199 * 1024 * 1024,
15
+ projectSizeLimit: 164 * 1024 * 1024,
16
+ subpackageSizeLimit: 10 * 1024 * 1024,
17
+ },
18
+ });
19
+ })();
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { buildPkgs, downloadOdrPkgs, writeOdrConfig } from './src/libs';
1
+ export { buildPkgs, debugPkgs, downloadOdrPkgs, writeOdrConfig } from './src/libs';
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * ==========================================
3
3
  * @Description: ttmg pack
4
- * @Version: 0.0.8
4
+ * @Version: 0.0.9
5
5
  * @Author: zhanghongyang.mocha
6
- * @Date: 2025-08-20 10:49:07
6
+ * @Date: 2025-08-20 11:16:06
7
7
  * ==========================================
8
8
  */
9
- "use strict";var e=require("fs"),t=require("winston"),n=require("path");require("crypto"),require("zlib");var s=require("acorn"),o=require("glob"),i=require("magic-string");function c(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var s=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,s.get?s:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var r=c(e),a=c(n);function u(t){e.existsSync(t)||e.mkdirSync(t,{recursive:!0})}const l=new class{constructor(){this.logger=null}init(e,s=!0){this.enableLog=s,this.logger=t.createLogger({level:"info",format:t.format.combine(t.format.timestamp(),t.format.json()),transports:[new t.transports.File({filename:n.join(e,"pack.log")}),new t.transports.Console]})}info(e){this.enableLog&&this.logger.info(e)}error(e){this.enableLog&&this.logger.error(e)}warn(e){this.enableLog&&this.logger.warn(e)}debug(e){this.enableLog&&this.logger.debug(e)}log(e){this.logger.info(e)}setOutput(e){this.output=e}};function f(t){if(!e.existsSync(t))return!1;if(!e.statSync(t).isDirectory())return!1;let s=!0;const o=e.readdirSync(t);for(const i of o){const o=n.join(t,i);if(e.statSync(o).isDirectory()){f(o)||(s=!1)}else s=!1}return!!s&&(e.rmSync(t,{recursive:!0}),!0)}const m="packageConfig.json",d="game.json",g="__GAME__",p=".txt",y="subpackages",k="_code",h="_asset",j=62914560,S=["ttmg_odr_tag_1","ttmg_odr_tag_2","ttmg_odr_tag_3"];function b(t,s=[]){let o=0;if(!e.existsSync(t))return 0;const i=e.readdirSync(t,{withFileTypes:!0});for(const c of i){const i=n.join(t,c.name);c.isDirectory()?s.includes(c.name)||(o+=b(i,s)):c.isFile()&&(o+=e.statSync(i).size)}return o}function _(t){const s=e.readdirSync(t,{withFileTypes:!0});for(const o of s){const s=n.join(t,o.name);if(o.isDirectory())_(s);else if(o.isFile()&&(s.endsWith(".js")||s.endsWith(".js.map")))try{e.unlinkSync(s)}catch(e){}}}function $(t){const s=e.readdirSync(t,{withFileTypes:!0});for(const o of s){const s=n.join(t,o.name);if(o.isDirectory())$(s);else if(o.isFile()&&!s.endsWith(".js")&&!s.endsWith(".js.map"))try{e.unlinkSync(s)}catch(e){}}}const w=["node_modules","__MACOSX"],x=[".DS_Store","Thumbs.db"];const O={__GAME__:{code_url:"https://connect.tiktok-minis.com/test/__GAME___code.txt",asset_url:"https://connect.tiktok-minis.com/test/__GAME___asset.txt",asset_md5:"8e3cc2ebd5536e9183b93fda34c1e7f4",root:"",main:"game.js"},configBundle:{root:"subpackages/configBundle",main:"subpackages/configBundle/game.js",asset_md5:"f624a1b37fb35d4dfb1975105a51ebd4",code_url:"https://connect.tiktok-minis.com/test/configBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/configBundle_asset.txt"},gameBundle:{main:"subpackages/gameBundle/game.js",root:"subpackages/gameBundle",asset_md5:"fcc9f686bbc8d6f983263e7132598b26",code_url:"https://connect.tiktok-minis.com/test/gameBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/gameBundle_asset.txt"},mainBundle:{main:"subpackages/mainBundle/game.js",root:"subpackages/mainBundle",asset_md5:"36b9674d48f9fbb0de6e8f48b194aebc",code_url:"https://connect.tiktok-minis.com/test/mainBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/mainBundle_asset.txt"},resources:{root:"subpackages/resources",main:"subpackages/resources/game.js",asset_md5:"1c4608d7690750f7bd5c00663013fc70",code_url:"https://connect.tiktok-minis.com/test/resources_code.txt",asset_url:"https://connect.tiktok-minis.com/test/resources_asset.txt"},iceAndFire:{root:"subpackages/iceAndFire",main:"subpackages/iceAndFire/game.js",asset_md5:"c7fd8e8506dd59725269027a52e2cae4",code_url:"https://connect.tiktok-minis.com/test/iceAndFire_code.txt",asset_url:"https://connect.tiktok-minis.com/test/iceAndFire_asset.txt"},pushstone:{root:"subpackages/pushstone",main:"subpackages/pushstone/game.js",asset_md5:"f5061dba94ad53e1f578325a7cb26a01",code_url:"https://connect.tiktok-minis.com/test/pushstone_code.txt",asset_url:"https://connect.tiktok-minis.com/test/pushstone_asset.txt"},main:{root:"subpackages/main",main:"subpackages/main/game.js",asset_md5:"aece2f69cc168d7cefb248e8574c3371",code_url:"https://connect.tiktok-minis.com/test/main_code.txt",asset_url:"https://connect.tiktok-minis.com/test/main_asset.txt"}},v=[{id:""+1e17*Math.random(),packages:O},{id:""+1e17*Math.random(),packages:O}];function M(t,s){l.info("start check project");const o=null==s?void 0:s.projectSizeLimit;!function(t){l.info("start check config");const s=n.join(t,d);if(!e.existsSync(s)){const e="can not find game.json in game source code, please check it";throw l.error(e),new Error(e)}l.info("check config successfully")}(t),function(e,t){l.info("start check project size");const n=b(e,[]),s=Math.round(n/1048576),o=Math.round(t/1048576);if(n>t){const e=`Game size ${s}MB, must not exceed ${o}MB`;throw l.error(e),new Error(e)}l.info(`Game size ${s}MB, check successfully!`),l.info("Game size check successfully!")}(t,o),l.info("check project successfully")}function F(e,t){l.info("start check main package");const{mainPackageSizeLimit:n}=t;l.info("check game.js");const s=a.join(e,"game.js");if(!r.existsSync(s)){const e="game.js must exist in main package!";throw l.error(e),new Error(e)}l.info("check game.js successfully"),function({entryDir:e,limit:t}){l.info("start check main package size");const n=b(e,["subpackages"]),s=Math.round(n/1048576),o=Math.round(t/1048576);if(n>t){const e=`Main package size ${s}MB, must not exceed ${o}MB`;throw l.error(e),new Error(e)}l.info(`Main package size ${s}MB, check successfully!`)}({entryDir:e,limit:n}),l.info("check main package successfully")}function D(t,s){const{subpackageSizeLimit:o}=s||{};l.info("start check subpackages in game.json");const i=n.join(t,d),c=JSON.parse(e.readFileSync(i,"utf-8")).subpackages||[];(null==c?void 0:c.length)?c.forEach(s=>{if(!s.name||!s.root){const e="The subpackages configuration in game.json is invalid: the root or name field in one or more subpackages is empty. Please ensure that all subpackages have non-empty root and name values.";throw l.error(e),new Error(e)}const i=n.join(t,s.root);if(!e.existsSync(i)){const e=`The subpackages configuration in game.json is invalid: can not find subpackage ${s.name} entry dir, please check it`;throw l.error(e),new Error(e)}const c=s.root;if(!e.existsSync(n.join(t,c))){const e=`The subpackages configuration in game.json is invalid: can not find subpackage ${s.name} root, please check it`;throw l.error(e),new Error(e)}o&&function({entryDir:e,subPkgName:t,limit:s}){const o=n.join(e,"subpackages",t),i=b(o,[]),c=Math.round(i/1048576);if(c>s){const e=`${t} Sub package size ${c}MB, must not exceed ${s/1048576}MB`;throw l.error(e),new Error(e)}l.info(`${t} Sub package size ${c}MB, check successfully!`)}({entryDir:t,subPkgName:s.name,limit:o})}):l.info("subpackages is empty"),l.info("check subpackages in game.json successfully")}async function E(t,s){l.info("开始基于源代码中的 game.json 生成 packageConfig.json");const o=n.join(t,d),i=JSON.parse(e.readFileSync(o,"utf-8")),c={};c[g]={url:"",md5:"",root:"",main:"game.js",output:`${g}${p}`},function(e){if(!e||0===e.length)return[];function t(e){return String(e).replace(/^\/+|\/+$/g,"")}function n(e){return String(e).trim().replace(/^\/+/,"")}function s(e){return e.endsWith("/")||!/\.[a-zA-Z0-9]+$/.test(e)}return e.map(e=>{const o=t(e.name);let i=n(e.root);const c=i.indexOf(o);return i=-1!==c?i.slice(c):o+(s(i)?"/game.js":"/"+i),s(i)&&(i=i.replace(/\/+$/,"")+"/game.js"),{main:i,root:o}})}(i.subpackages).forEach(e=>{c[e.root]={url:"",md5:"",root:`${y}/${e.root}`,main:`${y}/${e.main}`,output:`${e.root}${p}`}});const r={packages:c};return Object.keys(c).forEach(s=>{const o=n.join(t,c[s].main);if(!e.existsSync(o))throw l.error(`开发者源代码包中的子包 ${s} 中的 main 文件 ${c[s].main} 不存在`),new Error(`开发者源代码包中的子包 ${s} 中的 main 文件 ${c[s].main} 不存在`)}),e.existsSync(s)&&e.rmSync(s,{recursive:!0}),e.mkdirSync(s),e.writeFileSync(n.join(s,m),JSON.stringify(r,null,2)),l.info("基于源代码中的 game.json 生成 packageConfig.json 成功"),r}function B(e){const t=[];return Object.values(e).forEach(e=>{Object.values(e).forEach(e=>{t.push(...e)})}),t}function P(t,s=[".js",".ts",".jsx",".tsx"],o=[]){let i=[];if(!e.existsSync(t))return i;const c=e.readdirSync(t,{withFileTypes:!0});for(const e of c){const c=n.join(t,e.name);if(e.isDirectory()){if(o.includes(e.name))continue;i=i.concat(P(c,s,[]))}else s.some(t=>e.name.endsWith(t))&&i.push(c)}return i}function z(t,i){const c=function(t){return e.readdirSync(t).filter(s=>{const o=n.join(t,s);return e.statSync(o).isDirectory()&&!["node_modules","dist","build","output"].includes(s)}).map(e=>e+"/")}(t),r=o.sync("**/*.js",{cwd:t,ignore:[]}),a=[];r.forEach(o=>{const i=n.join(t,o),r=e.readFileSync(i,"utf-8");let u;try{u=s.parse(r,{ecmaVersion:"latest",sourceType:"module"})}catch(e){return}A(u,s=>{if("CallExpression"===s.type&&"Identifier"===s.callee.type&&("require"===s.callee.name||"requireAsync"===s.callee.name)&&s.arguments.length>0&&"Literal"===s.arguments[0].type){const o=s.arguments[0].value;let r=null;if(o.startsWith("."))r=n.resolve(n.dirname(i),o);else if(o.startsWith("/"))r=n.resolve(t,"."+o);else for(const e of c)if(o.startsWith(e)){r=n.resolve(t,o);break}r&&!function(t){if(e.existsSync(t)&&e.statSync(t).isFile())return!0;const n=[".js",".ts",".jsx",".tsx"];for(const s of n)if(e.existsSync(t+s)&&e.statSync(t+s).isFile())return!0;return!1}(r)&&(r=null),a.push({file:n.relative(t,i),callee:s.callee.name,requirePath:o,resolvedPath:r?n.relative(t,r):""})}})});const u=a.map(e=>{let t="";Object.keys(i).forEach(n=>{e.resolvedPath&&e.resolvedPath.startsWith(i[n].root)&&(t=n)});let n="";return Object.keys(i).forEach(t=>{e.file.startsWith(i[t].root)&&(n=t)}),Object.assign(Object.assign({},e),{curModule:n,depModule:t})}),l=[".js",".ts",".jsx",".tsx"];return u.reduce((e,t)=>{return e[t.curModule]||(e[t.curModule]={}),t.curModule===t.depModule||t.resolvedPath&&(n=t.resolvedPath,l.some(e=>n.endsWith(e)))&&(e[t.curModule]=Object.assign(Object.assign({},e[t.curModule]),{[t.resolvedPath]:t.depModule})),e;var n},{})}function A(e,t){t(e);for(let n in e)if(e.hasOwnProperty(n)){const s=e[n];Array.isArray(s)?s.forEach(e=>e&&"string"==typeof e.type&&A(e,t)):s&&"string"==typeof s.type&&A(s,t)}}function T({gameEntry:t,gameOutput:s,pkgName:o,allDeps:c,allMaps:r,pkgConfig:a,destRoot:f}){let m=Date.now();l.info(`pack start,startTime:${m}`);const d=r[o],g={main:a.main,deps:c[o]||{},map:r[o]};u(f),e.writeFileSync(n.join(f,"moduleConfig.json"),JSON.stringify(g));for(const s in d){const c=d[s];if(!Array.isArray(c)||0===c.length)continue;const r=new i.Bundle({separator:"\n"});for(const o of c){const c=n.join(t,o);if(e.existsSync(c)&&(n.basename(c)!==s&&/\.js$/i.test(o))){const t=e.readFileSync(c,"utf-8"),n=o.replace(/\\/g,"/"),s=`define("game:${n}", ["require", "requireAsync", "module", "exports", "sandboxGlobal"], function(require, requireAsync, module, exports, sandboxGlobal){\nwith(sandboxGlobal){\n`,a="\n}\n});\n",u=new i(t,{filename:n}),l=new i(s).appendLeft(s.length,u.toString()).append(a);r.addSource({content:l,filename:n})}}const a=n.join(f,n.basename(s));e.writeFileSync(a,r.toString()+`\n//# sourceMappingURL=${s}.map`);const u=r.generateMap({hires:!0,includeContent:!0,file:s});e.writeFileSync(a+".map",u.toString()),l.info(`pack end,packName:${o}`)}}function L({pkgRoot:t,destRoot:s,packedFiles:o,gameEntry:i,gameOutput:c,skipDirs:r=[],isRoot:a=!0}){if(!e.existsSync(t))return;const l=e.readdirSync(t,{withFileTypes:!0});for(const f of l){const l=n.join(t,f.name),m=n.join(s,f.name);a&&f.isDirectory()&&r.includes(f.name)||(f.isDirectory()?L({pkgRoot:l,destRoot:m,gameOutput:c,packedFiles:o,gameEntry:i,skipDirs:r,isRoot:!1}):(u(n.dirname(m)),o.includes(n.relative(i,l))||e.copyFileSync(l,m)))}}async function C({gameEntry:t,gameOutput:s}){let o=Date.now();!function(t){!function t(s){let o;try{o=e.readdirSync(s)}catch(e){return void console.warn(`无法访问目录: ${s}`,e)}o.forEach(o=>{const i=n.join(s,o);try{const n=e.statSync(i);n.isDirectory()?w.includes(o)?(e.rmSync(i,{recursive:!0,force:!0}),console.log(`已删除无用目录: ${i}`)):t(i):n.isFile()&&x.includes(o)&&(e.rmSync(i,{force:!0}),console.log(`已删除无用文件: ${i}`))}catch(e){console.warn(`无法处理: ${i}`,e)}})}(t)}(t),l.info(`pack start,startTime:${o}`);const{packages:i}=await E(t,s),c=z(t,i),r=function(e,t){l.info("开始基于游戏源代码收集分包中的 JS 文件");const s={},o=Object.values(t).filter(e=>e.root&&""!==e.root).map(e=>e.root.split(n.sep)[0]).filter(Boolean),i=Array.from(new Set(o));for(const o in t){const c=t[o];let r,a;"__GAME__"===o?(a=P(e,[".js",".ts",".jsx",".tsx"],i),r=e):(r=n.join(e,c.root),a=P(r));const u=[];a.forEach(t=>{u.push(n.relative(e,t).replace(/\\/g,"/"))});const l=t[o].root;s[o]={[l?`${l}/game.pack.js`:"game.pack.js"]:u}}return l.info("基于游戏源代码收集分包中的 JS 文件完成"),s}(t,i);for(const e in r){l.info(`开始基于游戏源代码打包,包名:${e}`);let o=Date.now();const a=i[e],u=n.join(t,a.root),m=n.join(s,e,a.root);T({gameEntry:t,gameOutput:s,allDeps:c,allMaps:r,pkgName:e,pkgConfig:a,destRoot:m}),L({gameEntry:t,gameOutput:s,pkgRoot:u,destRoot:m,packedFiles:B(r),skipDirs:[y]});f(n.join(s,e)),l.info(`基于游戏源代码打包分包完成,包名:${e}`),l.info(`基于游戏源代码打包分包耗时,包名:${e},耗时:${Date.now()-o}ms`)}return l.info(`pack end,duration:${Date.now()-o}ms`),{}}exports.buildPkgs=async function(t){const{entry:s,output:o,enableLog:i=!0,enableCheck:c=!0,enableDev:r=!1,enableOdr:a=!0,rules:f}=t;let d=Date.now();l.init(o,i),l.info("TTMG_PACK_VERSION: 0.0.8"),l.info(`pack start, startTime:${d}`);try{return c&&await async function({entryDir:e,config:t}){l.info("开始校验项目"),M(e,t),F(e,t),D(e,t),l.info("校验项目完成")}({entryDir:s,config:{projectSizeLimit:(null==f?void 0:f.projectSizeLimit)||31457280,mainPackageSizeLimit:(null==f?void 0:f.mainPackageSizeLimit)||4194304,subpackageSizeLimit:null==f?void 0:f.subpackageSizeLimit}}),await C({gameEntry:s,gameOutput:o}),a&&await async function(t){let s=Date.now();l.info(`makeOdrPkgs start, ${s}`);const o=n.join(t,m),i=JSON.parse(e.readFileSync(o,"utf-8")),c=i.packages;for(const s in c){const o=n.join(t,s),i=n.join(t,`${s}${k}`),r=n.join(t,`${s}${h}`);u(i),u(r),e.cpSync(o,i,{recursive:!0}),e.cpSync(o,r,{recursive:!0}),$(i),_(r),c[`${s}${k}`]=Object.assign(Object.assign({},c[s]),{code_url:"",code_md5:"",output:`${s}${k}${p}`}),c[`${s}${h}`]=Object.assign(Object.assign({},c[s]),{asset_url:"",asset_md5:"",output:`${s}${h}${p}`})}e.writeFileSync(o,JSON.stringify(i,null,2)),l.info(`makeOdrPkgs end, ${Date.now()-s}ms`)}(o),r&&function(t){l.info("mergePkgs start");const s=n.join(t,m);let o;try{o=JSON.parse(e.readFileSync(s,"utf-8"))}catch(e){return void l.error(`读取配置文件失败: ${s}, err: ${e.message}`)}const i=o.packages;if(i&&"object"==typeof i){for(const s of Object.keys(i)){const o=n.join(t,s);if(!e.existsSync(o)){l.warn(`package 目录不存在: ${o}`);continue}const i=e.readdirSync(o);for(const s of i){const i=n.join(o,s),c=n.join(t,s);try{const t=e.statSync(i);if(t.isFile())e.copyFileSync(i,c);else if(t.isDirectory())e.cpSync(i,c,{recursive:!0});else if(t.isSymbolicLink()){const n=e.readlinkSync(i);e.existsSync(c)&&e.rmSync(c,{force:!0}),e.symlinkSync(n,c,t.isDirectory()?"dir":"file")}l.info(`合并文件/目录: ${i} -> ${c}`)}catch(e){l.error(`处理文件失败: ${i}, err: ${e.message}`)}}try{e.rmSync(o,{recursive:!0,force:!0}),l.info(`已删除 package 目录: ${o}`)}catch(e){l.error(`删除 package 目录失败: ${o}, err: ${e.message}`)}}l.info("mergePkgs 完成")}else l.error("配置文件中 packages 字段无效, 请检查配置")}(o),{isSuccess:!0}}catch(e){return l.error(`pack error:${e.message}`),{isSuccess:!1,errorMsg:e.message}}finally{l.info(`pack end:${Date.now()-d}ms`)}},exports.downloadOdrPkgs=async function(){const t=n.join(__dirname,"temp");e.existsSync(t)||e.mkdirSync(t);const s=await async function(){return v}();console.log("odr_games",s),function(e,t){for(const n of e){const{id:e,packages:s}=n,o=a.join(t,e);r.existsSync(o)||r.mkdirSync(o);for(const e in s){const t=s[e],{code_url:n}=t,i=require("child_process").execSync(`curl -s "${n}"`).toString();console.log("downloadAndSaveCodesSync code",n);const c=`${e}.txt`,u=a.join(o,c);r.writeFileSync(u,i)}}}(s,t);const o={};for(const e of s){const{id:s,packages:i}=e,c=n.join(t,s);o[s]=b(c)}const i={};S.forEach(e=>{i[e]=[]});const c={};for(const r of s){const{id:s,packages:a}=r,u=o[s];if(u>j)continue;let l=null;for(const c of S){const r=n.join(t,c);e.existsSync(r)||e.mkdirSync(r);if(i[c].reduce((e,t)=>e+o[t],0)+u<=j){const o=n.join(t,s),a=n.join(r,s);e.cpSync(o,a,{recursive:!0}),i[c].push(s),l=c;break}}if(l){c[s]={tag:l,packages:{}};for(const e in a){const t=a[e];console.log("TTMGODRConfig[gameId].packages",e,t),c[s].packages[e]={root:t.root,main:t.main,asset_md5:t.asset_md5,asset_url:t.asset_url}}}}const u=n.join(t,"TTMG_ODR_CONFIG.json");e.writeFileSync(u,JSON.stringify(c,null,2),"utf-8"),console.log("TTMG_ODR_CONFIG.json 已生成:",u)},exports.writeOdrConfig=async function(e){l.info("writeOdrPackagesConfig start");const t=a.join(e,m),n=JSON.parse(r.readFileSync(t,"utf-8")),s=n.packages,o=n.odr_packages||{};for(const e in s){if(e.endsWith(k)){const t=s[e],n=e.split(k)[0];o[n]||(o[n]={}),o[n]=Object.assign(Object.assign({},o[n]),{root:t.root,code_output:t.output,code_md5:t.md5,main:t.main}),delete s[e]}if(e.endsWith(h)){const t=e.split(h)[0],n=s[e];o[t]=Object.assign(Object.assign({},o[t]),{root:n.root,asset_output:n.output,asset_md5:n.md5}),delete s[e]}}n.odr_packages=o,r.writeFileSync(t,JSON.stringify(n,null,2)),l.info("writeOdrPackagesConfig end")};
9
+ "use strict";var e=require("fs"),t=require("winston"),n=require("path");require("crypto"),require("zlib");var s=require("acorn"),o=require("glob"),i=require("magic-string");function c(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var s=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,s.get?s:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var r=c(e),a=c(n);function u(t){e.existsSync(t)||e.mkdirSync(t,{recursive:!0})}const l=new class{constructor(){this.logger=null}init(e,s=!0){this.enableLog=s,this.logger=t.createLogger({level:"info",format:t.format.combine(t.format.timestamp(),t.format.json()),transports:[new t.transports.File({filename:n.join(e,"pack.log")}),new t.transports.Console]})}info(e){this.enableLog&&this.logger.info(e)}error(e){this.enableLog&&this.logger.error(e)}warn(e){this.enableLog&&this.logger.warn(e)}debug(e){this.enableLog&&this.logger.debug(e)}log(e){this.logger.info(e)}setOutput(e){this.output=e}};function f(t){if(!e.existsSync(t))return!1;if(!e.statSync(t).isDirectory())return!1;let s=!0;const o=e.readdirSync(t);for(const i of o){const o=n.join(t,i);if(e.statSync(o).isDirectory()){f(o)||(s=!1)}else s=!1}return!!s&&(e.rmSync(t,{recursive:!0}),!0)}const m="packageConfig.json",g="game.json",d="__GAME__",p=".txt",y="subpackages",k="_code",h="_asset",j=62914560,S=["ttmg_odr_tag_1","ttmg_odr_tag_2","ttmg_odr_tag_3"],b=31457280,_=4194304;function $(t,s=[]){let o=0;if(!e.existsSync(t))return 0;const i=e.readdirSync(t,{withFileTypes:!0});for(const c of i){const i=n.join(t,c.name);c.isDirectory()?s.includes(c.name)||(o+=$(i,s)):c.isFile()&&(o+=e.statSync(i).size)}return o}function w(t){const s=e.readdirSync(t,{withFileTypes:!0});for(const o of s){const s=n.join(t,o.name);if(o.isDirectory())w(s);else if(o.isFile()&&(s.endsWith(".js")||s.endsWith(".js.map")))try{e.unlinkSync(s)}catch(e){}}}function x(t){const s=e.readdirSync(t,{withFileTypes:!0});for(const o of s){const s=n.join(t,o.name);if(o.isDirectory())x(s);else if(o.isFile()&&!s.endsWith(".js")&&!s.endsWith(".js.map"))try{e.unlinkSync(s)}catch(e){}}}const O=["node_modules","__MACOSX"],v=[".DS_Store","Thumbs.db"];const M={__GAME__:{code_url:"https://connect.tiktok-minis.com/test/__GAME___code.txt",asset_url:"https://connect.tiktok-minis.com/test/__GAME___asset.txt",asset_md5:"8e3cc2ebd5536e9183b93fda34c1e7f4",root:"",main:"game.js"},configBundle:{root:"subpackages/configBundle",main:"subpackages/configBundle/game.js",asset_md5:"f624a1b37fb35d4dfb1975105a51ebd4",code_url:"https://connect.tiktok-minis.com/test/configBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/configBundle_asset.txt"},gameBundle:{main:"subpackages/gameBundle/game.js",root:"subpackages/gameBundle",asset_md5:"fcc9f686bbc8d6f983263e7132598b26",code_url:"https://connect.tiktok-minis.com/test/gameBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/gameBundle_asset.txt"},mainBundle:{main:"subpackages/mainBundle/game.js",root:"subpackages/mainBundle",asset_md5:"36b9674d48f9fbb0de6e8f48b194aebc",code_url:"https://connect.tiktok-minis.com/test/mainBundle_code.txt",asset_url:"https://connect.tiktok-minis.com/test/mainBundle_asset.txt"},resources:{root:"subpackages/resources",main:"subpackages/resources/game.js",asset_md5:"1c4608d7690750f7bd5c00663013fc70",code_url:"https://connect.tiktok-minis.com/test/resources_code.txt",asset_url:"https://connect.tiktok-minis.com/test/resources_asset.txt"},iceAndFire:{root:"subpackages/iceAndFire",main:"subpackages/iceAndFire/game.js",asset_md5:"c7fd8e8506dd59725269027a52e2cae4",code_url:"https://connect.tiktok-minis.com/test/iceAndFire_code.txt",asset_url:"https://connect.tiktok-minis.com/test/iceAndFire_asset.txt"},pushstone:{root:"subpackages/pushstone",main:"subpackages/pushstone/game.js",asset_md5:"f5061dba94ad53e1f578325a7cb26a01",code_url:"https://connect.tiktok-minis.com/test/pushstone_code.txt",asset_url:"https://connect.tiktok-minis.com/test/pushstone_asset.txt"},main:{root:"subpackages/main",main:"subpackages/main/game.js",asset_md5:"aece2f69cc168d7cefb248e8574c3371",code_url:"https://connect.tiktok-minis.com/test/main_code.txt",asset_url:"https://connect.tiktok-minis.com/test/main_asset.txt"}},F=[{id:""+1e17*Math.random(),packages:M},{id:""+1e17*Math.random(),packages:M}];function D(t,s){l.info("start check project");const o=null==s?void 0:s.projectSizeLimit;!function(t){l.info("start check config");const s=n.join(t,g);if(!e.existsSync(s)){const e="can not find game.json in game source code, please check it";throw l.error(e),new Error(e)}l.info("check config successfully")}(t),function(e,t){l.info("start check project size");const n=$(e,[]),s=Math.round(n/1048576),o=Math.round(t/1048576);if(n>t){const e=`Game size ${s}MB, must not exceed ${o}MB`;throw l.error(e),new Error(e)}l.info(`Game size ${s}MB, check successfully!`),l.info("Game size check successfully!")}(t,o),l.info("check project successfully")}function E(e,t){l.info("start check main package");const{mainPackageSizeLimit:n}=t;l.info("check game.js");const s=a.join(e,"game.js");if(!r.existsSync(s)){const e="game.js must exist in main package!";throw l.error(e),new Error(e)}l.info("check game.js successfully"),function({entryDir:e,limit:t}){l.info("start check main package size");const n=$(e,["subpackages"]),s=Math.round(n/1048576),o=Math.round(t/1048576);if(n>t){const e=`Main package size ${s}MB, must not exceed ${o}MB`;throw l.error(e),new Error(e)}l.info(`Main package size ${s}MB, check successfully!`)}({entryDir:e,limit:n}),l.info("check main package successfully")}function z(t,s){const{subpackageSizeLimit:o}=s||{};l.info("start check subpackages in game.json");const i=n.join(t,g),c=JSON.parse(e.readFileSync(i,"utf-8")).subpackages||[];(null==c?void 0:c.length)?c.forEach(s=>{if(!s.name||!s.root){const e="The subpackages configuration in game.json is invalid: the root or name field in one or more subpackages is empty. Please ensure that all subpackages have non-empty root and name values.";throw l.error(e),new Error(e)}const i=n.join(t,s.root);if(!e.existsSync(i)){const e=`The subpackages configuration in game.json is invalid: can not find subpackage ${s.name} entry dir, please check it`;throw l.error(e),new Error(e)}const c=s.root;if(!e.existsSync(n.join(t,c))){const e=`The subpackages configuration in game.json is invalid: can not find subpackage ${s.name} root, please check it`;throw l.error(e),new Error(e)}o&&function({entryDir:e,subPkgName:t,limit:s}){const o=n.join(e,"subpackages",t),i=$(o,[]),c=Math.round(i/1048576);if(c>s){const e=`${t} Sub package size ${c}MB, must not exceed ${s/1048576}MB`;throw l.error(e),new Error(e)}l.info(`${t} Sub package size ${c}MB, check successfully!`)}({entryDir:t,subPkgName:s.name,limit:o})}):l.info("subpackages is empty"),l.info("check subpackages in game.json successfully")}async function P({entryDir:e,config:t}){l.info("开始校验项目"),D(e,t),E(e,t),z(e,t),l.info("校验项目完成")}async function B(t,s){l.info("开始基于源代码中的 game.json 生成 packageConfig.json");const o=n.join(t,g),i=JSON.parse(e.readFileSync(o,"utf-8")),c={};c[d]={url:"",md5:"",root:"",main:"game.js",output:`${d}${p}`},function(e){if(!e||0===e.length)return[];function t(e){return String(e).replace(/^\/+|\/+$/g,"")}function n(e){return String(e).trim().replace(/^\/+/,"")}function s(e){return e.endsWith("/")||!/\.[a-zA-Z0-9]+$/.test(e)}return e.map(e=>{const o=t(e.name);let i=n(e.root);const c=i.indexOf(o);return i=-1!==c?i.slice(c):o+(s(i)?"/game.js":"/"+i),s(i)&&(i=i.replace(/\/+$/,"")+"/game.js"),{main:i,root:o}})}(i.subpackages).forEach(e=>{c[e.root]={url:"",md5:"",root:`${y}/${e.root}`,main:`${y}/${e.main}`,output:`${e.root}${p}`}});const r={packages:c};return Object.keys(c).forEach(s=>{const o=n.join(t,c[s].main);if(!e.existsSync(o))throw l.error(`开发者源代码包中的子包 ${s} 中的 main 文件 ${c[s].main} 不存在`),new Error(`开发者源代码包中的子包 ${s} 中的 main 文件 ${c[s].main} 不存在`)}),e.existsSync(s)&&e.rmSync(s,{recursive:!0}),e.mkdirSync(s),e.writeFileSync(n.join(s,m),JSON.stringify(r,null,2)),l.info("基于源代码中的 game.json 生成 packageConfig.json 成功"),r}function L(e){const t=[];return Object.values(e).forEach(e=>{Object.values(e).forEach(e=>{t.push(...e)})}),t}function A(t,s=[".js",".ts",".jsx",".tsx"],o=[]){let i=[];if(!e.existsSync(t))return i;const c=e.readdirSync(t,{withFileTypes:!0});for(const e of c){const c=n.join(t,e.name);if(e.isDirectory()){if(o.includes(e.name))continue;i=i.concat(A(c,s,[]))}else s.some(t=>e.name.endsWith(t))&&i.push(c)}return i}function T(t,i){const c=function(t){return e.readdirSync(t).filter(s=>{const o=n.join(t,s);return e.statSync(o).isDirectory()&&!["node_modules","dist","build","output"].includes(s)}).map(e=>e+"/")}(t),r=o.sync("**/*.js",{cwd:t,ignore:[]}),a=[];r.forEach(o=>{const i=n.join(t,o),r=e.readFileSync(i,"utf-8");let u;try{u=s.parse(r,{ecmaVersion:"latest",sourceType:"module"})}catch(e){return}C(u,s=>{if("CallExpression"===s.type&&"Identifier"===s.callee.type&&("require"===s.callee.name||"requireAsync"===s.callee.name)&&s.arguments.length>0&&"Literal"===s.arguments[0].type){const o=s.arguments[0].value;let r=null;if(o.startsWith("."))r=n.resolve(n.dirname(i),o);else if(o.startsWith("/"))r=n.resolve(t,"."+o);else for(const e of c)if(o.startsWith(e)){r=n.resolve(t,o);break}r&&!function(t){if(e.existsSync(t)&&e.statSync(t).isFile())return!0;const n=[".js",".ts",".jsx",".tsx"];for(const s of n)if(e.existsSync(t+s)&&e.statSync(t+s).isFile())return!0;return!1}(r)&&(r=null),a.push({file:n.relative(t,i),callee:s.callee.name,requirePath:o,resolvedPath:r?n.relative(t,r):""})}})});const u=a.map(e=>{let t="";Object.keys(i).forEach(n=>{e.resolvedPath&&e.resolvedPath.startsWith(i[n].root)&&(t=n)});let n="";return Object.keys(i).forEach(t=>{e.file.startsWith(i[t].root)&&(n=t)}),Object.assign(Object.assign({},e),{curModule:n,depModule:t})}),l=[".js",".ts",".jsx",".tsx"];return u.reduce((e,t)=>{return e[t.curModule]||(e[t.curModule]={}),t.curModule===t.depModule||t.resolvedPath&&(n=t.resolvedPath,l.some(e=>n.endsWith(e)))&&(e[t.curModule]=Object.assign(Object.assign({},e[t.curModule]),{[t.resolvedPath]:t.depModule})),e;var n},{})}function C(e,t){t(e);for(let n in e)if(e.hasOwnProperty(n)){const s=e[n];Array.isArray(s)?s.forEach(e=>e&&"string"==typeof e.type&&C(e,t)):s&&"string"==typeof s.type&&C(s,t)}}function N({gameEntry:t,gameOutput:s,pkgName:o,allDeps:c,allMaps:r,pkgConfig:a,destRoot:f}){let m=Date.now();l.info(`pack start,startTime:${m}`);const g=r[o],d={main:a.main,deps:c[o]||{},map:r[o]};u(f),e.writeFileSync(n.join(f,"moduleConfig.json"),JSON.stringify(d));for(const s in g){const c=g[s];if(!Array.isArray(c)||0===c.length)continue;const r=new i.Bundle({separator:"\n"});for(const o of c){const c=n.join(t,o);if(e.existsSync(c)&&(n.basename(c)!==s&&/\.js$/i.test(o))){const t=e.readFileSync(c,"utf-8"),n=o.replace(/\\/g,"/"),s=`define("game:${n}", ["require", "requireAsync", "module", "exports", "sandboxGlobal"], function(require, requireAsync, module, exports, sandboxGlobal){\nwith(sandboxGlobal){\n`,a="\n}\n});\n",u=new i(t,{filename:n}),l=new i(s).appendLeft(s.length,u.toString()).append(a);r.addSource({content:l,filename:n})}}const a=n.join(f,n.basename(s));e.writeFileSync(a,r.toString()+`\n//# sourceMappingURL=${s}.map`);const u=r.generateMap({hires:!0,includeContent:!0,file:s});e.writeFileSync(a+".map",u.toString()),l.info(`pack end,packName:${o}`)}}function G({pkgRoot:t,destRoot:s,packedFiles:o,gameEntry:i,gameOutput:c,skipDirs:r=[],isRoot:a=!0}){if(!e.existsSync(t))return;const l=e.readdirSync(t,{withFileTypes:!0});for(const f of l){const l=n.join(t,f.name),m=n.join(s,f.name);a&&f.isDirectory()&&r.includes(f.name)||(f.isDirectory()?G({pkgRoot:l,destRoot:m,gameOutput:c,packedFiles:o,gameEntry:i,skipDirs:r,isRoot:!1}):(u(n.dirname(m)),o.includes(n.relative(i,l))||e.copyFileSync(l,m)))}}async function q({gameEntry:t,gameOutput:s}){let o=Date.now();!function(t){!function t(s){let o;try{o=e.readdirSync(s)}catch(e){return void console.warn(`无法访问目录: ${s}`,e)}o.forEach(o=>{const i=n.join(s,o);try{const n=e.statSync(i);n.isDirectory()?O.includes(o)?(e.rmSync(i,{recursive:!0,force:!0}),console.log(`已删除无用目录: ${i}`)):t(i):n.isFile()&&v.includes(o)&&(e.rmSync(i,{force:!0}),console.log(`已删除无用文件: ${i}`))}catch(e){console.warn(`无法处理: ${i}`,e)}})}(t)}(t),l.info(`pack start,startTime:${o}`);const{packages:i}=await B(t,s),c=T(t,i),r=function(e,t){l.info("开始基于游戏源代码收集分包中的 JS 文件");const s={},o=Object.values(t).filter(e=>e.root&&""!==e.root).map(e=>e.root.split(n.sep)[0]).filter(Boolean),i=Array.from(new Set(o));for(const o in t){const c=t[o];let r,a;"__GAME__"===o?(a=A(e,[".js",".ts",".jsx",".tsx"],i),r=e):(r=n.join(e,c.root),a=A(r));const u=[];a.forEach(t=>{u.push(n.relative(e,t).replace(/\\/g,"/"))});const l=t[o].root;s[o]={[l?`${l}/game.pack.js`:"game.pack.js"]:u}}return l.info("基于游戏源代码收集分包中的 JS 文件完成"),s}(t,i);for(const e in r){l.info(`开始基于游戏源代码打包,包名:${e}`);let o=Date.now();const a=i[e],u=n.join(t,a.root),m=n.join(s,e,a.root);N({gameEntry:t,gameOutput:s,allDeps:c,allMaps:r,pkgName:e,pkgConfig:a,destRoot:m}),G({gameEntry:t,gameOutput:s,pkgRoot:u,destRoot:m,packedFiles:L(r),skipDirs:[y]});f(n.join(s,e)),l.info(`基于游戏源代码打包分包完成,包名:${e}`),l.info(`基于游戏源代码打包分包耗时,包名:${e},耗时:${Date.now()-o}ms`)}return l.info(`pack end,duration:${Date.now()-o}ms`),{}}exports.buildPkgs=async function(t){const{entry:s,output:o,rules:i}=t;let c=Date.now();l.init(o,!0),l.info("TTMG_PACK_VERSION: 0.0.9"),l.info(`pack start, startTime:${c}`);try{return await P({entryDir:s,config:{projectSizeLimit:(null==i?void 0:i.projectSizeLimit)||b,mainPackageSizeLimit:(null==i?void 0:i.mainPackageSizeLimit)||_,subpackageSizeLimit:null==i?void 0:i.subpackageSizeLimit}}),await q({gameEntry:s,gameOutput:o}),await async function(t){let s=Date.now();l.info(`makeOdrPkgs start, ${s}`);const o=n.join(t,m),i=JSON.parse(e.readFileSync(o,"utf-8")),c=i.packages;for(const s in c){const o=n.join(t,s),i=n.join(t,`${s}${k}`),r=n.join(t,`${s}${h}`);u(i),u(r),e.cpSync(o,i,{recursive:!0}),e.cpSync(o,r,{recursive:!0}),x(i),w(r),c[`${s}${k}`]=Object.assign(Object.assign({},c[s]),{code_url:"",code_md5:"",output:`${s}${k}${p}`}),c[`${s}${h}`]=Object.assign(Object.assign({},c[s]),{asset_url:"",asset_md5:"",output:`${s}${h}${p}`})}e.writeFileSync(o,JSON.stringify(i,null,2)),l.info(`makeOdrPkgs end, ${Date.now()-s}ms`)}(o),{isSuccess:!0}}catch(e){return l.error(`pack error:${e.message}`),{isSuccess:!1,errorMsg:e.message}}finally{l.info(`pack end:${Date.now()-c}ms`)}},exports.debugPkgs=async function(t){const{entry:s,output:o,rules:i}=t;l.init(o,!1);try{return await P({entryDir:s,config:{projectSizeLimit:(null==i?void 0:i.projectSizeLimit)||b,mainPackageSizeLimit:(null==i?void 0:i.mainPackageSizeLimit)||_,subpackageSizeLimit:null==i?void 0:i.subpackageSizeLimit}}),await q({gameEntry:s,gameOutput:o}),await function(t){l.info("mergePkgs start");const s=n.join(t,m);let o;try{o=JSON.parse(e.readFileSync(s,"utf-8"))}catch(e){return void l.error(`读取配置文件失败: ${s}, err: ${e.message}`)}const i=o.packages;if(i&&"object"==typeof i){for(const s of Object.keys(i)){const o=n.join(t,s);if(!e.existsSync(o)){l.warn(`package 目录不存在: ${o}`);continue}const i=e.readdirSync(o);for(const s of i){const i=n.join(o,s),c=n.join(t,s);try{const t=e.statSync(i);if(t.isFile())e.copyFileSync(i,c);else if(t.isDirectory())e.cpSync(i,c,{recursive:!0});else if(t.isSymbolicLink()){const n=e.readlinkSync(i);e.existsSync(c)&&e.rmSync(c,{force:!0}),e.symlinkSync(n,c,t.isDirectory()?"dir":"file")}l.info(`合并文件/目录: ${i} -> ${c}`)}catch(e){l.error(`处理文件失败: ${i}, err: ${e.message}`)}}try{e.rmSync(o,{recursive:!0,force:!0}),l.info(`已删除 package 目录: ${o}`)}catch(e){l.error(`删除 package 目录失败: ${o}, err: ${e.message}`)}}l.info("mergePkgs 完成")}else l.error("配置文件中 packages 字段无效, 请检查配置")}(o),{isSuccess:!0}}catch(e){return{isSuccess:!1,errorMsg:e.message}}},exports.downloadOdrPkgs=async function(){const t=n.join(__dirname,"temp");e.existsSync(t)||e.mkdirSync(t);const s=await async function(){return F}();console.log("odr_games",s),function(e,t){for(const n of e){const{id:e,packages:s}=n,o=a.join(t,e);r.existsSync(o)||r.mkdirSync(o);for(const e in s){const t=s[e],{code_url:n}=t,i=require("child_process").execSync(`curl -s "${n}"`).toString();console.log("downloadAndSaveCodesSync code",n);const c=`${e}.txt`,u=a.join(o,c);r.writeFileSync(u,i)}}}(s,t);const o={};for(const e of s){const{id:s,packages:i}=e,c=n.join(t,s);o[s]=$(c)}const i={};S.forEach(e=>{i[e]=[]});const c={};for(const r of s){const{id:s,packages:a}=r,u=o[s];if(u>j)continue;let l=null;for(const c of S){const r=n.join(t,c);e.existsSync(r)||e.mkdirSync(r);if(i[c].reduce((e,t)=>e+o[t],0)+u<=j){const o=n.join(t,s),a=n.join(r,s);e.cpSync(o,a,{recursive:!0}),i[c].push(s),l=c;break}}if(l){c[s]={tag:l,packages:{}};for(const e in a){const t=a[e];console.log("TTMGODRConfig[gameId].packages",e,t),c[s].packages[e]={root:t.root,main:t.main,asset_md5:t.asset_md5,asset_url:t.asset_url}}}}const u=n.join(t,"TTMG_ODR_CONFIG.json");e.writeFileSync(u,JSON.stringify(c,null,2),"utf-8"),console.log("TTMG_ODR_CONFIG.json 已生成:",u)},exports.writeOdrConfig=async function(e){l.info("writeOdrPackagesConfig start");const t=a.join(e,m),n=JSON.parse(r.readFileSync(t,"utf-8")),s=n.packages,o=n.odr_packages||{};for(const e in s){if(e.endsWith(k)){const t=s[e],n=e.split(k)[0];o[n]||(o[n]={}),o[n]=Object.assign(Object.assign({},o[n]),{root:t.root,code_output:t.output,code_md5:t.md5,main:t.main}),delete s[e]}if(e.endsWith(h)){const t=e.split(h)[0],n=s[e];o[t]=Object.assign(Object.assign({},o[t]),{root:n.root,asset_output:n.output,asset_md5:n.md5}),delete s[e]}}n.odr_packages=o,r.writeFileSync(t,JSON.stringify(n,null,2)),l.info("writeOdrPackagesConfig end")};
10
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/ensureDirSync.ts","../src/utils/logger.ts","../src/utils/removeEmptyDir.ts","../src/constants/index.ts","../src/utils/getDirSizeSync.ts","../src/utils/deleteJsFilesSync.ts","../src/utils/deleteNoJsFilesSync.ts","../src/utils/removeSystemUseless.ts","../src/libs/odrPkgs/mock.ts","../src/libs/checkPkgs/checkProject.ts","../src/libs/checkPkgs/checkMainpackage.ts","../src/libs/checkPkgs/checkSubpackages.ts","../src/libs/makePkgs/setup.ts","../src/libs/makePkgs/collectMaps.ts","../src/libs/makePkgs/collectDeps.ts","../src/libs/makePkgs/pack.ts","../src/libs/makePkgs/partition.ts","../src/libs/makePkgs/index.ts","../src/libs/buildPkgs/index.ts","../src/libs/checkPkgs/index.ts","../src/libs/odrPkgs/makeOdrPkgs.ts","../src/libs/mergePkgs/index.ts","../src/libs/odrPkgs/downloadOdrPkgs.ts","../src/libs/odrPkgs/utils.ts","../src/libs/odrPkgs/writeOdrConfig.ts"],"sourcesContent":["import fs from 'fs';\nexport function ensureDirSync(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n","import winston from 'winston';\nimport path from 'path';\n\nclass Logger {\n logger: winston.Logger;\n enableLog: boolean;\n output: any;\n constructor() {\n this.logger = null;\n }\n init(output: string, enableLog = true) {\n this.enableLog = enableLog;\n this.logger = winston.createLogger({\n level: 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.json(), // 输出为 JSON 格式\n ),\n transports: [\n new winston.transports.File({\n filename: path.join(output, 'pack.log'),\n }),\n new winston.transports.Console(),\n ],\n });\n }\n info(msg: string) {\n if (this.enableLog) {\n this.logger.info(msg);\n }\n }\n error(msg) {\n if (this.enableLog) {\n this.logger.error(msg);\n }\n }\n warn(msg) {\n if (this.enableLog) {\n this.logger.warn(msg);\n }\n }\n debug(msg) {\n if (this.enableLog) {\n this.logger.debug(msg);\n }\n }\n log(msg) {\n this.logger.info(msg);\n }\n setOutput(output) {\n this.output = output;\n }\n}\n\nexport const logger = new Logger();\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * 移除指定目录下所有空文件夹(递归)\n * @param {string} dir 目标目录\n * @returns {boolean} 返回当前目录是否已被删除(即是否为空)\n */\nexport function removeEmptyDir(dir) {\n if (!fs.existsSync(dir)) return false;\n if (!fs.statSync(dir).isDirectory()) return false;\n\n let isEmpty = true;\n const files = fs.readdirSync(dir);\n for (const file of files) {\n const fullPath = path.join(dir, file);\n if (fs.statSync(fullPath).isDirectory()) {\n // 递归处理子目录\n const childIsEmpty = removeEmptyDir(fullPath);\n if (!childIsEmpty) isEmpty = false;\n } else {\n // 有文件,当前目录不为空\n isEmpty = false;\n }\n }\n\n // 如果当前目录为空,删除它\n if (isEmpty) {\n fs.rmSync(dir, { recursive: true });\n return true;\n }\n return false;\n}\n\n","export const GAME_PACK_CONFIG_FILE_NAME = 'packageConfig.json';\nexport const GAME_ORIGIN_CONFIG_FILE_NAME = 'game.json';\nexport const GAME_MODULE_CONFIG_FILE_NAME = 'moduleConfig.json';\nexport const GAME_OUTPUT_CONFIG_FILE_NAME = 'output.json';\nexport const GAME_MAIN_PACKAGE_NAME = '__GAME__';\nexport const TTPKG_TAG = 'TPKG';\nexport const STTPKG_TAG = 'SPKG';\nexport const TTPKG_VERSION = 2;\nexport const ARK_KEY_LEN = 32;\nexport const ARK_INT_LEN = 4;\nexport const UNIT32_LEN = 4;\nexport const UINT16_LEN = 2;\nexport const STTPKG_VERSION = 1;\nexport const ZSTD_COMPRESS_LEVEL = 19;\nexport const ROLL_FILE_EXT = [\n '.js',\n '.json',\n '.wxml',\n '.ttml',\n '.wxss',\n '.ttss',\n];\nexport const EXT = '';\nexport const BROTLI_COMPRESS_TYPE = 1;\nexport const ZSTD_COMPRESS_TYPE = 3;\n\nexport const STTPKG_EXT = '.txt';\n\nexport const SUBPACKAGES_DIR_NAME = 'subpackages';\n\nexport const ODR_CODE_DIR_SUFFIX = '_code';\n\nexport const ODR_ASSET_DIR_SUFFIX = '_asset';\n\n// 60MB const ONE_ODR_PKG_LIMIT = 1024 * 1024;\nexport const ONE_ODR_PKG_LIMIT = 1024 * 1024 * 60;\n\nexport const AVAILABLE_ODR_TAG_LIST = [\n 'ttmg_odr_tag_1',\n 'ttmg_odr_tag_2',\n 'ttmg_odr_tag_3',\n];\n\nexport const PROJECT_SIZE_LIMIT = 30 * 1024 * 1024;\n\n\nexport const MAINPACKAGE_SIZE_LIMIT = 4 * 1024 * 1024;\n","import fs from 'fs';\nimport path from 'path';\n// 递归统计目录下所有文件的大小,支持我过滤某些文件夹\nexport function getDirSizeSync(dir: string, filterDirs: string[] = []) {\n let totalSize = 0;\n if (!fs.existsSync(dir)) return 0;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!filterDirs.includes(entry.name)) {\n totalSize += getDirSizeSync(fullPath, filterDirs);\n }\n } else if (entry.isFile()) {\n totalSize += fs.statSync(fullPath).size;\n }\n }\n return totalSize;\n}\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * 同步删除指定目录及其子目录下所有 .js 文件\n * @param {string} dir 目标目录路径\n */\nexport function deleteJsFilesSync(dir) {\n // 读取目录内容\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // 递归处理子目录\n deleteJsFilesSync(fullPath);\n } else if (\n entry.isFile() &&\n (fullPath.endsWith('.js') || fullPath.endsWith('.js.map'))\n ) {\n try {\n fs.unlinkSync(fullPath);\n } catch (err) {}\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport function deleteNoJsFilesSync(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // 递归处理子目录\n deleteNoJsFilesSync(fullPath);\n } else if (\n entry.isFile() &&\n !(fullPath.endsWith('.js') || fullPath.endsWith('.js.map'))\n ) {\n try {\n fs.unlinkSync(fullPath);\n } catch (err) {}\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nconst uselessDirs = ['node_modules', '__MACOSX'];\nconst uselessFiles = ['.DS_Store', 'Thumbs.db'];\n\nexport function removeSystemUseless(gameEntry: string) {\n /**\n * 递归删除目录下的无用文件夹和无用文件\n */\n function removeUselessDirs(dir: string) {\n let files: string[];\n try {\n files = fs.readdirSync(dir);\n } catch (err) {\n // 目录不可访问,跳过\n console.warn(`无法访问目录: ${dir}`, err);\n return;\n }\n files.forEach(file => {\n const filePath = path.join(dir, file);\n try {\n const stat = fs.statSync(filePath);\n if (stat.isDirectory()) {\n if (uselessDirs.includes(file)) {\n // 删除无用目录\n fs.rmSync(filePath, { recursive: true, force: true });\n console.log(`已删除无用目录: ${filePath}`);\n } else {\n // 递归处理子目录\n removeUselessDirs(filePath);\n }\n } else if (stat.isFile()) {\n if (uselessFiles.includes(file)) {\n // 删除无用文件\n fs.rmSync(filePath, { force: true });\n console.log(`已删除无用文件: ${filePath}`);\n }\n }\n } catch (err) {\n // 某个文件/目录不可访问,跳过\n console.warn(`无法处理: ${filePath}`, err);\n }\n });\n }\n removeUselessDirs(gameEntry);\n}\n","interface ODRPackage {\n // md5: string;\n root: string;\n main: string;\n code_url: string;\n // code_md5: string;\n asset_md5: string;\n asset_url: string;\n}\n\ntype ODRPackages = Record<string, ODRPackage>;\nconst odrPackages: ODRPackages = {\n __GAME__: {\n // md5: '6eac4e8a7a7f54a20bcca6c67d71ebad',\n code_url: 'https://connect.tiktok-minis.com/test/__GAME___code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/__GAME___asset.txt',\n asset_md5: '8e3cc2ebd5536e9183b93fda34c1e7f4',\n root: '',\n main: 'game.js',\n },\n configBundle: {\n // md5: '575a0a1f0191e682fc27af897515740b',\n root: 'subpackages/configBundle',\n main: 'subpackages/configBundle/game.js',\n asset_md5: 'f624a1b37fb35d4dfb1975105a51ebd4',\n code_url: 'https://connect.tiktok-minis.com/test/configBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/configBundle_asset.txt',\n },\n gameBundle: {\n // md5: '02e5d043be3156cfe2553e8af0f1b3d3',\n main: 'subpackages/gameBundle/game.js',\n root: 'subpackages/gameBundle',\n asset_md5: 'fcc9f686bbc8d6f983263e7132598b26',\n code_url: 'https://connect.tiktok-minis.com/test/gameBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/gameBundle_asset.txt',\n },\n mainBundle: {\n // md5: 'f28aae73fbb0cc3b8876c2773a1c5789',\n main: 'subpackages/mainBundle/game.js',\n root: 'subpackages/mainBundle',\n asset_md5: '36b9674d48f9fbb0de6e8f48b194aebc',\n code_url: 'https://connect.tiktok-minis.com/test/mainBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/mainBundle_asset.txt',\n },\n resources: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/resources',\n main: 'subpackages/resources/game.js',\n asset_md5: '1c4608d7690750f7bd5c00663013fc70',\n code_url: 'https://connect.tiktok-minis.com/test/resources_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/resources_asset.txt',\n },\n iceAndFire: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/iceAndFire',\n main: 'subpackages/iceAndFire/game.js',\n asset_md5: 'c7fd8e8506dd59725269027a52e2cae4',\n code_url: 'https://connect.tiktok-minis.com/test/iceAndFire_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/iceAndFire_asset.txt',\n },\n pushstone: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/pushstone',\n main: 'subpackages/pushstone/game.js',\n asset_md5: 'f5061dba94ad53e1f578325a7cb26a01',\n code_url: 'https://connect.tiktok-minis.com/test/pushstone_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/pushstone_asset.txt',\n },\n main: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/main',\n main: 'subpackages/main/game.js',\n asset_md5: 'aece2f69cc168d7cefb248e8574c3371',\n code_url: 'https://connect.tiktok-minis.com/test/main_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/main_asset.txt',\n },\n};\n\nexport const gameOdrPackages = [\n { id: `${Math.random() * 100000000000000000}`, packages: odrPackages },\n { id: `${Math.random() * 100000000000000000}`, packages: odrPackages },\n];\n","import path from 'path';\nimport fs from 'fs';\nimport { CheckConfig } from '@typings';\nimport { GAME_ORIGIN_CONFIG_FILE_NAME } from '@constants';\nimport { logger, getDirSizeSync } from '@utils';\n\nexport function checkConfig(entryDir: string) {\n logger.info('start check config');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n if (!fs.existsSync(gameJsonPath)) {\n const errMsg =\n 'can not find game.json in game source code, please check it';\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n logger.info('check config successfully');\n }\n}\n\n/**\n * 检查游戏大小是否超出限制\n * @param param0\n * @returns\n */\n\nexport function checkProjectSize(entryDir: string, limit: number) {\n logger.info('start check project size');\n const gameSize = getDirSizeSync(entryDir, []);\n const gameSizeMB = Math.round(gameSize / (1024 * 1024));\n const limitMB = Math.round(limit / (1024 * 1024));\n if (gameSize > limit) {\n const errMsg = `Game size ${gameSizeMB}MB, must not exceed ${limitMB}MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 游戏大小检查通过\n */\n logger.info(`Game size ${gameSizeMB}MB, check successfully!`);\n logger.info('Game size check successfully!');\n }\n}\n\nexport function checkProject(\n entryDir: string,\n config?: Pick<CheckConfig, 'projectSizeLimit'>\n) {\n logger.info('start check project');\n const projectSizeLimit = config?.projectSizeLimit;\n checkConfig(entryDir);\n checkProjectSize(entryDir, projectSizeLimit);\n logger.info('check project successfully');\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\nimport { logger, getDirSizeSync } from '@utils';\n/**\n * 检查主包大小是否超出限制\n * @param param0\n * @returns\n */\nexport function checkMainPackageSize({\n entryDir,\n limit,\n}: {\n entryDir: string;\n limit: number;\n}) {\n logger.info('start check main package size');\n const mainPkgSize = getDirSizeSync(entryDir, ['subpackages']);\n const mainPkgSizeMB = Math.round(mainPkgSize / (1024 * 1024));\n const limitMB = Math.round(limit / (1024 * 1024));\n if (mainPkgSize > limit) {\n const errMsg = `Main package size ${mainPkgSizeMB}MB, must not exceed ${limitMB}MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 主包大小检查通过\n */\n logger.info(`Main package size ${mainPkgSizeMB}MB, check successfully!`);\n }\n}\n\nexport function checkMainPackage(\n entryDir: string,\n context: {\n mainPackageSizeLimit: number;\n },\n) {\n logger.info('start check main package');\n const { mainPackageSizeLimit } = context;\n /**\n * 检查 game.js 是否存在\n */\n\n logger.info('check game.js');\n const gameJsPath = path.join(entryDir, 'game.js');\n if (!fs.existsSync(gameJsPath)) {\n const errMsg = 'game.js must exist in main package!';\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n logger.info('check game.js successfully');\n\n /**\n * 检查主包大小是否超出限制\n */\n checkMainPackageSize({\n entryDir,\n limit: mainPackageSizeLimit,\n });\n logger.info('check main package successfully');\n}\n","import { logger, getDirSizeSync } from '@utils';\nimport { CheckConfig } from '@typings';\nimport { GAME_ORIGIN_CONFIG_FILE_NAME } from '@constants';\n\nimport path from 'path';\nimport fs from 'fs';\n\nexport function checkSubpackages(\n entryDir: string,\n config?: Pick<CheckConfig, 'subpackageSizeLimit'>,\n) {\n const { subpackageSizeLimit } = config || {};\n /**\n * 开始校验 subpackages 配置是否有效\n */\n logger.info('start check subpackages in game.json');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));\n const subpackages: Array<{\n name: string;\n root: string;\n }> = gameJson.subpackages || [];\n if (!subpackages?.length) {\n logger.info('subpackages is empty');\n } else {\n subpackages.forEach(sub => {\n /**\n * 校验 subpackage 配置是否为空\n */\n if (!sub.name || !sub.root) {\n const errMsg =\n 'The subpackages configuration in game.json is invalid: the root or name field in one or more subpackages is empty. Please ensure that all subpackages have non-empty root and name values.';\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n /**\n * 校验 subpackage 配置是否有效\n */\n const subpackageEntryDir = path.join(entryDir, sub.root);\n // 检查是文件或者文件夹是否存在\n if (!fs.existsSync(subpackageEntryDir)) {\n const errMsg = `The subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} entry dir, please check it`;\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n const subpackageRoot = sub.root;\n if (!fs.existsSync(path.join(entryDir, subpackageRoot))) {\n const errMsg = `The subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} root, please check it`;\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n /**\n * 校验 subpackage 包大小\n */\n\n if (subpackageSizeLimit) {\n checkSubPackageSize({\n entryDir,\n subPkgName: sub.name,\n limit: subpackageSizeLimit,\n });\n }\n });\n }\n logger.info('check subpackages in game.json successfully');\n}\n\n/**\n * 检查子包大小是否超出限制\n * @param param0\n * @returns\n */\n\nfunction checkSubPackageSize({\n entryDir,\n subPkgName,\n limit,\n}: {\n entryDir: string;\n subPkgName: string;\n limit: number;\n}) {\n const subPkgDir = path.join(entryDir, 'subpackages', subPkgName);\n const subPkgSize = getDirSizeSync(subPkgDir, []);\n const sizeMB = Math.round(subPkgSize / (1024 * 1024));\n if (sizeMB > limit) {\n const errMsg = `${subPkgName} Sub package size ${sizeMB}MB, must not exceed ${\n limit / (1024 * 1024)\n }MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 子包大小检查通过\n */\n logger.info(\n `${subPkgName} Sub package size ${sizeMB}MB, check successfully!`,\n );\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n GAME_ORIGIN_CONFIG_FILE_NAME,\n GAME_MAIN_PACKAGE_NAME,\n STTPKG_EXT,\n SUBPACKAGES_DIR_NAME,\n} from '@constants';\n\nimport { logger } from '@utils';\n\n\n\nexport async function setup(entryDir: string, outputDir: string) {\n logger.info('开始基于源代码中的 game.json 生成 packageConfig.json');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));\n\n const packages = {};\n // 主包\n packages[GAME_MAIN_PACKAGE_NAME] = {\n url: '',\n md5: '',\n root: '',\n main: 'game.js',\n output: `${GAME_MAIN_PACKAGE_NAME}${STTPKG_EXT}`,\n };\n\n transformSubPackages(gameJson.subpackages).forEach(sub => {\n // root 是目录\n packages[sub.root] = {\n url: '',\n md5: '',\n root: `${SUBPACKAGES_DIR_NAME}/${sub.root}`,\n main: `${SUBPACKAGES_DIR_NAME}/${sub.main}`,\n output: `${sub.root}${STTPKG_EXT}`,\n };\n });\n\n const result = {\n packages,\n };\n /**\n * 校验子包的 main 文件是否存在\n */\n Object.keys(packages).forEach(pkg => {\n const pkgPath = path.join(entryDir, packages[pkg].main);\n if (!fs.existsSync(pkgPath)) {\n logger.error(\n `开发者源代码包中的子包 ${pkg} 中的 main 文件 ${packages[pkg].main} 不存在`,\n );\n\n throw new Error(\n `开发者源代码包中的子包 ${pkg} 中的 main 文件 ${packages[pkg].main} 不存在`,\n );\n }\n });\n\n if (fs.existsSync(outputDir)) {\n fs.rmSync(outputDir, { recursive: true });\n }\n fs.mkdirSync(outputDir);\n fs.writeFileSync(\n path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME),\n JSON.stringify(result, null, 2),\n );\n logger.info('基于源代码中的 game.json 生成 packageConfig.json 成功');\n return result;\n}\n\nfunction transformSubPackages(configs) {\n if (!configs || configs.length === 0) {\n return [];\n }\n function normalizeName(name) {\n return String(name).replace(/^\\/+|\\/+$/g, '');\n }\n\n function normalizeRoot(root) {\n return String(root).trim().replace(/^\\/+/, '');\n }\n\n function isDirectory(str) {\n // 以 / 结尾,或没有 .js 结尾且没有 . 号\n return str.endsWith('/') || !/\\.[a-zA-Z0-9]+$/.test(str);\n }\n\n return configs.map(config => {\n const name = normalizeName(config.name);\n let root = normalizeRoot(config.root);\n\n // 找到 root 中 name 的第一次出现\n const idx = root.indexOf(name);\n\n if (idx !== -1) {\n // 保留从 name 开始的部分\n root = root.slice(idx);\n } else {\n // root 里没有 name,直接用 name 拼接\n root = name + (isDirectory(root) ? '/game.js' : '/' + root);\n }\n\n // 如果 root 现在是目录,补全 game.js\n if (isDirectory(root)) {\n root = root.replace(/\\/+$/, '') + '/game.js';\n }\n\n return { main: root, root: name };\n });\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { logger } from '@utils';\n\nexport function flattenMaps(allMaps) {\n const list = [];\n Object.values(allMaps).forEach(map => {\n Object.values(map).forEach(arr => {\n list.push(...arr);\n });\n });\n return list;\n}\n\n// 递归收集 JS 文件,但可排除指定目录\nfunction collectAllJsFiles(\n dir,\n exts = ['.js', '.ts', '.jsx', '.tsx'],\n excludeDirs = [],\n) {\n let files = [];\n if (!fs.existsSync(dir)) return files;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (excludeDirs.includes(entry.name)) continue; // 跳过排除目录\n files = files.concat(collectAllJsFiles(fullPath, exts, [])); // 只排除一级\n } else if (exts.some(ext => entry.name.endsWith(ext))) {\n files.push(fullPath);\n }\n }\n return files;\n}\n\n// 构建每个包的 map\nexport function collectMaps(\n entryDir,\n packages: Record<string, { root: string }>,\n) {\n logger.info('开始基于游戏源代码收集分包中的 JS 文件');\n const result = {};\n // 1. 先收集所有分包根目录名(如 subpackages/level1、subpackages/level2)\n const subRoots = Object.values(packages)\n .filter(pkg => pkg.root && pkg.root !== '')\n .map(pkg => pkg.root.split(path.sep)[0]) // 只提取一级目录名\n .filter(Boolean);\n const uniqueSubRoots = Array.from(new Set(subRoots));\n\n for (const pkgName in packages) {\n const pkg = packages[pkgName];\n let srcRoot;\n let jsFiles;\n if (pkgName === '__GAME__') {\n // 主包:只收集 entryDir 下非分包目录\n jsFiles = collectAllJsFiles(\n entryDir,\n ['.js', '.ts', '.jsx', '.tsx'],\n uniqueSubRoots,\n );\n srcRoot = entryDir;\n } else {\n // 分包:只收集自己目录\n srcRoot = path.join(entryDir, pkg.root);\n jsFiles = collectAllJsFiles(srcRoot);\n }\n // 以包的 srcRoot 为基准生成相对路径\n const list = [];\n jsFiles.forEach(absPath => {\n list.push(path.relative(entryDir, absPath).replace(/\\\\/g, '/'));\n });\n const packNameRoot = packages[pkgName].root;\n result[pkgName] = {\n [packNameRoot ? `${packNameRoot}/game.pack.js` : 'game.pack.js']: list,\n };\n }\n logger.info('基于游戏源代码收集分包中的 JS 文件完成');\n return result;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport acorn from 'acorn';\nimport glob from 'glob';\n\nexport function collectDeps(gameEntry, packages) {\n // 自动扫描 game 目录下的一级文件夹作为根前缀\n const rootPrefixes = getRootPrefixes(gameEntry);\n\n // 查找所有 JS 文件\n const files = glob.sync('**/*.js', {\n cwd: gameEntry,\n ignore: []\n });\n\n const requireCalls = [];\n\n files.forEach(file => {\n const fullPath = path.join(gameEntry, file);\n const code = fs.readFileSync(fullPath, 'utf-8');\n\n let ast;\n try {\n ast = acorn.parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n } catch (e) {\n // 跳过无法解析的文件\n return;\n }\n\n walkAst(ast, node => {\n // require('xxx') 或 requireAsync('xxx')\n if (\n node.type === 'CallExpression' &&\n node.callee.type === 'Identifier' &&\n (node.callee.name === 'require' ||\n node.callee.name === 'requireAsync') &&\n node.arguments.length > 0 &&\n node.arguments[0].type === 'Literal'\n ) {\n const requirePath = node.arguments[0].value;\n let resolvedPath = null;\n\n if (requirePath.startsWith('.')) {\n resolvedPath = path.resolve(path.dirname(fullPath), requirePath);\n } else if (requirePath.startsWith('/')) {\n resolvedPath = path.resolve(gameEntry, '.' + requirePath);\n } else {\n for (const prefix of rootPrefixes) {\n if (requirePath.startsWith(prefix)) {\n resolvedPath = path.resolve(gameEntry, requirePath);\n break;\n }\n }\n }\n\n // 校验文件是否存在(支持 .js/.ts/.jsx/.tsx 后缀自动补全)\n if (resolvedPath && !fileExistsWithExtensions(resolvedPath)) {\n resolvedPath = null;\n }\n\n requireCalls.push({\n file: path.relative(gameEntry, fullPath),\n callee: node.callee.name,\n requirePath,\n resolvedPath: resolvedPath\n ? path.relative(gameEntry, resolvedPath)\n : '',\n });\n }\n });\n });\n\n const newRequireCalls = requireCalls.map(i => {\n /**\n * 基于 packages 来判断\n */\n let depModule = '';\n Object.keys(packages).forEach(pkg => {\n if (i.resolvedPath && i.resolvedPath.startsWith(packages[pkg].root)) {\n depModule = pkg;\n }\n });\n\n let curModule = '';\n Object.keys(packages).forEach(pkg => {\n if (i.file.startsWith(packages[pkg].root)) {\n curModule = pkg;\n }\n });\n return {\n ...i,\n curModule,\n depModule,\n };\n });\n\n // 只统计 JS/TS/JSX/TSX 文件依赖\n const exts = ['.js', '.ts', '.jsx', '.tsx'];\n const isJsLike = f => exts.some(ext => f.endsWith(ext));\n\n const result = newRequireCalls.reduce((acc, cur) => {\n if (!acc[cur.curModule]) {\n acc[cur.curModule] = {};\n }\n if (cur.curModule === cur.depModule) {\n return acc;\n }\n if (cur.resolvedPath && isJsLike(cur.resolvedPath)) {\n acc[cur.curModule] = {\n ...acc[cur.curModule],\n [cur.resolvedPath]: cur.depModule,\n };\n }\n return acc;\n }, {});\n return result;\n}\n\nfunction getRootPrefixes(gameEntry) {\n return fs\n .readdirSync(gameEntry)\n .filter(name => {\n const fullPath = path.join(gameEntry, name);\n return (\n fs.statSync(fullPath).isDirectory() &&\n !['node_modules', 'dist', 'build', 'output'].includes(name)\n );\n })\n .map(name => name + '/');\n}\n\nfunction walkAst(node, cb) {\n cb(node);\n for (let key in node) {\n if (node.hasOwnProperty(key)) {\n const child = node[key];\n if (Array.isArray(child)) {\n child.forEach(c => c && typeof c.type === 'string' && walkAst(c, cb));\n } else if (child && typeof child.type === 'string') {\n walkAst(child, cb);\n }\n }\n }\n}\n\n// 支持 .js/.ts/.jsx/.tsx 自动补全\nfunction fileExistsWithExtensions(filePath) {\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) return true;\n const exts = ['.js', '.ts', '.jsx', '.tsx'];\n for (const ext of exts) {\n if (fs.existsSync(filePath + ext) && fs.statSync(filePath + ext).isFile())\n return true;\n }\n return false;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport {\n GAME_MODULE_CONFIG_FILE_NAME,\n GAME_MAIN_PACKAGE_NAME,\n} from '@constants';\nimport { logger, ensureDirSync } from '@utils';\nimport MagicString, { Bundle } from 'magic-string';\n\nexport function pack({\n gameEntry,\n gameOutput,\n pkgName,\n allDeps,\n allMaps,\n pkgConfig,\n destRoot,\n}: {\n gameOutput: string;\n gameEntry: string;\n pkgName: string;\n allDeps: Record<string, string[]>;\n allMaps: Record<string, Record<string, string[]>>;\n pkgConfig: {\n main: string;\n root: string;\n };\n destRoot: string;\n}) {\n let startTime = Date.now();\n logger.info(`pack start,startTime:${startTime}`);\n const packMap = allMaps[pkgName];\n const moduleConfig = {\n main: pkgConfig.main,\n deps: allDeps[pkgName] || {},\n map: allMaps[pkgName],\n };\n\n ensureDirSync(destRoot);\n fs.writeFileSync(\n path.join(destRoot, GAME_MODULE_CONFIG_FILE_NAME),\n JSON.stringify(moduleConfig),\n );\n\n for (const packFileName in packMap) {\n const relPaths = packMap[packFileName];\n if (!Array.isArray(relPaths) || relPaths.length === 0) continue;\n\n const concat = new Bundle({ separator: '\\n' });\n for (const relPath of relPaths) {\n const absPath = path.join(gameEntry, relPath);\n if (!fs.existsSync(absPath)) continue;\n if (path.basename(absPath) === packFileName) continue;\n\n /**\n * 只匹配 js 文件\n */\n if (/\\.js$/i.test(relPath)) {\n const code = fs.readFileSync(absPath, 'utf-8');\n const fileId = relPath.replace(/\\\\/g, '/');\n const defineHeader = `define(\"game:${fileId}\", [\"require\", \"requireAsync\", \"module\", \"exports\", \"sandboxGlobal\"], function(require, requireAsync, module, exports, sandboxGlobal){\\nwith(sandboxGlobal){\\n`;\n const defineFooter = `\\n}\\n});\\n`;\n\n const fileMagic = new MagicString(code, { filename: fileId });\n const wrapped = new MagicString(defineHeader)\n .appendLeft(defineHeader.length, fileMagic.toString())\n .append(defineFooter);\n\n concat.addSource({ content: wrapped, filename: fileId });\n }\n }\n\n // 输出 pack 文件和 .map 到 output/包名/包root/\n const outFile = path.join(destRoot, path.basename(packFileName));\n fs.writeFileSync(\n outFile,\n concat.toString() + `\\n//# sourceMappingURL=${packFileName}.map`,\n );\n\n const map = concat.generateMap({\n hires: true,\n includeContent: true,\n file: packFileName,\n });\n fs.writeFileSync(outFile + '.map', map.toString());\n logger.info(`pack end,packName:${pkgName}`);\n }\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { ensureDirSync } from '@utils';\n\nexport function partition({\n pkgRoot,\n destRoot,\n packedFiles,\n gameEntry,\n gameOutput,\n skipDirs = [],\n isRoot = true\n}) {\n if (!fs.existsSync(pkgRoot)) return;\n const entries = fs.readdirSync(pkgRoot, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = path.join(pkgRoot, entry.name);\n const destPath = path.join(destRoot, entry.name);\n // 只在第一层判断是否跳过分包目录\n if (isRoot && entry.isDirectory() && skipDirs.includes(entry.name)) {\n continue; // 跳过分包目录\n }\n\n if (entry.isDirectory()) {\n partition({\n pkgRoot: srcPath,\n destRoot: destPath,\n gameOutput,\n packedFiles,\n gameEntry,\n skipDirs,\n isRoot: false, // 递归下去不再判断\n });\n } else {\n ensureDirSync(path.dirname(destPath));\n if (!packedFiles.includes(path.relative(gameEntry, srcPath))) {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { SUBPACKAGES_DIR_NAME } from '@constants';\nimport { logger, removeEmptyDir, removeSystemUseless } from '@utils';\nimport { setup } from './setup';\nimport { flattenMaps, collectMaps } from './collectMaps';\nimport { collectDeps } from './collectDeps';\nimport { pack } from './pack';\nimport { partition } from './partition';\nexport async function makePkgs({ gameEntry, gameOutput }) {\n let startTime = Date.now();\n removeSystemUseless(gameEntry);\n logger.info(`pack start,startTime:${startTime}`);\n const { packages } = await setup(gameEntry, gameOutput);\n const allDeps = collectDeps(gameEntry, packages);\n const allMaps = collectMaps(gameEntry, packages);\n const pkgOutput = {};\n\n for (const pkgName in allMaps) {\n logger.info(`开始基于游戏源代码打包,包名:${pkgName}`);\n let startTime = Date.now();\n const pkgConfig = packages[pkgName];\n const pkgRoot = path.join(gameEntry, pkgConfig.root);\n const destRoot = path.join(gameOutput, pkgName, pkgConfig.root);\n /**\n * 打包\n */\n pack({\n gameEntry,\n gameOutput,\n allDeps,\n allMaps,\n pkgName,\n pkgConfig,\n destRoot,\n });\n\n /**\n * 分包\n */\n partition({\n gameEntry,\n gameOutput,\n pkgRoot,\n destRoot,\n packedFiles: flattenMaps(allMaps),\n skipDirs: [SUBPACKAGES_DIR_NAME],\n });\n\n const pkgRootDir = path.join(gameOutput, pkgName);\n removeEmptyDir(pkgRootDir);\n logger.info(`基于游戏源代码打包分包完成,包名:${pkgName}`);\n logger.info(\n `基于游戏源代码打包分包耗时,包名:${pkgName},耗时:${\n Date.now() - startTime\n }ms`,\n );\n }\n // splitOdrPackages(gameOutput);\n logger.info(`pack end,duration:${Date.now() - startTime}ms`);\n\n return pkgOutput;\n}\n","import { logger } from '@utils';\nimport { PROJECT_SIZE_LIMIT, MAINPACKAGE_SIZE_LIMIT } from '@constants';\nimport { BuildConfig } from '@typings';\n\nimport { checkPkgs } from '../checkPkgs';\nimport { mergePkgs } from '../mergePkgs';\nimport { makePkgs } from '../makePkgs';\nimport { makeOdrPkgs } from '../odrPkgs';\n\nexport async function buildPkgs(config: BuildConfig): Promise<{\n isSuccess: boolean;\n errorMsg?: string;\n}> {\n const {\n entry: entryDir,\n output: outputDir,\n enableLog = true,\n enableCheck = true,\n enableDev = false,\n enableOdr = true,\n rules,\n } = config;\n let startTime = Date.now();\n logger.init(outputDir, enableLog);\n logger.info(`TTMG_PACK_VERSION: ${process.env.TTMG_PACK_VERSION}`);\n logger.info(`pack start, startTime:${startTime}`);\n try {\n /**\n * 校验\n */\n if (enableCheck) {\n await checkPkgs({\n entryDir,\n config: {\n projectSizeLimit: rules?.projectSizeLimit || PROJECT_SIZE_LIMIT,\n mainPackageSizeLimit:\n rules?.mainPackageSizeLimit || MAINPACKAGE_SIZE_LIMIT,\n subpackageSizeLimit: rules?.subpackageSizeLimit,\n },\n });\n }\n /**\n * 打包\n */\n await makePkgs({\n gameEntry: entryDir,\n gameOutput: outputDir,\n });\n\n /**\n * 分拆 odr 包\n */\n if (enableOdr) {\n await makeOdrPkgs(outputDir);\n }\n\n if (enableDev) {\n /**\n * 合并\n */\n mergePkgs(outputDir);\n }\n\n return {\n isSuccess: true,\n };\n } catch (error) {\n logger.error(`pack error:${error.message}`);\n return {\n isSuccess: false,\n errorMsg: error.message,\n };\n } finally {\n logger.info(`pack end:${Date.now() - startTime}ms`);\n }\n}\n","import { logger } from '@utils';\nimport { CheckConfig } from '@typings';\nimport { checkProject } from './checkProject';\nimport { checkMainPackage } from './checkMainpackage';\nimport { checkSubpackages } from './checkSubpackages';\n\nexport async function checkPkgs({\n entryDir,\n config,\n}: {\n entryDir: string;\n config: CheckConfig;\n}) {\n logger.info('开始校验项目');\n /**\n * 1. 校验项目\n */\n checkProject(entryDir, config);\n /**\n * 2. 校验主包\n */\n checkMainPackage(entryDir, config);\n /**\n * 3. 如果有,校验分包\n */\n checkSubpackages(entryDir, config);\n logger.info('校验项目完成');\n}\n","import path from 'path';\nimport fs from 'fs';\nimport {\n ensureDirSync,\n deleteNoJsFilesSync,\n logger,\n deleteJsFilesSync,\n} from '@utils';\n\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n ODR_ASSET_DIR_SUFFIX,\n ODR_CODE_DIR_SUFFIX,\n STTPKG_EXT,\n} from '@constants';\n\nexport async function makeOdrPkgs(outputDir: string) {\n let startTime = Date.now();\n logger.info(`makeOdrPkgs start, ${startTime}`);\n const outputPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n const config = JSON.parse(fs.readFileSync(outputPath, 'utf-8'));\n const packages = config.packages;\n for (const pkgName in packages) {\n /**\n * 将原本的分包配置,转换为 odr 的配置,\n * 将原本产物按照原路径,分别拆分成两个文件夹:js 部分 package_name_code,asset 部分 package_name_asset\n */\n const pkgOutput = path.join(outputDir, pkgName);\n const codeOutput = path.join(outputDir, `${pkgName}${ODR_CODE_DIR_SUFFIX}`);\n const assetOutput = path.join(\n outputDir,\n `${pkgName}${ODR_ASSET_DIR_SUFFIX}`,\n );\n ensureDirSync(codeOutput);\n ensureDirSync(assetOutput);\n fs.cpSync(pkgOutput, codeOutput, { recursive: true });\n fs.cpSync(pkgOutput, assetOutput, { recursive: true });\n deleteNoJsFilesSync(codeOutput);\n deleteJsFilesSync(assetOutput);\n\n /**\n * 写入配置\n */\n packages[`${pkgName}${ODR_CODE_DIR_SUFFIX}`] = {\n ...packages[pkgName],\n code_url: '',\n code_md5: '',\n output: `${pkgName}${ODR_CODE_DIR_SUFFIX}${STTPKG_EXT}`,\n };\n packages[`${pkgName}${ODR_ASSET_DIR_SUFFIX}`] = {\n ...packages[pkgName],\n asset_url: '',\n asset_md5: '',\n output: `${pkgName}${ODR_ASSET_DIR_SUFFIX}${STTPKG_EXT}`,\n };\n }\n fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));\n logger.info(`makeOdrPkgs end, ${Date.now() - startTime}ms`);\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { logger } from '@utils';\nimport { ProjectConfig } from '@typings';\nimport { GAME_PACK_CONFIG_FILE_NAME } from '@constants';\n\n/**\n * 将 packages 中的每个 package 下的文件内容合并到 outputDir 下,不保留 package name\n * @param outputDir 输出目录\n */\nexport function mergePkgs(outputDir: string) {\n logger.info('mergePkgs start');\n const gamePackConfigPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n let gamePackConfig: ProjectConfig;\n try {\n gamePackConfig = JSON.parse(fs.readFileSync(gamePackConfigPath, 'utf-8'));\n } catch (err) {\n logger.error(\n `读取配置文件失败: ${gamePackConfigPath}, err: ${err.message}`,\n );\n return;\n }\n\n const packages = gamePackConfig.packages;\n if (!packages || typeof packages !== 'object') {\n logger.error('配置文件中 packages 字段无效, 请检查配置');\n return;\n }\n\n for (const pkgName of Object.keys(packages)) {\n const pkgDir = path.join(outputDir, pkgName);\n if (!fs.existsSync(pkgDir)) {\n logger.warn(`package 目录不存在: ${pkgDir}`);\n continue;\n }\n\n const files = fs.readdirSync(pkgDir);\n for (const file of files) {\n const srcPath = path.join(pkgDir, file);\n const destPath = path.join(outputDir, file);\n\n try {\n const stat = fs.statSync(srcPath);\n if (stat.isFile()) {\n fs.copyFileSync(srcPath, destPath);\n } else if (stat.isDirectory()) {\n fs.cpSync(srcPath, destPath, { recursive: true });\n } else if (stat.isSymbolicLink()) {\n const linkTarget = fs.readlinkSync(srcPath);\n // 判断目标是否已存在符号链接\n if (fs.existsSync(destPath)) {\n fs.rmSync(destPath, { force: true });\n }\n fs.symlinkSync(\n linkTarget,\n destPath,\n stat.isDirectory() ? 'dir' : 'file',\n );\n }\n logger.info(`合并文件/目录: ${srcPath} -> ${destPath}`);\n } catch (err) {\n logger.error(`处理文件失败: ${srcPath}, err: ${err.message}`);\n }\n }\n\n // 删除 package 目录\n try {\n fs.rmSync(pkgDir, { recursive: true, force: true });\n logger.info(`已删除 package 目录: ${pkgDir}`);\n } catch (err) {\n logger.error(`删除 package 目录失败: ${pkgDir}, err: ${err.message}`);\n }\n }\n\n logger.info('mergePkgs 完成');\n}\n","/**\n * 合并请求拆包\n */\nimport fs from 'fs';\nimport path from 'path';\nimport { getDirSizeSync } from '@utils';\nimport { fetchAllGames, downloadAndSaveCodesSync } from './utils';\nimport { AVAILABLE_ODR_TAG_LIST, ONE_ODR_PKG_LIMIT } from '@constants';\n\nexport async function downloadOdrPkgs() {\n const TEMP_DIR = path.join(__dirname, 'temp');\n if (!fs.existsSync(TEMP_DIR)) fs.mkdirSync(TEMP_DIR);\n const games = await fetchAllGames();\n console.log('odr_games', games);\n downloadAndSaveCodesSync(games, TEMP_DIR);\n const gamesContentSize = {};\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameDir = path.join(TEMP_DIR, gameId);\n gamesContentSize[gameId] = getDirSizeSync(gameDir);\n }\n // ODR TAG 分配\n const odrTagGameMap = {};\n AVAILABLE_ODR_TAG_LIST.forEach(tag => {\n odrTagGameMap[tag] = [];\n });\n // 用于产出 TTMGODRConfig\n const TTMGODRConfig = {};\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameSize = gamesContentSize[gameId];\n if (gameSize > ONE_ODR_PKG_LIMIT) continue;\n let assignedTag = null;\n for (const odrTag of AVAILABLE_ODR_TAG_LIST) {\n const odrTagDir = path.join(TEMP_DIR, odrTag);\n if (!fs.existsSync(odrTagDir)) fs.mkdirSync(odrTagDir);\n const currentTagSize = odrTagGameMap[odrTag].reduce(\n (sum, gid) => sum + gamesContentSize[gid],\n 0,\n );\n if (currentTagSize + gameSize <= ONE_ODR_PKG_LIMIT) {\n // 复制资源\n const srcDir = path.join(TEMP_DIR, gameId);\n const destDir = path.join(odrTagDir, gameId);\n fs.cpSync(srcDir, destDir, { recursive: true });\n odrTagGameMap[odrTag].push(gameId);\n assignedTag = odrTag;\n break;\n }\n }\n if (!assignedTag) continue; // 没有分配成功就跳过\n // 构建 TTMGODRConfig\n\n TTMGODRConfig[gameId] = {\n tag: assignedTag,\n packages: {},\n };\n for (const packageName in packages) {\n const pkg = packages[packageName];\n console.log('TTMGODRConfig[gameId].packages', packageName, pkg);\n TTMGODRConfig[gameId].packages[packageName] = {\n root: pkg.root,\n main: pkg.main,\n // code_md5: pkg.code_md5,\n asset_md5: pkg.asset_md5,\n asset_url: pkg.asset_url,\n };\n }\n }\n // 写入 JSON 文件\n const configPath = path.join(TEMP_DIR, 'TTMG_ODR_CONFIG.json');\n fs.writeFileSync(configPath, JSON.stringify(TTMGODRConfig, null, 2), 'utf-8');\n console.log('TTMG_ODR_CONFIG.json 已生成:', configPath);\n}\n","\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { ODRPackages } from '@typings';\nimport { gameOdrPackages } from './mock';\n\nexport function fetchGames(params: { size: number; offset: number }): Promise<{\n data: Array<{\n id: string;\n packages: ODRPackages;\n }>;\n total: number;\n}> {\n const { size, offset } = params;\n const url = `https://game-odr.bytedance.net/odr/api/v1/games?size=${size}&offset=${offset}`;\n return fetch(url).then(res => res.json());\n}\n\n\n\nexport async function fetchAllGames(): Promise<Array<{\n id: string;\n packages: ODRPackages;\n }>> {\n return gameOdrPackages;\n const size = 100;\n let offset = 0;\n let total = 0;\n const games: Array<{\n id: string;\n packages: ODRPackages;\n }> = [];\n while (true) {\n const res = await fetchGames({ size, offset });\n games.push(...res.data);\n total = res.total;\n if (games.length >= total) {\n break;\n }\n offset += size;\n }\n return games;\n}\n\n\n// 同步下载并写入所有 code_url 文件\nexport function downloadAndSaveCodesSync(\n games: Array<{\n id: string;\n packages: ODRPackages;\n }>,\n tempDir: string,\n) {\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameDir = path.join(tempDir, gameId);\n if (!fs.existsSync(gameDir)) fs.mkdirSync(gameDir);\n\n for (const packageName in packages) {\n const packageInfo = packages[packageName];\n const { code_url } = packageInfo;\n // 同步下载\n const code = require('child_process')\n .execSync(`curl -s \"${code_url}\"`)\n .toString();\n console.log('downloadAndSaveCodesSync code', code_url);\n const fileName = `${packageName}.txt`;\n const filePath = path.join(gameDir, fileName);\n fs.writeFileSync(filePath, code);\n }\n }\n}","import { logger } from '@utils';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n ODR_ASSET_DIR_SUFFIX,\n ODR_CODE_DIR_SUFFIX,\n} from '@constants';\n\n/**\n * 将 packageConfig packages 中 分拆的包 配置迁移到 odr_packages 中\n */\n\nexport async function writeOdrConfig(outputDir: string) {\n logger.info('writeOdrPackagesConfig start');\n const outputPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n const config = JSON.parse(fs.readFileSync(outputPath, 'utf-8'));\n const packages = config.packages;\n const odrPackages = config.odr_packages || {};\n for (const pkgName in packages) {\n if (pkgName.endsWith(ODR_CODE_DIR_SUFFIX)) {\n /**\n * 找到 assets 对应的包\n */\n const pkgConfig = packages[pkgName];\n const relatedPkgName = pkgName.split(ODR_CODE_DIR_SUFFIX)[0];\n if (!odrPackages[relatedPkgName]) {\n odrPackages[relatedPkgName] = {};\n }\n odrPackages[relatedPkgName] = {\n ...odrPackages[relatedPkgName],\n root: pkgConfig.root,\n code_output: pkgConfig.output,\n code_md5: pkgConfig.md5,\n main: pkgConfig.main,\n };\n delete packages[pkgName];\n }\n if (pkgName.endsWith(ODR_ASSET_DIR_SUFFIX)) {\n const relatedPkgName = pkgName.split(ODR_ASSET_DIR_SUFFIX)[0];\n const pkgConfig = packages[pkgName];\n odrPackages[relatedPkgName] = {\n ...odrPackages[relatedPkgName],\n root: pkgConfig.root,\n asset_output: pkgConfig.output,\n asset_md5: pkgConfig.md5,\n };\n delete packages[pkgName];\n }\n }\n config.odr_packages = odrPackages;\n fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));\n logger.info('writeOdrPackagesConfig end');\n}\n"],"names":["ensureDirSync","dir","fs","existsSync","mkdirSync","recursive","logger","constructor","this","init","output","enableLog","winston","createLogger","level","format","combine","timestamp","json","transports","File","filename","path","join","Console","info","msg","error","warn","debug","log","setOutput","removeEmptyDir","statSync","isDirectory","isEmpty","files","readdirSync","file","fullPath","rmSync","GAME_PACK_CONFIG_FILE_NAME","GAME_ORIGIN_CONFIG_FILE_NAME","GAME_MAIN_PACKAGE_NAME","STTPKG_EXT","SUBPACKAGES_DIR_NAME","ODR_CODE_DIR_SUFFIX","ODR_ASSET_DIR_SUFFIX","ONE_ODR_PKG_LIMIT","AVAILABLE_ODR_TAG_LIST","getDirSizeSync","filterDirs","totalSize","entries","withFileTypes","entry","name","includes","isFile","size","deleteJsFilesSync","endsWith","unlinkSync","err","deleteNoJsFilesSync","uselessDirs","uselessFiles","odrPackages","__GAME__","code_url","asset_url","asset_md5","root","main","configBundle","gameBundle","mainBundle","resources","iceAndFire","pushstone","gameOdrPackages","id","Math","random","packages","checkProject","entryDir","config","projectSizeLimit","gameJsonPath","errMsg","Error","checkConfig","limit","gameSize","gameSizeMB","round","limitMB","checkProjectSize","checkMainPackage","context","mainPackageSizeLimit","gameJsPath","mainPkgSize","mainPkgSizeMB","checkMainPackageSize","checkSubpackages","subpackageSizeLimit","subpackages","JSON","parse","readFileSync","length","forEach","sub","subpackageEntryDir","subpackageRoot","subPkgName","subPkgDir","subPkgSize","sizeMB","checkSubPackageSize","async","setup","outputDir","gameJson","url","md5","configs","normalizeName","String","replace","normalizeRoot","trim","str","test","map","idx","indexOf","slice","transformSubPackages","result","Object","keys","pkg","pkgPath","writeFileSync","stringify","flattenMaps","allMaps","list","values","arr","push","collectAllJsFiles","exts","excludeDirs","concat","some","ext","collectDeps","gameEntry","rootPrefixes","filter","getRootPrefixes","glob","sync","cwd","ignore","requireCalls","code","ast","acorn","ecmaVersion","sourceType","e","walkAst","node","type","callee","arguments","requirePath","value","resolvedPath","startsWith","resolve","dirname","prefix","filePath","fileExistsWithExtensions","relative","newRequireCalls","i","depModule","curModule","assign","reduce","acc","cur","f","cb","key","hasOwnProperty","child","Array","isArray","c","pack","gameOutput","pkgName","allDeps","pkgConfig","destRoot","startTime","Date","now","packMap","moduleConfig","deps","packFileName","relPaths","Bundle","separator","relPath","absPath","basename","fileId","defineHeader","defineFooter","fileMagic","MagicString","wrapped","appendLeft","toString","append","addSource","content","outFile","generateMap","hires","includeContent","partition","pkgRoot","packedFiles","skipDirs","isRoot","srcPath","destPath","copyFileSync","makePkgs","removeUselessDirs","console","stat","force","removeSystemUseless","subRoots","split","sep","Boolean","uniqueSubRoots","from","Set","srcRoot","jsFiles","packNameRoot","collectMaps","enableCheck","enableDev","enableOdr","rules","checkPkgs","outputPath","pkgOutput","codeOutput","assetOutput","cpSync","code_md5","makeOdrPkgs","gamePackConfigPath","gamePackConfig","message","pkgDir","isSymbolicLink","linkTarget","readlinkSync","symlinkSync","mergePkgs","isSuccess","errorMsg","TEMP_DIR","__dirname","games","fetchAllGames","tempDir","game","gameId","gameDir","packageName","packageInfo","require","execSync","fileName","downloadAndSaveCodesSync","gamesContentSize","odrTagGameMap","tag","TTMGODRConfig","assignedTag","odrTag","odrTagDir","sum","gid","srcDir","destDir","configPath","odr_packages","relatedPkgName","code_output","asset_output"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/ensureDirSync.ts","../src/utils/logger.ts","../src/utils/removeEmptyDir.ts","../src/constants/index.ts","../src/utils/getDirSizeSync.ts","../src/utils/deleteJsFilesSync.ts","../src/utils/deleteNoJsFilesSync.ts","../src/utils/removeSystemUseless.ts","../src/libs/odrPkgs/mock.ts","../src/libs/checkPkgs/checkProject.ts","../src/libs/checkPkgs/checkMainpackage.ts","../src/libs/checkPkgs/checkSubpackages.ts","../src/libs/checkPkgs/index.ts","../src/libs/makePkgs/setup.ts","../src/libs/makePkgs/collectMaps.ts","../src/libs/makePkgs/collectDeps.ts","../src/libs/makePkgs/pack.ts","../src/libs/makePkgs/partition.ts","../src/libs/makePkgs/index.ts","../src/libs/buildPkgs/index.ts","../src/libs/odrPkgs/makeOdrPkgs.ts","../src/libs/debugPkgs/index.ts","../src/libs/mergePkgs/index.ts","../src/libs/odrPkgs/downloadOdrPkgs.ts","../src/libs/odrPkgs/utils.ts","../src/libs/odrPkgs/writeOdrConfig.ts"],"sourcesContent":["import fs from 'fs';\nexport function ensureDirSync(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n","import winston from 'winston';\nimport path from 'path';\n\nclass Logger {\n logger: winston.Logger;\n enableLog: boolean;\n output: any;\n constructor() {\n this.logger = null;\n }\n init(output: string, enableLog = true) {\n this.enableLog = enableLog;\n this.logger = winston.createLogger({\n level: 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.json(), // 输出为 JSON 格式\n ),\n transports: [\n new winston.transports.File({\n filename: path.join(output, 'pack.log'),\n }),\n new winston.transports.Console(),\n ],\n });\n }\n info(msg: string) {\n if (this.enableLog) {\n this.logger.info(msg);\n }\n }\n error(msg) {\n if (this.enableLog) {\n this.logger.error(msg);\n }\n }\n warn(msg) {\n if (this.enableLog) {\n this.logger.warn(msg);\n }\n }\n debug(msg) {\n if (this.enableLog) {\n this.logger.debug(msg);\n }\n }\n log(msg) {\n this.logger.info(msg);\n }\n setOutput(output) {\n this.output = output;\n }\n}\n\nexport const logger = new Logger();\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * 移除指定目录下所有空文件夹(递归)\n * @param {string} dir 目标目录\n * @returns {boolean} 返回当前目录是否已被删除(即是否为空)\n */\nexport function removeEmptyDir(dir) {\n if (!fs.existsSync(dir)) return false;\n if (!fs.statSync(dir).isDirectory()) return false;\n\n let isEmpty = true;\n const files = fs.readdirSync(dir);\n for (const file of files) {\n const fullPath = path.join(dir, file);\n if (fs.statSync(fullPath).isDirectory()) {\n // 递归处理子目录\n const childIsEmpty = removeEmptyDir(fullPath);\n if (!childIsEmpty) isEmpty = false;\n } else {\n // 有文件,当前目录不为空\n isEmpty = false;\n }\n }\n\n // 如果当前目录为空,删除它\n if (isEmpty) {\n fs.rmSync(dir, { recursive: true });\n return true;\n }\n return false;\n}\n\n","export const GAME_PACK_CONFIG_FILE_NAME = 'packageConfig.json';\nexport const GAME_ORIGIN_CONFIG_FILE_NAME = 'game.json';\nexport const GAME_MODULE_CONFIG_FILE_NAME = 'moduleConfig.json';\nexport const GAME_OUTPUT_CONFIG_FILE_NAME = 'output.json';\nexport const GAME_MAIN_PACKAGE_NAME = '__GAME__';\nexport const TTPKG_TAG = 'TPKG';\nexport const STTPKG_TAG = 'SPKG';\nexport const TTPKG_VERSION = 2;\nexport const ARK_KEY_LEN = 32;\nexport const ARK_INT_LEN = 4;\nexport const UNIT32_LEN = 4;\nexport const UINT16_LEN = 2;\nexport const STTPKG_VERSION = 1;\nexport const ZSTD_COMPRESS_LEVEL = 19;\nexport const ROLL_FILE_EXT = [\n '.js',\n '.json',\n '.wxml',\n '.ttml',\n '.wxss',\n '.ttss',\n];\nexport const EXT = '';\nexport const BROTLI_COMPRESS_TYPE = 1;\nexport const ZSTD_COMPRESS_TYPE = 3;\n\nexport const STTPKG_EXT = '.txt';\n\nexport const SUBPACKAGES_DIR_NAME = 'subpackages';\n\nexport const ODR_CODE_DIR_SUFFIX = '_code';\n\nexport const ODR_ASSET_DIR_SUFFIX = '_asset';\n\n// 60MB const ONE_ODR_PKG_LIMIT = 1024 * 1024;\nexport const ONE_ODR_PKG_LIMIT = 1024 * 1024 * 60;\n\nexport const AVAILABLE_ODR_TAG_LIST = [\n 'ttmg_odr_tag_1',\n 'ttmg_odr_tag_2',\n 'ttmg_odr_tag_3',\n];\n\nexport const PROJECT_SIZE_LIMIT = 30 * 1024 * 1024;\n\n\nexport const MAINPACKAGE_SIZE_LIMIT = 4 * 1024 * 1024;\n","import fs from 'fs';\nimport path from 'path';\n// 递归统计目录下所有文件的大小,支持我过滤某些文件夹\nexport function getDirSizeSync(dir: string, filterDirs: string[] = []) {\n let totalSize = 0;\n if (!fs.existsSync(dir)) return 0;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!filterDirs.includes(entry.name)) {\n totalSize += getDirSizeSync(fullPath, filterDirs);\n }\n } else if (entry.isFile()) {\n totalSize += fs.statSync(fullPath).size;\n }\n }\n return totalSize;\n}\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * 同步删除指定目录及其子目录下所有 .js 文件\n * @param {string} dir 目标目录路径\n */\nexport function deleteJsFilesSync(dir) {\n // 读取目录内容\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // 递归处理子目录\n deleteJsFilesSync(fullPath);\n } else if (\n entry.isFile() &&\n (fullPath.endsWith('.js') || fullPath.endsWith('.js.map'))\n ) {\n try {\n fs.unlinkSync(fullPath);\n } catch (err) {}\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport function deleteNoJsFilesSync(dir) {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // 递归处理子目录\n deleteNoJsFilesSync(fullPath);\n } else if (\n entry.isFile() &&\n !(fullPath.endsWith('.js') || fullPath.endsWith('.js.map'))\n ) {\n try {\n fs.unlinkSync(fullPath);\n } catch (err) {}\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nconst uselessDirs = ['node_modules', '__MACOSX'];\nconst uselessFiles = ['.DS_Store', 'Thumbs.db'];\n\nexport function removeSystemUseless(gameEntry: string) {\n /**\n * 递归删除目录下的无用文件夹和无用文件\n */\n function removeUselessDirs(dir: string) {\n let files: string[];\n try {\n files = fs.readdirSync(dir);\n } catch (err) {\n // 目录不可访问,跳过\n console.warn(`无法访问目录: ${dir}`, err);\n return;\n }\n files.forEach(file => {\n const filePath = path.join(dir, file);\n try {\n const stat = fs.statSync(filePath);\n if (stat.isDirectory()) {\n if (uselessDirs.includes(file)) {\n // 删除无用目录\n fs.rmSync(filePath, { recursive: true, force: true });\n console.log(`已删除无用目录: ${filePath}`);\n } else {\n // 递归处理子目录\n removeUselessDirs(filePath);\n }\n } else if (stat.isFile()) {\n if (uselessFiles.includes(file)) {\n // 删除无用文件\n fs.rmSync(filePath, { force: true });\n console.log(`已删除无用文件: ${filePath}`);\n }\n }\n } catch (err) {\n // 某个文件/目录不可访问,跳过\n console.warn(`无法处理: ${filePath}`, err);\n }\n });\n }\n removeUselessDirs(gameEntry);\n}\n","interface ODRPackage {\n // md5: string;\n root: string;\n main: string;\n code_url: string;\n // code_md5: string;\n asset_md5: string;\n asset_url: string;\n}\n\ntype ODRPackages = Record<string, ODRPackage>;\nconst odrPackages: ODRPackages = {\n __GAME__: {\n // md5: '6eac4e8a7a7f54a20bcca6c67d71ebad',\n code_url: 'https://connect.tiktok-minis.com/test/__GAME___code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/__GAME___asset.txt',\n asset_md5: '8e3cc2ebd5536e9183b93fda34c1e7f4',\n root: '',\n main: 'game.js',\n },\n configBundle: {\n // md5: '575a0a1f0191e682fc27af897515740b',\n root: 'subpackages/configBundle',\n main: 'subpackages/configBundle/game.js',\n asset_md5: 'f624a1b37fb35d4dfb1975105a51ebd4',\n code_url: 'https://connect.tiktok-minis.com/test/configBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/configBundle_asset.txt',\n },\n gameBundle: {\n // md5: '02e5d043be3156cfe2553e8af0f1b3d3',\n main: 'subpackages/gameBundle/game.js',\n root: 'subpackages/gameBundle',\n asset_md5: 'fcc9f686bbc8d6f983263e7132598b26',\n code_url: 'https://connect.tiktok-minis.com/test/gameBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/gameBundle_asset.txt',\n },\n mainBundle: {\n // md5: 'f28aae73fbb0cc3b8876c2773a1c5789',\n main: 'subpackages/mainBundle/game.js',\n root: 'subpackages/mainBundle',\n asset_md5: '36b9674d48f9fbb0de6e8f48b194aebc',\n code_url: 'https://connect.tiktok-minis.com/test/mainBundle_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/mainBundle_asset.txt',\n },\n resources: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/resources',\n main: 'subpackages/resources/game.js',\n asset_md5: '1c4608d7690750f7bd5c00663013fc70',\n code_url: 'https://connect.tiktok-minis.com/test/resources_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/resources_asset.txt',\n },\n iceAndFire: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/iceAndFire',\n main: 'subpackages/iceAndFire/game.js',\n asset_md5: 'c7fd8e8506dd59725269027a52e2cae4',\n code_url: 'https://connect.tiktok-minis.com/test/iceAndFire_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/iceAndFire_asset.txt',\n },\n pushstone: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/pushstone',\n main: 'subpackages/pushstone/game.js',\n asset_md5: 'f5061dba94ad53e1f578325a7cb26a01',\n code_url: 'https://connect.tiktok-minis.com/test/pushstone_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/pushstone_asset.txt',\n },\n main: {\n // md5: '238c98f80a43d0603ac4a371c1b6184b',\n root: 'subpackages/main',\n main: 'subpackages/main/game.js',\n asset_md5: 'aece2f69cc168d7cefb248e8574c3371',\n code_url: 'https://connect.tiktok-minis.com/test/main_code.txt',\n asset_url: 'https://connect.tiktok-minis.com/test/main_asset.txt',\n },\n};\n\nexport const gameOdrPackages = [\n { id: `${Math.random() * 100000000000000000}`, packages: odrPackages },\n { id: `${Math.random() * 100000000000000000}`, packages: odrPackages },\n];\n","import path from 'path';\nimport fs from 'fs';\nimport { CheckConfig } from '@typings';\nimport { GAME_ORIGIN_CONFIG_FILE_NAME } from '@constants';\nimport { logger, getDirSizeSync } from '@utils';\n\nexport function checkConfig(entryDir: string) {\n logger.info('start check config');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n if (!fs.existsSync(gameJsonPath)) {\n const errMsg =\n 'can not find game.json in game source code, please check it';\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n logger.info('check config successfully');\n }\n}\n\n/**\n * 检查游戏大小是否超出限制\n * @param param0\n * @returns\n */\n\nexport function checkProjectSize(entryDir: string, limit: number) {\n logger.info('start check project size');\n const gameSize = getDirSizeSync(entryDir, []);\n const gameSizeMB = Math.round(gameSize / (1024 * 1024));\n const limitMB = Math.round(limit / (1024 * 1024));\n if (gameSize > limit) {\n const errMsg = `Game size ${gameSizeMB}MB, must not exceed ${limitMB}MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 游戏大小检查通过\n */\n logger.info(`Game size ${gameSizeMB}MB, check successfully!`);\n logger.info('Game size check successfully!');\n }\n}\n\nexport function checkProject(\n entryDir: string,\n config: Pick<CheckConfig, 'projectSizeLimit'>\n) {\n logger.info('start check project');\n const projectSizeLimit = config?.projectSizeLimit;\n checkConfig(entryDir);\n checkProjectSize(entryDir, projectSizeLimit);\n logger.info('check project successfully');\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\nimport { logger, getDirSizeSync } from '@utils';\n/**\n * 检查主包大小是否超出限制\n * @param param0\n * @returns\n */\nexport function checkMainPackageSize({\n entryDir,\n limit,\n}: {\n entryDir: string;\n limit: number;\n}) {\n logger.info('start check main package size');\n const mainPkgSize = getDirSizeSync(entryDir, ['subpackages']);\n const mainPkgSizeMB = Math.round(mainPkgSize / (1024 * 1024));\n const limitMB = Math.round(limit / (1024 * 1024));\n if (mainPkgSize > limit) {\n const errMsg = `Main package size ${mainPkgSizeMB}MB, must not exceed ${limitMB}MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 主包大小检查通过\n */\n logger.info(`Main package size ${mainPkgSizeMB}MB, check successfully!`);\n }\n}\n\nexport function checkMainPackage(\n entryDir: string,\n config: {\n mainPackageSizeLimit: number;\n },\n) {\n logger.info('start check main package');\n const { mainPackageSizeLimit } = config;\n /**\n * 检查 game.js 是否存在\n */\n\n logger.info('check game.js');\n const gameJsPath = path.join(entryDir, 'game.js');\n if (!fs.existsSync(gameJsPath)) {\n const errMsg = 'game.js must exist in main package!';\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n logger.info('check game.js successfully');\n\n /**\n * 检查主包大小是否超出限制\n */\n checkMainPackageSize({\n entryDir,\n limit: mainPackageSizeLimit,\n });\n logger.info('check main package successfully');\n}\n","import { logger, getDirSizeSync } from '@utils';\nimport { CheckConfig } from '@typings';\nimport { GAME_ORIGIN_CONFIG_FILE_NAME } from '@constants';\n\nimport path from 'path';\nimport fs from 'fs';\n\nexport function checkSubpackages(\n entryDir: string,\n config?: Pick<CheckConfig, 'subpackageSizeLimit'>,\n) {\n const { subpackageSizeLimit } = config || {};\n /**\n * 开始校验 subpackages 配置是否有效\n */\n logger.info('start check subpackages in game.json');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));\n const subpackages: Array<{\n name: string;\n root: string;\n }> = gameJson.subpackages || [];\n if (!subpackages?.length) {\n logger.info('subpackages is empty');\n } else {\n subpackages.forEach(sub => {\n /**\n * 校验 subpackage 配置是否为空\n */\n if (!sub.name || !sub.root) {\n const errMsg =\n 'The subpackages configuration in game.json is invalid: the root or name field in one or more subpackages is empty. Please ensure that all subpackages have non-empty root and name values.';\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n /**\n * 校验 subpackage 配置是否有效\n */\n const subpackageEntryDir = path.join(entryDir, sub.root);\n // 检查是文件或者文件夹是否存在\n if (!fs.existsSync(subpackageEntryDir)) {\n const errMsg = `The subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} entry dir, please check it`;\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n const subpackageRoot = sub.root;\n if (!fs.existsSync(path.join(entryDir, subpackageRoot))) {\n const errMsg = `The subpackages configuration in game.json is invalid: can not find subpackage ${sub.name} root, please check it`;\n logger.error(errMsg);\n throw new Error(errMsg);\n }\n /**\n * 校验 subpackage 包大小\n */\n\n if (subpackageSizeLimit) {\n checkSubPackageSize({\n entryDir,\n subPkgName: sub.name,\n limit: subpackageSizeLimit,\n });\n }\n });\n }\n logger.info('check subpackages in game.json successfully');\n}\n\n/**\n * 检查子包大小是否超出限制\n * @param param0\n * @returns\n */\n\nfunction checkSubPackageSize({\n entryDir,\n subPkgName,\n limit,\n}: {\n entryDir: string;\n subPkgName: string;\n limit: number;\n}) {\n const subPkgDir = path.join(entryDir, 'subpackages', subPkgName);\n const subPkgSize = getDirSizeSync(subPkgDir, []);\n const sizeMB = Math.round(subPkgSize / (1024 * 1024));\n if (sizeMB > limit) {\n const errMsg = `${subPkgName} Sub package size ${sizeMB}MB, must not exceed ${\n limit / (1024 * 1024)\n }MB`;\n logger.error(errMsg);\n throw new Error(errMsg);\n } else {\n /**\n * 子包大小检查通过\n */\n logger.info(\n `${subPkgName} Sub package size ${sizeMB}MB, check successfully!`,\n );\n }\n}\n","import { logger } from '@utils';\nimport { CheckConfig } from '@typings';\nimport { checkProject } from './checkProject';\nimport { checkMainPackage } from './checkMainpackage';\nimport { checkSubpackages } from './checkSubpackages';\n\nexport async function checkPkgs({\n entryDir,\n config,\n}: {\n entryDir: string;\n config: CheckConfig;\n}) {\n logger.info('开始校验项目');\n /**\n * 1. 校验项目\n */\n checkProject(entryDir, config);\n /**\n * 2. 校验主包\n */\n checkMainPackage(entryDir, config);\n /**\n * 3. 如果有,校验分包\n */\n checkSubpackages(entryDir, config);\n logger.info('校验项目完成');\n}\n","import fs from 'fs';\nimport path from 'path';\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n GAME_ORIGIN_CONFIG_FILE_NAME,\n GAME_MAIN_PACKAGE_NAME,\n STTPKG_EXT,\n SUBPACKAGES_DIR_NAME,\n} from '@constants';\n\nimport { logger } from '@utils';\n\n\n\nexport async function setup(entryDir: string, outputDir: string) {\n logger.info('开始基于源代码中的 game.json 生成 packageConfig.json');\n const gameJsonPath = path.join(entryDir, GAME_ORIGIN_CONFIG_FILE_NAME);\n const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));\n\n const packages = {};\n // 主包\n packages[GAME_MAIN_PACKAGE_NAME] = {\n url: '',\n md5: '',\n root: '',\n main: 'game.js',\n output: `${GAME_MAIN_PACKAGE_NAME}${STTPKG_EXT}`,\n };\n\n transformSubPackages(gameJson.subpackages).forEach(sub => {\n // root 是目录\n packages[sub.root] = {\n url: '',\n md5: '',\n root: `${SUBPACKAGES_DIR_NAME}/${sub.root}`,\n main: `${SUBPACKAGES_DIR_NAME}/${sub.main}`,\n output: `${sub.root}${STTPKG_EXT}`,\n };\n });\n\n const result = {\n packages,\n };\n /**\n * 校验子包的 main 文件是否存在\n */\n Object.keys(packages).forEach(pkg => {\n const pkgPath = path.join(entryDir, packages[pkg].main);\n if (!fs.existsSync(pkgPath)) {\n logger.error(\n `开发者源代码包中的子包 ${pkg} 中的 main 文件 ${packages[pkg].main} 不存在`,\n );\n\n throw new Error(\n `开发者源代码包中的子包 ${pkg} 中的 main 文件 ${packages[pkg].main} 不存在`,\n );\n }\n });\n\n if (fs.existsSync(outputDir)) {\n fs.rmSync(outputDir, { recursive: true });\n }\n fs.mkdirSync(outputDir);\n fs.writeFileSync(\n path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME),\n JSON.stringify(result, null, 2),\n );\n logger.info('基于源代码中的 game.json 生成 packageConfig.json 成功');\n return result;\n}\n\nfunction transformSubPackages(configs) {\n if (!configs || configs.length === 0) {\n return [];\n }\n function normalizeName(name) {\n return String(name).replace(/^\\/+|\\/+$/g, '');\n }\n\n function normalizeRoot(root) {\n return String(root).trim().replace(/^\\/+/, '');\n }\n\n function isDirectory(str) {\n // 以 / 结尾,或没有 .js 结尾且没有 . 号\n return str.endsWith('/') || !/\\.[a-zA-Z0-9]+$/.test(str);\n }\n\n return configs.map(config => {\n const name = normalizeName(config.name);\n let root = normalizeRoot(config.root);\n\n // 找到 root 中 name 的第一次出现\n const idx = root.indexOf(name);\n\n if (idx !== -1) {\n // 保留从 name 开始的部分\n root = root.slice(idx);\n } else {\n // root 里没有 name,直接用 name 拼接\n root = name + (isDirectory(root) ? '/game.js' : '/' + root);\n }\n\n // 如果 root 现在是目录,补全 game.js\n if (isDirectory(root)) {\n root = root.replace(/\\/+$/, '') + '/game.js';\n }\n\n return { main: root, root: name };\n });\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { logger } from '@utils';\n\nexport function flattenMaps(allMaps) {\n const list = [];\n Object.values(allMaps).forEach(map => {\n Object.values(map).forEach(arr => {\n list.push(...arr);\n });\n });\n return list;\n}\n\n// 递归收集 JS 文件,但可排除指定目录\nfunction collectAllJsFiles(\n dir,\n exts = ['.js', '.ts', '.jsx', '.tsx'],\n excludeDirs = [],\n) {\n let files = [];\n if (!fs.existsSync(dir)) return files;\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (excludeDirs.includes(entry.name)) continue; // 跳过排除目录\n files = files.concat(collectAllJsFiles(fullPath, exts, [])); // 只排除一级\n } else if (exts.some(ext => entry.name.endsWith(ext))) {\n files.push(fullPath);\n }\n }\n return files;\n}\n\n// 构建每个包的 map\nexport function collectMaps(\n entryDir,\n packages: Record<string, { root: string }>,\n) {\n logger.info('开始基于游戏源代码收集分包中的 JS 文件');\n const result = {};\n // 1. 先收集所有分包根目录名(如 subpackages/level1、subpackages/level2)\n const subRoots = Object.values(packages)\n .filter(pkg => pkg.root && pkg.root !== '')\n .map(pkg => pkg.root.split(path.sep)[0]) // 只提取一级目录名\n .filter(Boolean);\n const uniqueSubRoots = Array.from(new Set(subRoots));\n\n for (const pkgName in packages) {\n const pkg = packages[pkgName];\n let srcRoot;\n let jsFiles;\n if (pkgName === '__GAME__') {\n // 主包:只收集 entryDir 下非分包目录\n jsFiles = collectAllJsFiles(\n entryDir,\n ['.js', '.ts', '.jsx', '.tsx'],\n uniqueSubRoots,\n );\n srcRoot = entryDir;\n } else {\n // 分包:只收集自己目录\n srcRoot = path.join(entryDir, pkg.root);\n jsFiles = collectAllJsFiles(srcRoot);\n }\n // 以包的 srcRoot 为基准生成相对路径\n const list = [];\n jsFiles.forEach(absPath => {\n list.push(path.relative(entryDir, absPath).replace(/\\\\/g, '/'));\n });\n const packNameRoot = packages[pkgName].root;\n result[pkgName] = {\n [packNameRoot ? `${packNameRoot}/game.pack.js` : 'game.pack.js']: list,\n };\n }\n logger.info('基于游戏源代码收集分包中的 JS 文件完成');\n return result;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport acorn from 'acorn';\nimport glob from 'glob';\n\nexport function collectDeps(gameEntry, packages) {\n // 自动扫描 game 目录下的一级文件夹作为根前缀\n const rootPrefixes = getRootPrefixes(gameEntry);\n\n // 查找所有 JS 文件\n const files = glob.sync('**/*.js', {\n cwd: gameEntry,\n ignore: []\n });\n\n const requireCalls = [];\n\n files.forEach(file => {\n const fullPath = path.join(gameEntry, file);\n const code = fs.readFileSync(fullPath, 'utf-8');\n\n let ast;\n try {\n ast = acorn.parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n } catch (e) {\n // 跳过无法解析的文件\n return;\n }\n\n walkAst(ast, node => {\n // require('xxx') 或 requireAsync('xxx')\n if (\n node.type === 'CallExpression' &&\n node.callee.type === 'Identifier' &&\n (node.callee.name === 'require' ||\n node.callee.name === 'requireAsync') &&\n node.arguments.length > 0 &&\n node.arguments[0].type === 'Literal'\n ) {\n const requirePath = node.arguments[0].value;\n let resolvedPath = null;\n\n if (requirePath.startsWith('.')) {\n resolvedPath = path.resolve(path.dirname(fullPath), requirePath);\n } else if (requirePath.startsWith('/')) {\n resolvedPath = path.resolve(gameEntry, '.' + requirePath);\n } else {\n for (const prefix of rootPrefixes) {\n if (requirePath.startsWith(prefix)) {\n resolvedPath = path.resolve(gameEntry, requirePath);\n break;\n }\n }\n }\n\n // 校验文件是否存在(支持 .js/.ts/.jsx/.tsx 后缀自动补全)\n if (resolvedPath && !fileExistsWithExtensions(resolvedPath)) {\n resolvedPath = null;\n }\n\n requireCalls.push({\n file: path.relative(gameEntry, fullPath),\n callee: node.callee.name,\n requirePath,\n resolvedPath: resolvedPath\n ? path.relative(gameEntry, resolvedPath)\n : '',\n });\n }\n });\n });\n\n const newRequireCalls = requireCalls.map(i => {\n /**\n * 基于 packages 来判断\n */\n let depModule = '';\n Object.keys(packages).forEach(pkg => {\n if (i.resolvedPath && i.resolvedPath.startsWith(packages[pkg].root)) {\n depModule = pkg;\n }\n });\n\n let curModule = '';\n Object.keys(packages).forEach(pkg => {\n if (i.file.startsWith(packages[pkg].root)) {\n curModule = pkg;\n }\n });\n return {\n ...i,\n curModule,\n depModule,\n };\n });\n\n // 只统计 JS/TS/JSX/TSX 文件依赖\n const exts = ['.js', '.ts', '.jsx', '.tsx'];\n const isJsLike = f => exts.some(ext => f.endsWith(ext));\n\n const result = newRequireCalls.reduce((acc, cur) => {\n if (!acc[cur.curModule]) {\n acc[cur.curModule] = {};\n }\n if (cur.curModule === cur.depModule) {\n return acc;\n }\n if (cur.resolvedPath && isJsLike(cur.resolvedPath)) {\n acc[cur.curModule] = {\n ...acc[cur.curModule],\n [cur.resolvedPath]: cur.depModule,\n };\n }\n return acc;\n }, {});\n return result;\n}\n\nfunction getRootPrefixes(gameEntry) {\n return fs\n .readdirSync(gameEntry)\n .filter(name => {\n const fullPath = path.join(gameEntry, name);\n return (\n fs.statSync(fullPath).isDirectory() &&\n !['node_modules', 'dist', 'build', 'output'].includes(name)\n );\n })\n .map(name => name + '/');\n}\n\nfunction walkAst(node, cb) {\n cb(node);\n for (let key in node) {\n if (node.hasOwnProperty(key)) {\n const child = node[key];\n if (Array.isArray(child)) {\n child.forEach(c => c && typeof c.type === 'string' && walkAst(c, cb));\n } else if (child && typeof child.type === 'string') {\n walkAst(child, cb);\n }\n }\n }\n}\n\n// 支持 .js/.ts/.jsx/.tsx 自动补全\nfunction fileExistsWithExtensions(filePath) {\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) return true;\n const exts = ['.js', '.ts', '.jsx', '.tsx'];\n for (const ext of exts) {\n if (fs.existsSync(filePath + ext) && fs.statSync(filePath + ext).isFile())\n return true;\n }\n return false;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport {\n GAME_MODULE_CONFIG_FILE_NAME,\n GAME_MAIN_PACKAGE_NAME,\n} from '@constants';\nimport { logger, ensureDirSync } from '@utils';\nimport MagicString, { Bundle } from 'magic-string';\n\nexport function pack({\n gameEntry,\n gameOutput,\n pkgName,\n allDeps,\n allMaps,\n pkgConfig,\n destRoot,\n}: {\n gameOutput: string;\n gameEntry: string;\n pkgName: string;\n allDeps: Record<string, string[]>;\n allMaps: Record<string, Record<string, string[]>>;\n pkgConfig: {\n main: string;\n root: string;\n };\n destRoot: string;\n}) {\n let startTime = Date.now();\n logger.info(`pack start,startTime:${startTime}`);\n const packMap = allMaps[pkgName];\n const moduleConfig = {\n main: pkgConfig.main,\n deps: allDeps[pkgName] || {},\n map: allMaps[pkgName],\n };\n\n ensureDirSync(destRoot);\n fs.writeFileSync(\n path.join(destRoot, GAME_MODULE_CONFIG_FILE_NAME),\n JSON.stringify(moduleConfig),\n );\n\n for (const packFileName in packMap) {\n const relPaths = packMap[packFileName];\n if (!Array.isArray(relPaths) || relPaths.length === 0) continue;\n\n const concat = new Bundle({ separator: '\\n' });\n for (const relPath of relPaths) {\n const absPath = path.join(gameEntry, relPath);\n if (!fs.existsSync(absPath)) continue;\n if (path.basename(absPath) === packFileName) continue;\n\n /**\n * 只匹配 js 文件\n */\n if (/\\.js$/i.test(relPath)) {\n const code = fs.readFileSync(absPath, 'utf-8');\n const fileId = relPath.replace(/\\\\/g, '/');\n const defineHeader = `define(\"game:${fileId}\", [\"require\", \"requireAsync\", \"module\", \"exports\", \"sandboxGlobal\"], function(require, requireAsync, module, exports, sandboxGlobal){\\nwith(sandboxGlobal){\\n`;\n const defineFooter = `\\n}\\n});\\n`;\n\n const fileMagic = new MagicString(code, { filename: fileId });\n const wrapped = new MagicString(defineHeader)\n .appendLeft(defineHeader.length, fileMagic.toString())\n .append(defineFooter);\n\n concat.addSource({ content: wrapped, filename: fileId });\n }\n }\n\n // 输出 pack 文件和 .map 到 output/包名/包root/\n const outFile = path.join(destRoot, path.basename(packFileName));\n fs.writeFileSync(\n outFile,\n concat.toString() + `\\n//# sourceMappingURL=${packFileName}.map`,\n );\n\n const map = concat.generateMap({\n hires: true,\n includeContent: true,\n file: packFileName,\n });\n fs.writeFileSync(outFile + '.map', map.toString());\n logger.info(`pack end,packName:${pkgName}`);\n }\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { ensureDirSync } from '@utils';\n\nexport function partition({\n pkgRoot,\n destRoot,\n packedFiles,\n gameEntry,\n gameOutput,\n skipDirs = [],\n isRoot = true\n}) {\n if (!fs.existsSync(pkgRoot)) return;\n const entries = fs.readdirSync(pkgRoot, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = path.join(pkgRoot, entry.name);\n const destPath = path.join(destRoot, entry.name);\n // 只在第一层判断是否跳过分包目录\n if (isRoot && entry.isDirectory() && skipDirs.includes(entry.name)) {\n continue; // 跳过分包目录\n }\n\n if (entry.isDirectory()) {\n partition({\n pkgRoot: srcPath,\n destRoot: destPath,\n gameOutput,\n packedFiles,\n gameEntry,\n skipDirs,\n isRoot: false, // 递归下去不再判断\n });\n } else {\n ensureDirSync(path.dirname(destPath));\n if (!packedFiles.includes(path.relative(gameEntry, srcPath))) {\n fs.copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { SUBPACKAGES_DIR_NAME } from '@constants';\nimport { logger, removeEmptyDir, removeSystemUseless } from '@utils';\nimport { setup } from './setup';\nimport { flattenMaps, collectMaps } from './collectMaps';\nimport { collectDeps } from './collectDeps';\nimport { pack } from './pack';\nimport { partition } from './partition';\nexport async function makePkgs({ gameEntry, gameOutput }) {\n let startTime = Date.now();\n removeSystemUseless(gameEntry);\n logger.info(`pack start,startTime:${startTime}`);\n const { packages } = await setup(gameEntry, gameOutput);\n const allDeps = collectDeps(gameEntry, packages);\n const allMaps = collectMaps(gameEntry, packages);\n const pkgOutput = {};\n\n for (const pkgName in allMaps) {\n logger.info(`开始基于游戏源代码打包,包名:${pkgName}`);\n let startTime = Date.now();\n const pkgConfig = packages[pkgName];\n const pkgRoot = path.join(gameEntry, pkgConfig.root);\n const destRoot = path.join(gameOutput, pkgName, pkgConfig.root);\n /**\n * 打包\n */\n pack({\n gameEntry,\n gameOutput,\n allDeps,\n allMaps,\n pkgName,\n pkgConfig,\n destRoot,\n });\n\n /**\n * 分包\n */\n partition({\n gameEntry,\n gameOutput,\n pkgRoot,\n destRoot,\n packedFiles: flattenMaps(allMaps),\n skipDirs: [SUBPACKAGES_DIR_NAME],\n });\n\n const pkgRootDir = path.join(gameOutput, pkgName);\n removeEmptyDir(pkgRootDir);\n logger.info(`基于游戏源代码打包分包完成,包名:${pkgName}`);\n logger.info(\n `基于游戏源代码打包分包耗时,包名:${pkgName},耗时:${\n Date.now() - startTime\n }ms`,\n );\n }\n // splitOdrPackages(gameOutput);\n logger.info(`pack end,duration:${Date.now() - startTime}ms`);\n\n return pkgOutput;\n}\n","import { logger } from '@utils';\nimport { PROJECT_SIZE_LIMIT, MAINPACKAGE_SIZE_LIMIT } from '@constants';\nimport { BuildConfig } from '@typings';\nimport { checkPkgs } from '../checkPkgs';\nimport { makePkgs } from '../makePkgs';\nimport { makeOdrPkgs } from '../odrPkgs';\n\nexport async function buildPkgs(config: BuildConfig): Promise<{\n isSuccess: boolean;\n errorMsg?: string;\n}> {\n const { entry: entryDir, output: outputDir, rules } = config;\n let startTime = Date.now();\n logger.init(outputDir, true);\n logger.info(`TTMG_PACK_VERSION: ${process.env.TTMG_PACK_VERSION}`);\n logger.info(`pack start, startTime:${startTime}`);\n try {\n /**\n * 校验\n */\n await checkPkgs({\n entryDir,\n config: {\n projectSizeLimit: rules?.projectSizeLimit || PROJECT_SIZE_LIMIT,\n mainPackageSizeLimit:\n rules?.mainPackageSizeLimit || MAINPACKAGE_SIZE_LIMIT,\n subpackageSizeLimit: rules?.subpackageSizeLimit,\n },\n });\n /**\n * 打包\n */\n await makePkgs({\n gameEntry: entryDir,\n gameOutput: outputDir,\n });\n\n /**\n * 分拆 odr 包\n */\n await makeOdrPkgs(outputDir);\n\n return {\n isSuccess: true,\n };\n } catch (error) {\n logger.error(`pack error:${error.message}`);\n return {\n isSuccess: false,\n errorMsg: error.message,\n };\n } finally {\n logger.info(`pack end:${Date.now() - startTime}ms`);\n }\n}\n","import path from 'path';\nimport fs from 'fs';\nimport {\n ensureDirSync,\n deleteNoJsFilesSync,\n logger,\n deleteJsFilesSync,\n} from '@utils';\n\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n ODR_ASSET_DIR_SUFFIX,\n ODR_CODE_DIR_SUFFIX,\n STTPKG_EXT,\n} from '@constants';\n\nexport async function makeOdrPkgs(outputDir: string) {\n let startTime = Date.now();\n logger.info(`makeOdrPkgs start, ${startTime}`);\n const outputPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n const config = JSON.parse(fs.readFileSync(outputPath, 'utf-8'));\n const packages = config.packages;\n for (const pkgName in packages) {\n /**\n * 将原本的分包配置,转换为 odr 的配置,\n * 将原本产物按照原路径,分别拆分成两个文件夹:js 部分 package_name_code,asset 部分 package_name_asset\n */\n const pkgOutput = path.join(outputDir, pkgName);\n const codeOutput = path.join(outputDir, `${pkgName}${ODR_CODE_DIR_SUFFIX}`);\n const assetOutput = path.join(\n outputDir,\n `${pkgName}${ODR_ASSET_DIR_SUFFIX}`,\n );\n ensureDirSync(codeOutput);\n ensureDirSync(assetOutput);\n fs.cpSync(pkgOutput, codeOutput, { recursive: true });\n fs.cpSync(pkgOutput, assetOutput, { recursive: true });\n deleteNoJsFilesSync(codeOutput);\n deleteJsFilesSync(assetOutput);\n\n /**\n * 写入配置\n */\n packages[`${pkgName}${ODR_CODE_DIR_SUFFIX}`] = {\n ...packages[pkgName],\n code_url: '',\n code_md5: '',\n output: `${pkgName}${ODR_CODE_DIR_SUFFIX}${STTPKG_EXT}`,\n };\n packages[`${pkgName}${ODR_ASSET_DIR_SUFFIX}`] = {\n ...packages[pkgName],\n asset_url: '',\n asset_md5: '',\n output: `${pkgName}${ODR_ASSET_DIR_SUFFIX}${STTPKG_EXT}`,\n };\n }\n fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));\n logger.info(`makeOdrPkgs end, ${Date.now() - startTime}ms`);\n}\n","import { logger } from '@utils';\nimport { PROJECT_SIZE_LIMIT, MAINPACKAGE_SIZE_LIMIT } from '@constants';\nimport { BuildConfig } from '@typings';\nimport { checkPkgs } from '../checkPkgs';\nimport { mergePkgs } from '../mergePkgs';\nimport { makePkgs } from '../makePkgs';\n\nexport async function debugPkgs(config: BuildConfig): Promise<{\n isSuccess: boolean;\n errorMsg?: string;\n}> {\n const { entry: entryDir, output: outputDir, rules } = config;\n let startTime = Date.now();\n logger.init(outputDir, false);\n try {\n /**\n * 校验\n */\n await checkPkgs({\n entryDir,\n config: {\n projectSizeLimit: rules?.projectSizeLimit || PROJECT_SIZE_LIMIT,\n mainPackageSizeLimit:\n rules?.mainPackageSizeLimit || MAINPACKAGE_SIZE_LIMIT,\n subpackageSizeLimit: rules?.subpackageSizeLimit,\n },\n });\n /**\n * 打包\n */\n await makePkgs({\n gameEntry: entryDir,\n gameOutput: outputDir,\n });\n\n /**\n * 合并\n */\n await mergePkgs(outputDir);\n\n return {\n isSuccess: true,\n };\n } catch (error) {\n return {\n isSuccess: false,\n errorMsg: error.message,\n };\n }\n}\n","import path from 'path';\nimport fs from 'fs';\nimport { logger } from '@utils';\nimport { ProjectConfig } from '@typings';\nimport { GAME_PACK_CONFIG_FILE_NAME } from '@constants';\n\n/**\n * 将 packages 中的每个 package 下的文件内容合并到 outputDir 下,不保留 package name\n * @param outputDir 输出目录\n */\nexport function mergePkgs(outputDir: string) {\n logger.info('mergePkgs start');\n const gamePackConfigPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n let gamePackConfig: ProjectConfig;\n try {\n gamePackConfig = JSON.parse(fs.readFileSync(gamePackConfigPath, 'utf-8'));\n } catch (err) {\n logger.error(\n `读取配置文件失败: ${gamePackConfigPath}, err: ${err.message}`,\n );\n return;\n }\n\n const packages = gamePackConfig.packages;\n if (!packages || typeof packages !== 'object') {\n logger.error('配置文件中 packages 字段无效, 请检查配置');\n return;\n }\n\n for (const pkgName of Object.keys(packages)) {\n const pkgDir = path.join(outputDir, pkgName);\n if (!fs.existsSync(pkgDir)) {\n logger.warn(`package 目录不存在: ${pkgDir}`);\n continue;\n }\n\n const files = fs.readdirSync(pkgDir);\n for (const file of files) {\n const srcPath = path.join(pkgDir, file);\n const destPath = path.join(outputDir, file);\n\n try {\n const stat = fs.statSync(srcPath);\n if (stat.isFile()) {\n fs.copyFileSync(srcPath, destPath);\n } else if (stat.isDirectory()) {\n fs.cpSync(srcPath, destPath, { recursive: true });\n } else if (stat.isSymbolicLink()) {\n const linkTarget = fs.readlinkSync(srcPath);\n // 判断目标是否已存在符号链接\n if (fs.existsSync(destPath)) {\n fs.rmSync(destPath, { force: true });\n }\n fs.symlinkSync(\n linkTarget,\n destPath,\n stat.isDirectory() ? 'dir' : 'file',\n );\n }\n logger.info(`合并文件/目录: ${srcPath} -> ${destPath}`);\n } catch (err) {\n logger.error(`处理文件失败: ${srcPath}, err: ${err.message}`);\n }\n }\n\n // 删除 package 目录\n try {\n fs.rmSync(pkgDir, { recursive: true, force: true });\n logger.info(`已删除 package 目录: ${pkgDir}`);\n } catch (err) {\n logger.error(`删除 package 目录失败: ${pkgDir}, err: ${err.message}`);\n }\n }\n\n logger.info('mergePkgs 完成');\n}\n","/**\n * 合并请求拆包\n */\nimport fs from 'fs';\nimport path from 'path';\nimport { getDirSizeSync } from '@utils';\nimport { fetchAllGames, downloadAndSaveCodesSync } from './utils';\nimport { AVAILABLE_ODR_TAG_LIST, ONE_ODR_PKG_LIMIT } from '@constants';\n\nexport async function downloadOdrPkgs() {\n const TEMP_DIR = path.join(__dirname, 'temp');\n if (!fs.existsSync(TEMP_DIR)) fs.mkdirSync(TEMP_DIR);\n const games = await fetchAllGames();\n console.log('odr_games', games);\n downloadAndSaveCodesSync(games, TEMP_DIR);\n const gamesContentSize = {};\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameDir = path.join(TEMP_DIR, gameId);\n gamesContentSize[gameId] = getDirSizeSync(gameDir);\n }\n // ODR TAG 分配\n const odrTagGameMap = {};\n AVAILABLE_ODR_TAG_LIST.forEach(tag => {\n odrTagGameMap[tag] = [];\n });\n // 用于产出 TTMGODRConfig\n const TTMGODRConfig = {};\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameSize = gamesContentSize[gameId];\n if (gameSize > ONE_ODR_PKG_LIMIT) continue;\n let assignedTag = null;\n for (const odrTag of AVAILABLE_ODR_TAG_LIST) {\n const odrTagDir = path.join(TEMP_DIR, odrTag);\n if (!fs.existsSync(odrTagDir)) fs.mkdirSync(odrTagDir);\n const currentTagSize = odrTagGameMap[odrTag].reduce(\n (sum, gid) => sum + gamesContentSize[gid],\n 0,\n );\n if (currentTagSize + gameSize <= ONE_ODR_PKG_LIMIT) {\n // 复制资源\n const srcDir = path.join(TEMP_DIR, gameId);\n const destDir = path.join(odrTagDir, gameId);\n fs.cpSync(srcDir, destDir, { recursive: true });\n odrTagGameMap[odrTag].push(gameId);\n assignedTag = odrTag;\n break;\n }\n }\n if (!assignedTag) continue; // 没有分配成功就跳过\n // 构建 TTMGODRConfig\n\n TTMGODRConfig[gameId] = {\n tag: assignedTag,\n packages: {},\n };\n for (const packageName in packages) {\n const pkg = packages[packageName];\n console.log('TTMGODRConfig[gameId].packages', packageName, pkg);\n TTMGODRConfig[gameId].packages[packageName] = {\n root: pkg.root,\n main: pkg.main,\n // code_md5: pkg.code_md5,\n asset_md5: pkg.asset_md5,\n asset_url: pkg.asset_url,\n };\n }\n }\n // 写入 JSON 文件\n const configPath = path.join(TEMP_DIR, 'TTMG_ODR_CONFIG.json');\n fs.writeFileSync(configPath, JSON.stringify(TTMGODRConfig, null, 2), 'utf-8');\n console.log('TTMG_ODR_CONFIG.json 已生成:', configPath);\n}\n","\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { ODRPackages } from '@typings';\nimport { gameOdrPackages } from './mock';\n\nexport function fetchGames(params: { size: number; offset: number }): Promise<{\n data: Array<{\n id: string;\n packages: ODRPackages;\n }>;\n total: number;\n}> {\n const { size, offset } = params;\n const url = `https://game-odr.bytedance.net/odr/api/v1/games?size=${size}&offset=${offset}`;\n return fetch(url).then(res => res.json());\n}\n\n\n\nexport async function fetchAllGames(): Promise<Array<{\n id: string;\n packages: ODRPackages;\n }>> {\n return gameOdrPackages;\n const size = 100;\n let offset = 0;\n let total = 0;\n const games: Array<{\n id: string;\n packages: ODRPackages;\n }> = [];\n while (true) {\n const res = await fetchGames({ size, offset });\n games.push(...res.data);\n total = res.total;\n if (games.length >= total) {\n break;\n }\n offset += size;\n }\n return games;\n}\n\n\n// 同步下载并写入所有 code_url 文件\nexport function downloadAndSaveCodesSync(\n games: Array<{\n id: string;\n packages: ODRPackages;\n }>,\n tempDir: string,\n) {\n for (const game of games) {\n const { id: gameId, packages } = game;\n const gameDir = path.join(tempDir, gameId);\n if (!fs.existsSync(gameDir)) fs.mkdirSync(gameDir);\n\n for (const packageName in packages) {\n const packageInfo = packages[packageName];\n const { code_url } = packageInfo;\n // 同步下载\n const code = require('child_process')\n .execSync(`curl -s \"${code_url}\"`)\n .toString();\n console.log('downloadAndSaveCodesSync code', code_url);\n const fileName = `${packageName}.txt`;\n const filePath = path.join(gameDir, fileName);\n fs.writeFileSync(filePath, code);\n }\n }\n}","import { logger } from '@utils';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nimport {\n GAME_PACK_CONFIG_FILE_NAME,\n ODR_ASSET_DIR_SUFFIX,\n ODR_CODE_DIR_SUFFIX,\n} from '@constants';\n\n/**\n * 将 packageConfig packages 中 分拆的包 配置迁移到 odr_packages 中\n */\n\nexport async function writeOdrConfig(outputDir: string) {\n logger.info('writeOdrPackagesConfig start');\n const outputPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);\n const config = JSON.parse(fs.readFileSync(outputPath, 'utf-8'));\n const packages = config.packages;\n const odrPackages = config.odr_packages || {};\n for (const pkgName in packages) {\n if (pkgName.endsWith(ODR_CODE_DIR_SUFFIX)) {\n /**\n * 找到 assets 对应的包\n */\n const pkgConfig = packages[pkgName];\n const relatedPkgName = pkgName.split(ODR_CODE_DIR_SUFFIX)[0];\n if (!odrPackages[relatedPkgName]) {\n odrPackages[relatedPkgName] = {};\n }\n odrPackages[relatedPkgName] = {\n ...odrPackages[relatedPkgName],\n root: pkgConfig.root,\n code_output: pkgConfig.output,\n code_md5: pkgConfig.md5,\n main: pkgConfig.main,\n };\n delete packages[pkgName];\n }\n if (pkgName.endsWith(ODR_ASSET_DIR_SUFFIX)) {\n const relatedPkgName = pkgName.split(ODR_ASSET_DIR_SUFFIX)[0];\n const pkgConfig = packages[pkgName];\n odrPackages[relatedPkgName] = {\n ...odrPackages[relatedPkgName],\n root: pkgConfig.root,\n asset_output: pkgConfig.output,\n asset_md5: pkgConfig.md5,\n };\n delete packages[pkgName];\n }\n }\n config.odr_packages = odrPackages;\n fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));\n logger.info('writeOdrPackagesConfig end');\n}\n"],"names":["ensureDirSync","dir","fs","existsSync","mkdirSync","recursive","logger","constructor","this","init","output","enableLog","winston","createLogger","level","format","combine","timestamp","json","transports","File","filename","path","join","Console","info","msg","error","warn","debug","log","setOutput","removeEmptyDir","statSync","isDirectory","isEmpty","files","readdirSync","file","fullPath","rmSync","GAME_PACK_CONFIG_FILE_NAME","GAME_ORIGIN_CONFIG_FILE_NAME","GAME_MAIN_PACKAGE_NAME","STTPKG_EXT","SUBPACKAGES_DIR_NAME","ODR_CODE_DIR_SUFFIX","ODR_ASSET_DIR_SUFFIX","ONE_ODR_PKG_LIMIT","AVAILABLE_ODR_TAG_LIST","PROJECT_SIZE_LIMIT","MAINPACKAGE_SIZE_LIMIT","getDirSizeSync","filterDirs","totalSize","entries","withFileTypes","entry","name","includes","isFile","size","deleteJsFilesSync","endsWith","unlinkSync","err","deleteNoJsFilesSync","uselessDirs","uselessFiles","odrPackages","__GAME__","code_url","asset_url","asset_md5","root","main","configBundle","gameBundle","mainBundle","resources","iceAndFire","pushstone","gameOdrPackages","id","Math","random","packages","checkProject","entryDir","config","projectSizeLimit","gameJsonPath","errMsg","Error","checkConfig","limit","gameSize","gameSizeMB","round","limitMB","checkProjectSize","checkMainPackage","mainPackageSizeLimit","gameJsPath","mainPkgSize","mainPkgSizeMB","checkMainPackageSize","checkSubpackages","subpackageSizeLimit","subpackages","JSON","parse","readFileSync","length","forEach","sub","subpackageEntryDir","subpackageRoot","subPkgName","subPkgDir","subPkgSize","sizeMB","checkSubPackageSize","async","checkPkgs","setup","outputDir","gameJson","url","md5","configs","normalizeName","String","replace","normalizeRoot","trim","str","test","map","idx","indexOf","slice","transformSubPackages","result","Object","keys","pkg","pkgPath","writeFileSync","stringify","flattenMaps","allMaps","list","values","arr","push","collectAllJsFiles","exts","excludeDirs","concat","some","ext","collectDeps","gameEntry","rootPrefixes","filter","getRootPrefixes","glob","sync","cwd","ignore","requireCalls","code","ast","acorn","ecmaVersion","sourceType","e","walkAst","node","type","callee","arguments","requirePath","value","resolvedPath","startsWith","resolve","dirname","prefix","filePath","fileExistsWithExtensions","relative","newRequireCalls","i","depModule","curModule","assign","reduce","acc","cur","f","cb","key","hasOwnProperty","child","Array","isArray","c","pack","gameOutput","pkgName","allDeps","pkgConfig","destRoot","startTime","Date","now","packMap","moduleConfig","deps","packFileName","relPaths","Bundle","separator","relPath","absPath","basename","fileId","defineHeader","defineFooter","fileMagic","MagicString","wrapped","appendLeft","toString","append","addSource","content","outFile","generateMap","hires","includeContent","partition","pkgRoot","packedFiles","skipDirs","isRoot","srcPath","destPath","copyFileSync","makePkgs","removeUselessDirs","console","stat","force","removeSystemUseless","subRoots","split","sep","Boolean","uniqueSubRoots","from","Set","srcRoot","jsFiles","packNameRoot","collectMaps","rules","outputPath","pkgOutput","codeOutput","assetOutput","cpSync","code_md5","makeOdrPkgs","isSuccess","message","errorMsg","gamePackConfigPath","gamePackConfig","pkgDir","isSymbolicLink","linkTarget","readlinkSync","symlinkSync","mergePkgs","TEMP_DIR","__dirname","games","fetchAllGames","tempDir","game","gameId","gameDir","packageName","packageInfo","require","execSync","fileName","downloadAndSaveCodesSync","gamesContentSize","odrTagGameMap","tag","TTMGODRConfig","assignedTag","odrTag","odrTagDir","sum","gid","srcDir","destDir","configPath","odr_packages","relatedPkgName","code_output","asset_output"],"mappings":";;;;;;;;gcACM,SAAUA,EAAcC,GACvBC,EAAGC,WAAWF,IAAMC,EAAGE,UAAUH,EAAK,CAAEI,WAAW,GAC1D,CCmDO,MAAMC,EAAS,IAnDtB,MAIE,WAAAC,GACEC,KAAKF,OAAS,IAChB,CACA,IAAAG,CAAKC,EAAgBC,GAAY,GAC/BH,KAAKG,UAAYA,EACjBH,KAAKF,OAASM,EAAQC,aAAa,CACjCC,MAAO,OACPC,OAAQH,EAAQG,OAAOC,QACrBJ,EAAQG,OAAOE,YACfL,EAAQG,OAAOG,QAEjBC,WAAY,CACV,IAAIP,EAAQO,WAAWC,KAAK,CAC1BC,SAAUC,EAAKC,KAAKb,EAAQ,cAE9B,IAAIE,EAAQO,WAAWK,UAG7B,CACA,IAAAC,CAAKC,GACClB,KAAKG,WACPH,KAAKF,OAAOmB,KAAKC,EAErB,CACA,KAAAC,CAAMD,GACAlB,KAAKG,WACPH,KAAKF,OAAOqB,MAAMD,EAEtB,CACA,IAAAE,CAAKF,GACClB,KAAKG,WACPH,KAAKF,OAAOsB,KAAKF,EAErB,CACA,KAAAG,CAAMH,GACAlB,KAAKG,WACPH,KAAKF,OAAOuB,MAAMH,EAEtB,CACA,GAAAI,CAAIJ,GACFlB,KAAKF,OAAOmB,KAAKC,EACnB,CACA,SAAAK,CAAUrB,GACRF,KAAKE,OAASA,CAChB,GC3CI,SAAUsB,EAAe/B,GAC7B,IAAKC,EAAGC,WAAWF,GAAM,OAAO,EAChC,IAAKC,EAAG+B,SAAShC,GAAKiC,cAAe,OAAO,EAE5C,IAAIC,GAAU,EACd,MAAMC,EAAQlC,EAAGmC,YAAYpC,GAC7B,IAAK,MAAMqC,KAAQF,EAAO,CACxB,MAAMG,EAAWjB,EAAKC,KAAKtB,EAAKqC,GAChC,GAAIpC,EAAG+B,SAASM,GAAUL,cAAe,CAElBF,EAAeO,KACjBJ,GAAU,EAC/B,MAEEA,GAAU,CAEd,CAGA,QAAIA,IACFjC,EAAGsC,OAAOvC,EAAK,CAAEI,WAAW,KACrB,EAGX,CChCO,MAAMoC,EAA6B,qBAC7BC,EAA+B,YAG/BC,EAAyB,WAsBzBC,EAAa,OAEbC,EAAuB,cAEvBC,EAAsB,QAEtBC,EAAuB,SAGvBC,EAAoB,SAEpBC,EAAyB,CACpC,iBACA,iBACA,kBAGWC,EAAqB,SAGrBC,EAAyB,iBC3CtBC,EAAenD,EAAaoD,EAAuB,IACjE,IAAIC,EAAY,EAChB,IAAKpD,EAAGC,WAAWF,GAAM,OAAO,EAChC,MAAMsD,EAAUrD,EAAGmC,YAAYpC,EAAK,CAAEuD,eAAe,IACrD,IAAK,MAAMC,KAASF,EAAS,CAC3B,MAAMhB,EAAWjB,EAAKC,KAAKtB,EAAKwD,EAAMC,MAClCD,EAAMvB,cACDmB,EAAWM,SAASF,EAAMC,QAC/BJ,GAAaF,EAAeb,EAAUc,IAE/BI,EAAMG,WACfN,GAAapD,EAAG+B,SAASM,GAAUsB,KAEvC,CACA,OAAOP,CACT,CCXM,SAAUQ,EAAkB7D,GAEhC,MAAMsD,EAAUrD,EAAGmC,YAAYpC,EAAK,CAAEuD,eAAe,IAErD,IAAK,MAAMC,KAASF,EAAS,CAC3B,MAAMhB,EAAWjB,EAAKC,KAAKtB,EAAKwD,EAAMC,MAEtC,GAAID,EAAMvB,cAER4B,EAAkBvB,QACb,GACLkB,EAAMG,WACLrB,EAASwB,SAAS,QAAUxB,EAASwB,SAAS,YAE/C,IACE7D,EAAG8D,WAAWzB,EAChB,CAAE,MAAO0B,GAAM,CAEnB,CACF,CCvBM,SAAUC,EAAoBjE,GAClC,MAAMsD,EAAUrD,EAAGmC,YAAYpC,EAAK,CAAEuD,eAAe,IAErD,IAAK,MAAMC,KAASF,EAAS,CAC3B,MAAMhB,EAAWjB,EAAKC,KAAKtB,EAAKwD,EAAMC,MAEtC,GAAID,EAAMvB,cAERgC,EAAoB3B,QACf,GACLkB,EAAMG,WACJrB,EAASwB,SAAS,SAAUxB,EAASwB,SAAS,WAEhD,IACE7D,EAAG8D,WAAWzB,EAChB,CAAE,MAAO0B,GAAM,CAEnB,CACF,CClBA,MAAME,EAAc,CAAC,eAAgB,YAC/BC,EAAe,CAAC,YAAa,aCOnC,MAAMC,EAA2B,CAC/BC,SAAU,CAERC,SAAU,0DACVC,UAAW,2DACXC,UAAW,mCACXC,KAAM,GACNC,KAAM,WAERC,aAAc,CAEZF,KAAM,2BACNC,KAAM,mCACNF,UAAW,mCACXF,SAAU,8DACVC,UAAW,gEAEbK,WAAY,CAEVF,KAAM,iCACND,KAAM,yBACND,UAAW,mCACXF,SAAU,4DACVC,UAAW,8DAEbM,WAAY,CAEVH,KAAM,iCACND,KAAM,yBACND,UAAW,mCACXF,SAAU,4DACVC,UAAW,8DAEbO,UAAW,CAETL,KAAM,wBACNC,KAAM,gCACNF,UAAW,mCACXF,SAAU,2DACVC,UAAW,6DAEbQ,WAAY,CAEVN,KAAM,yBACNC,KAAM,iCACNF,UAAW,mCACXF,SAAU,4DACVC,UAAW,8DAEbS,UAAW,CAETP,KAAM,wBACNC,KAAM,gCACNF,UAAW,mCACXF,SAAU,2DACVC,UAAW,6DAEbG,KAAM,CAEJD,KAAM,mBACNC,KAAM,2BACNF,UAAW,mCACXF,SAAU,sDACVC,UAAW,yDAIFU,EAAkB,CAC7B,CAAEC,GAAI,GAAmB,KAAhBC,KAAKC,SAAiCC,SAAUjB,GACzD,CAAEc,GAAI,GAAmB,KAAhBC,KAAKC,SAAiCC,SAAUjB,ICrCrD,SAAUkB,EACdC,EACAC,GAEAnF,EAAOmB,KAAK,uBACZ,MAAMiE,EAAmBD,aAAM,EAANA,EAAQC,kBA1C7B,SAAsBF,GAC1BlF,EAAOmB,KAAK,sBACZ,MAAMkE,EAAerE,EAAKC,KAAKiE,EAAU9C,GACzC,IAAKxC,EAAGC,WAAWwF,GAAe,CAChC,MAAMC,EACJ,8DAEF,MADAtF,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CACEtF,EAAOmB,KAAK,4BAEhB,CAgCEqE,CAAYN,GAxBR,SAA2BA,EAAkBO,GACjDzF,EAAOmB,KAAK,4BACZ,MAAMuE,EAAW5C,EAAeoC,EAAU,IACpCS,EAAab,KAAKc,MAAMF,EAAQ,SAChCG,EAAUf,KAAKc,MAAMH,EAAK,SAChC,GAAIC,EAAWD,EAAO,CACpB,MAAMH,EAAS,aAAaK,wBAAiCE,MAE7D,MADA7F,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CAIEtF,EAAOmB,KAAK,aAAawE,4BACzB3F,EAAOmB,KAAK,gCAEhB,CASE2E,CAAiBZ,EAAUE,GAC3BpF,EAAOmB,KAAK,6BACd,CCrBM,SAAU4E,EACdb,EACAC,GAIAnF,EAAOmB,KAAK,4BACZ,MAAM6E,qBAAEA,GAAyBb,EAKjCnF,EAAOmB,KAAK,iBACZ,MAAM8E,EAAajF,EAAKC,KAAKiE,EAAU,WACvC,IAAKtF,EAAGC,WAAWoG,GAAa,CAC9B,MAAMX,EAAS,sCAEf,MADAtF,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CACAtF,EAAOmB,KAAK,wCA1CuB+D,SACnCA,EAAQO,MACRA,IAKAzF,EAAOmB,KAAK,iCACZ,MAAM+E,EAAcpD,EAAeoC,EAAU,CAAC,gBACxCiB,EAAgBrB,KAAKc,MAAMM,EAAW,SACtCL,EAAUf,KAAKc,MAAMH,EAAK,SAChC,GAAIS,EAAcT,EAAO,CACvB,MAAMH,EAAS,qBAAqBa,wBAAoCN,MAExE,MADA7F,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CAIEtF,EAAOmB,KAAK,qBAAqBgF,2BAErC,CA0BEC,CAAqB,CACnBlB,WACAO,MAAOO,IAEThG,EAAOmB,KAAK,kCACd,CCrDM,SAAUkF,EACdnB,EACAC,GAEA,MAAMmB,oBAAEA,GAAwBnB,GAAU,CAAA,EAI1CnF,EAAOmB,KAAK,wCACZ,MAAMkE,EAAerE,EAAKC,KAAKiE,EAAU9C,GAEnCmE,EADWC,KAAKC,MAAM7G,EAAG8G,aAAarB,EAAc,UAI5CkB,aAAe,IACxBA,aAAW,EAAXA,EAAaI,QAGhBJ,EAAYK,QAAQC,IAIlB,IAAKA,EAAIzD,OAASyD,EAAIzC,KAAM,CAC1B,MAAMkB,EACJ,6LAEF,MADAtF,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CAIA,MAAMwB,EAAqB9F,EAAKC,KAAKiE,EAAU2B,EAAIzC,MAEnD,IAAKxE,EAAGC,WAAWiH,GAAqB,CACtC,MAAMxB,EAAS,kFAAkFuB,EAAIzD,kCAErG,MADApD,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CACA,MAAMyB,EAAiBF,EAAIzC,KAC3B,IAAKxE,EAAGC,WAAWmB,EAAKC,KAAKiE,EAAU6B,IAAkB,CACvD,MAAMzB,EAAS,kFAAkFuB,EAAIzD,6BAErG,MADApD,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CAKIgB,GAkBV,UAA6BpB,SAC3BA,EAAQ8B,WACRA,EAAUvB,MACVA,IAMA,MAAMwB,EAAYjG,EAAKC,KAAKiE,EAAU,cAAe8B,GAC/CE,EAAapE,EAAemE,EAAW,IACvCE,EAASrC,KAAKc,MAAMsB,EAAU,SACpC,GAAIC,EAAS1B,EAAO,CAClB,MAAMH,EAAS,GAAG0B,sBAA+BG,wBAC/C1B,EAAK,YAGP,MADAzF,EAAOqB,MAAMiE,GACP,IAAIC,MAAMD,EAClB,CAIEtF,EAAOmB,KACL,GAAG6F,sBAA+BG,2BAGxC,CA3CQC,CAAoB,CAClBlC,WACA8B,WAAYH,EAAIzD,KAChBqC,MAAOa,MApCbtG,EAAOmB,KAAK,wBAyCdnB,EAAOmB,KAAK,8CACd,CC3DOkG,eAAeC,GAAUpC,SAC9BA,EAAQC,OACRA,IAKAnF,EAAOmB,KAAK,UAIZ8D,EAAaC,EAAUC,GAIvBY,EAAiBb,EAAUC,GAI3BkB,EAAiBnB,EAAUC,GAC3BnF,EAAOmB,KAAK,SACd,CCbOkG,eAAeE,EAAMrC,EAAkBsC,GAC5CxH,EAAOmB,KAAK,6CACZ,MAAMkE,EAAerE,EAAKC,KAAKiE,EAAU9C,GACnCqF,EAAWjB,KAAKC,MAAM7G,EAAG8G,aAAarB,EAAc,UAEpDL,EAAW,CAAA,EAEjBA,EAAS3C,GAA0B,CACjCqF,IAAK,GACLC,IAAK,GACLvD,KAAM,GACNC,KAAM,UACNjE,OAAQ,GAAGiC,IAAyBC,KA6CxC,SAA8BsF,GAC5B,IAAKA,GAA8B,IAAnBA,EAAQjB,OACtB,MAAO,GAET,SAASkB,EAAczE,GACrB,OAAO0E,OAAO1E,GAAM2E,QAAQ,aAAc,GAC5C,CAEA,SAASC,EAAc5D,GACrB,OAAO0D,OAAO1D,GAAM6D,OAAOF,QAAQ,OAAQ,GAC7C,CAEA,SAASnG,EAAYsG,GAEnB,OAAOA,EAAIzE,SAAS,OAAS,kBAAkB0E,KAAKD,EACtD,CAEA,OAAON,EAAQQ,IAAIjD,IACjB,MAAM/B,EAAOyE,EAAc1C,EAAO/B,MAClC,IAAIgB,EAAO4D,EAAc7C,EAAOf,MAGhC,MAAMiE,EAAMjE,EAAKkE,QAAQlF,GAezB,OAXEgB,GAFU,IAARiE,EAEKjE,EAAKmE,MAAMF,GAGXjF,GAAQxB,EAAYwC,GAAQ,WAAa,IAAMA,GAIpDxC,EAAYwC,KACdA,EAAOA,EAAK2D,QAAQ,OAAQ,IAAM,YAG7B,CAAE1D,KAAMD,EAAMA,KAAMhB,IAE/B,CAjFEoF,CAAqBf,EAASlB,aAAaK,QAAQC,IAEjD7B,EAAS6B,EAAIzC,MAAQ,CACnBsD,IAAK,GACLC,IAAK,GACLvD,KAAM,GAAG7B,KAAwBsE,EAAIzC,OACrCC,KAAM,GAAG9B,KAAwBsE,EAAIxC,OACrCjE,OAAQ,GAAGyG,EAAIzC,OAAO9B,OAI1B,MAAMmG,EAAS,CACbzD,YA2BF,OAtBA0D,OAAOC,KAAK3D,GAAU4B,QAAQgC,IAC5B,MAAMC,EAAU7H,EAAKC,KAAKiE,EAAUF,EAAS4D,GAAKvE,MAClD,IAAKzE,EAAGC,WAAWgJ,GAKjB,MAJA7I,EAAOqB,MACL,eAAeuH,gBAAkB5D,EAAS4D,GAAKvE,YAG3C,IAAIkB,MACR,eAAeqD,gBAAkB5D,EAAS4D,GAAKvE,cAKjDzE,EAAGC,WAAW2H,IAChB5H,EAAGsC,OAAOsF,EAAW,CAAEzH,WAAW,IAEpCH,EAAGE,UAAU0H,GACb5H,EAAGkJ,cACD9H,EAAKC,KAAKuG,EAAWrF,GACrBqE,KAAKuC,UAAUN,EAAQ,KAAM,IAE/BzI,EAAOmB,KAAK,8CACLsH,CACT,CCjEM,SAAUO,EAAYC,GAC1B,MAAMC,EAAO,GAMb,OALAR,OAAOS,OAAOF,GAASrC,QAAQwB,IAC7BM,OAAOS,OAAOf,GAAKxB,QAAQwC,IACzBF,EAAKG,QAAQD,OAGVF,CACT,CAGA,SAASI,EACP3J,EACA4J,EAAO,CAAC,MAAO,MAAO,OAAQ,QAC9BC,EAAc,IAEd,IAAI1H,EAAQ,GACZ,IAAKlC,EAAGC,WAAWF,GAAM,OAAOmC,EAChC,MAAMmB,EAAUrD,EAAGmC,YAAYpC,EAAK,CAAEuD,eAAe,IACrD,IAAK,MAAMC,KAASF,EAAS,CAC3B,MAAMhB,EAAWjB,EAAKC,KAAKtB,EAAKwD,EAAMC,MACtC,GAAID,EAAMvB,cAAe,CACvB,GAAI4H,EAAYnG,SAASF,EAAMC,MAAO,SACtCtB,EAAQA,EAAM2H,OAAOH,EAAkBrH,EAAUsH,EAAM,IACzD,MAAWA,EAAKG,KAAKC,GAAOxG,EAAMC,KAAKK,SAASkG,KAC9C7H,EAAMuH,KAAKpH,EAEf,CACA,OAAOH,CACT,CC5BM,SAAU8H,EAAYC,EAAW7E,GAErC,MAAM8E,EA+GR,SAAyBD,GACvB,OAAOjK,EACJmC,YAAY8H,GACZE,OAAO3G,IACN,MAAMnB,EAAWjB,EAAKC,KAAK4I,EAAWzG,GACtC,OACExD,EAAG+B,SAASM,GAAUL,gBACrB,CAAC,eAAgB,OAAQ,QAAS,UAAUyB,SAASD,KAGzDgF,IAAIhF,GAAQA,EAAO,IACxB,CA1HuB4G,CAAgBH,GAG/B/H,EAAQmI,EAAKC,KAAK,UAAW,CACjCC,IAAKN,EACLO,OAAQ,KAGJC,EAAe,GAErBvI,EAAM8E,QAAQ5E,IACZ,MAAMC,EAAWjB,EAAKC,KAAK4I,EAAW7H,GAChCsI,EAAO1K,EAAG8G,aAAazE,EAAU,SAEvC,IAAIsI,EACJ,IACEA,EAAMC,EAAM/D,MAAM6D,EAAM,CAAEG,YAAa,SAAUC,WAAY,UAC/D,CAAE,MAAOC,GAEP,MACF,CAEAC,EAAQL,EAAKM,IAEX,GACgB,mBAAdA,EAAKC,MACgB,eAArBD,EAAKE,OAAOD,OACU,YAArBD,EAAKE,OAAO3H,MACU,iBAArByH,EAAKE,OAAO3H,OACdyH,EAAKG,UAAUrE,OAAS,GACG,YAA3BkE,EAAKG,UAAU,GAAGF,KAClB,CACA,MAAMG,EAAcJ,EAAKG,UAAU,GAAGE,MACtC,IAAIC,EAAe,KAEnB,GAAIF,EAAYG,WAAW,KACzBD,EAAenK,EAAKqK,QAAQrK,EAAKsK,QAAQrJ,GAAWgJ,QAC/C,GAAIA,EAAYG,WAAW,KAChCD,EAAenK,EAAKqK,QAAQxB,EAAW,IAAMoB,QAE7C,IAAK,MAAMM,KAAUzB,EACnB,GAAImB,EAAYG,WAAWG,GAAS,CAClCJ,EAAenK,EAAKqK,QAAQxB,EAAWoB,GACvC,KACF,CAKAE,IA0FZ,SAAkCK,GAChC,GAAI5L,EAAGC,WAAW2L,IAAa5L,EAAG+B,SAAS6J,GAAUlI,SAAU,OAAO,EACtE,MAAMiG,EAAO,CAAC,MAAO,MAAO,OAAQ,QACpC,IAAK,MAAMI,KAAOJ,EAChB,GAAI3J,EAAGC,WAAW2L,EAAW7B,IAAQ/J,EAAG+B,SAAS6J,EAAW7B,GAAKrG,SAC/D,OAAO,EAEX,OAAO,CACT,CAlG6BmI,CAAyBN,KAC5CA,EAAe,MAGjBd,EAAahB,KAAK,CAChBrH,KAAMhB,EAAK0K,SAAS7B,EAAW5H,GAC/B8I,OAAQF,EAAKE,OAAO3H,KACpB6H,cACAE,aAAcA,EACVnK,EAAK0K,SAAS7B,EAAWsB,GACzB,IAER,MAIJ,MAAMQ,EAAkBtB,EAAajC,IAAIwD,IAIvC,IAAIC,EAAY,GAChBnD,OAAOC,KAAK3D,GAAU4B,QAAQgC,IACxBgD,EAAET,cAAgBS,EAAET,aAAaC,WAAWpG,EAAS4D,GAAKxE,QAC5DyH,EAAYjD,KAIhB,IAAIkD,EAAY,GAMhB,OALApD,OAAOC,KAAK3D,GAAU4B,QAAQgC,IACxBgD,EAAE5J,KAAKoJ,WAAWpG,EAAS4D,GAAKxE,QAClC0H,EAAYlD,KAGhBF,OAAAqD,OAAArD,OAAAqD,OAAA,GACKH,IACHE,YACAD,gBAKEtC,EAAO,CAAC,MAAO,MAAO,OAAQ,QAkBpC,OAfeoC,EAAgBK,OAAO,CAACC,EAAKC,KAI1C,OAHKD,EAAIC,EAAIJ,aACXG,EAAIC,EAAIJ,WAAa,CAAA,GAEnBI,EAAIJ,YAAcI,EAAIL,WAGtBK,EAAIf,eATOgB,EASkBD,EAAIf,aATjB5B,EAAKG,KAAKC,GAAOwC,EAAE1I,SAASkG,OAU9CsC,EAAIC,EAAIJ,WAAUpD,OAAAqD,OAAArD,OAAAqD,OAAA,CAAA,EACbE,EAAIC,EAAIJ,YAAU,CACrB,CAACI,EAAIf,cAAee,EAAIL,aALnBI,EAPME,OAgBd,CAAA,EAEL,CAeA,SAASvB,EAAQC,EAAMuB,GACrBA,EAAGvB,GACH,IAAK,IAAIwB,KAAOxB,EACd,GAAIA,EAAKyB,eAAeD,GAAM,CAC5B,MAAME,EAAQ1B,EAAKwB,GACfG,MAAMC,QAAQF,GAChBA,EAAM3F,QAAQ8F,GAAKA,GAAuB,iBAAXA,EAAE5B,MAAqBF,EAAQ8B,EAAGN,IACxDG,GAA+B,iBAAfA,EAAMzB,MAC/BF,EAAQ2B,EAAOH,EAEnB,CAEJ,UCtIgBO,GAAK9C,UACnBA,EAAS+C,WACTA,EAAUC,QACVA,EAAOC,QACPA,EAAO7D,QACPA,EAAO8D,UACPA,EAASC,SACTA,IAaA,IAAIC,EAAYC,KAAKC,MACrBnN,EAAOmB,KAAK,wBAAwB8L,KACpC,MAAMG,EAAUnE,EAAQ4D,GAClBQ,EAAe,CACnBhJ,KAAM0I,EAAU1I,KAChBiJ,KAAMR,EAAQD,IAAY,CAAA,EAC1BzE,IAAKa,EAAQ4D,IAGfnN,EAAcsN,GACdpN,EAAGkJ,cACD9H,EAAKC,KAAK+L,EbtC8B,qBauCxCxG,KAAKuC,UAAUsE,IAGjB,IAAK,MAAME,KAAgBH,EAAS,CAClC,MAAMI,EAAWJ,EAAQG,GACzB,IAAKf,MAAMC,QAAQe,IAAiC,IAApBA,EAAS7G,OAAc,SAEvD,MAAM8C,EAAS,IAAIgE,EAAAA,OAAO,CAAEC,UAAW,OACvC,IAAK,MAAMC,KAAWH,EAAU,CAC9B,MAAMI,EAAU5M,EAAKC,KAAK4I,EAAW8D,GACrC,GAAK/N,EAAGC,WAAW+N,KACf5M,EAAK6M,SAASD,KAAaL,GAK3B,SAASpF,KAAKwF,IAAU,CAC1B,MAAMrD,EAAO1K,EAAG8G,aAAakH,EAAS,SAChCE,EAASH,EAAQ5F,QAAQ,MAAO,KAChCgG,EAAe,gBAAgBD,kKAC/BE,EAAe,aAEfC,EAAY,IAAIC,EAAY5D,EAAM,CAAEvJ,SAAU+M,IAC9CK,EAAU,IAAID,EAAYH,GAC7BK,WAAWL,EAAapH,OAAQsH,EAAUI,YAC1CC,OAAON,GAEVvE,EAAO8E,UAAU,CAAEC,QAASL,EAASpN,SAAU+M,GACjD,CACF,CAGA,MAAMW,EAAUzN,EAAKC,KAAK+L,EAAUhM,EAAK6M,SAASN,IAClD3N,EAAGkJ,cACD2F,EACAhF,EAAO4E,WAAa,0BAA0Bd,SAGhD,MAAMnF,EAAMqB,EAAOiF,YAAY,CAC7BC,OAAO,EACPC,gBAAgB,EAChB5M,KAAMuL,IAER3N,EAAGkJ,cAAc2F,EAAU,OAAQrG,EAAIiG,YACvCrO,EAAOmB,KAAK,qBAAqB0L,IACnC,CACF,CCnFM,SAAUgC,GAAUC,QACxBA,EAAO9B,SACPA,EAAQ+B,YACRA,EAAWlF,UACXA,EAAS+C,WACTA,EAAUoC,SACVA,EAAW,GAAEC,OACbA,GAAS,IAET,IAAKrP,EAAGC,WAAWiP,GAAU,OAC7B,MAAM7L,EAAUrD,EAAGmC,YAAY+M,EAAS,CAAE5L,eAAe,IACzD,IAAK,MAAMC,KAASF,EAAS,CAC3B,MAAMiM,EAAUlO,EAAKC,KAAK6N,EAAS3L,EAAMC,MACnC+L,EAAWnO,EAAKC,KAAK+L,EAAU7J,EAAMC,MAEvC6L,GAAU9L,EAAMvB,eAAiBoN,EAAS3L,SAASF,EAAMC,QAIzDD,EAAMvB,cACRiN,EAAU,CACRC,QAASI,EACTlC,SAAUmC,EACVvC,aACAmC,cACAlF,YACAmF,WACAC,QAAQ,KAGVvP,EAAcsB,EAAKsK,QAAQ6D,IACtBJ,EAAY1L,SAASrC,EAAK0K,SAAS7B,EAAWqF,KACjDtP,EAAGwP,aAAaF,EAASC,IAG/B,CACF,CC/BO9H,eAAegI,GAASxF,UAAEA,EAAS+C,WAAEA,IAC1C,IAAIK,EAAYC,KAAKC,OXJjB,SAA8BtD,IAIlC,SAASyF,EAAkB3P,GACzB,IAAImC,EACJ,IACEA,EAAQlC,EAAGmC,YAAYpC,EACzB,CAAE,MAAOgE,GAGP,YADA4L,QAAQjO,KAAK,WAAW3B,IAAOgE,EAEjC,CACA7B,EAAM8E,QAAQ5E,IACZ,MAAMwJ,EAAWxK,EAAKC,KAAKtB,EAAKqC,GAChC,IACE,MAAMwN,EAAO5P,EAAG+B,SAAS6J,GACrBgE,EAAK5N,cACHiC,EAAYR,SAASrB,IAEvBpC,EAAGsC,OAAOsJ,EAAU,CAAEzL,WAAW,EAAM0P,OAAO,IAC9CF,QAAQ/N,IAAI,YAAYgK,MAGxB8D,EAAkB9D,GAEXgE,EAAKlM,UACVQ,EAAaT,SAASrB,KAExBpC,EAAGsC,OAAOsJ,EAAU,CAAEiE,OAAO,IAC7BF,QAAQ/N,IAAI,YAAYgK,KAG9B,CAAE,MAAO7H,GAEP4L,QAAQjO,KAAK,SAASkK,IAAY7H,EACpC,GAEJ,CACA2L,CAAkBzF,EACpB,CWnCE6F,CAAoB7F,GACpB7J,EAAOmB,KAAK,wBAAwB8L,KACpC,MAAMjI,SAAEA,SAAmBuC,EAAMsC,EAAW+C,GACtCE,EAAUlD,EAAYC,EAAW7E,GACjCiE,EJqBF,SACJ/D,EACAF,GAEAhF,EAAOmB,KAAK,yBACZ,MAAMsH,EAAS,CAAA,EAETkH,EAAWjH,OAAOS,OAAOnE,GAC5B+E,OAAOnB,GAAOA,EAAIxE,MAAqB,KAAbwE,EAAIxE,MAC9BgE,IAAIQ,GAAOA,EAAIxE,KAAKwL,MAAM5O,EAAK6O,KAAK,IACpC9F,OAAO+F,SACJC,EAAiBvD,MAAMwD,KAAK,IAAIC,IAAIN,IAE1C,IAAK,MAAM9C,KAAW7H,EAAU,CAC9B,MAAM4D,EAAM5D,EAAS6H,GACrB,IAAIqD,EACAC,EACY,aAAZtD,GAEFsD,EAAU7G,EACRpE,EACA,CAAC,MAAO,MAAO,OAAQ,QACvB6K,GAEFG,EAAUhL,IAGVgL,EAAUlP,EAAKC,KAAKiE,EAAU0D,EAAIxE,MAClC+L,EAAU7G,EAAkB4G,IAG9B,MAAMhH,EAAO,GACbiH,EAAQvJ,QAAQgH,IACd1E,EAAKG,KAAKrI,EAAK0K,SAASxG,EAAU0I,GAAS7F,QAAQ,MAAO,QAE5D,MAAMqI,EAAepL,EAAS6H,GAASzI,KACvCqE,EAAOoE,GAAW,CAChB,CAACuD,EAAe,GAAGA,iBAA8B,gBAAiBlH,EAEtE,CAEA,OADAlJ,EAAOmB,KAAK,yBACLsH,CACT,CI/DkB4H,CAAYxG,EAAW7E,GAGvC,IAAK,MAAM6H,KAAW5D,EAAS,CAC7BjJ,EAAOmB,KAAK,kBAAkB0L,KAC9B,IAAII,EAAYC,KAAKC,MACrB,MAAMJ,EAAY/H,EAAS6H,GACrBiC,EAAU9N,EAAKC,KAAK4I,EAAWkD,EAAU3I,MACzC4I,EAAWhM,EAAKC,KAAK2L,EAAYC,EAASE,EAAU3I,MAI1DuI,EAAK,CACH9C,YACA+C,aACAE,UACA7D,UACA4D,UACAE,YACAC,aAMF6B,EAAU,CACRhF,YACA+C,aACAkC,UACA9B,WACA+B,YAAa/F,EAAYC,GACzB+F,SAAU,CAACzM,KAIbb,EADmBV,EAAKC,KAAK2L,EAAYC,IAEzC7M,EAAOmB,KAAK,oBAAoB0L,KAChC7M,EAAOmB,KACL,oBAAoB0L,QAClBK,KAAKC,MAAQF,MAGnB,CAIA,OAFAjN,EAAOmB,KAAK,qBAAqB+L,KAAKC,MAAQF,OA3C5B,CAAA,CA8CpB,mBCvDO5F,eAAyBlC,GAI9B,MAAQhC,MAAO+B,EAAU9E,OAAQoH,EAAS8I,MAAEA,GAAUnL,EACtD,IAAI8H,EAAYC,KAAKC,MACrBnN,EAAOG,KAAKqH,GAAW,GACvBxH,EAAOmB,KAAK,4BACZnB,EAAOmB,KAAK,yBAAyB8L,KACrC,IA0BE,aAtBM3F,EAAU,CACdpC,WACAC,OAAQ,CACNC,kBAAkBkL,eAAAA,EAAOlL,mBAAoBxC,EAC7CoD,sBACEsK,eAAAA,EAAOtK,uBAAwBnD,EACjCyD,oBAAqBgK,aAAK,EAALA,EAAOhK,6BAM1B+I,EAAS,CACbxF,UAAW3E,EACX0H,WAAYpF,UClBXH,eAA2BG,GAChC,IAAIyF,EAAYC,KAAKC,MACrBnN,EAAOmB,KAAK,sBAAsB8L,KAClC,MAAMsD,EAAavP,EAAKC,KAAKuG,EAAWrF,GAClCgD,EAASqB,KAAKC,MAAM7G,EAAG8G,aAAa6J,EAAY,UAChDvL,EAAWG,EAAOH,SACxB,IAAK,MAAM6H,KAAW7H,EAAU,CAK9B,MAAMwL,EAAYxP,EAAKC,KAAKuG,EAAWqF,GACjC4D,EAAazP,EAAKC,KAAKuG,EAAW,GAAGqF,IAAUrK,KAC/CkO,EAAc1P,EAAKC,KACvBuG,EACA,GAAGqF,IAAUpK,KAEf/C,EAAc+Q,GACd/Q,EAAcgR,GACd9Q,EAAG+Q,OAAOH,EAAWC,EAAY,CAAE1Q,WAAW,IAC9CH,EAAG+Q,OAAOH,EAAWE,EAAa,CAAE3Q,WAAW,IAC/C6D,EAAoB6M,GACpBjN,EAAkBkN,GAKlB1L,EAAS,GAAG6H,IAAUrK,KAAsBkG,OAAAqD,OAAArD,OAAAqD,OAAA,CAAA,EACvC/G,EAAS6H,KACZ5I,SAAU,GACV2M,SAAU,GACVxQ,OAAQ,GAAGyM,IAAUrK,IAAsBF,MAE7C0C,EAAS,GAAG6H,IAAUpK,KAAuBiG,OAAAqD,OAAArD,OAAAqD,OAAA,CAAA,EACxC/G,EAAS6H,KACZ3I,UAAW,GACXC,UAAW,GACX/D,OAAQ,GAAGyM,IAAUpK,IAAuBH,KAEhD,CACA1C,EAAGkJ,cAAcyH,EAAY/J,KAAKuC,UAAU5D,EAAQ,KAAM,IAC1DnF,EAAOmB,KAAK,oBAAoB+L,KAAKC,MAAQF,MAC/C,CDlBU4D,CAAYrJ,GAEX,CACLsJ,WAAW,EAEf,CAAE,MAAOzP,GAEP,OADArB,EAAOqB,MAAM,cAAcA,EAAM0P,WAC1B,CACLD,WAAW,EACXE,SAAU3P,EAAM0P,QAEpB,SACE/Q,EAAOmB,KAAK,YAAY+L,KAAKC,MAAQF,MACvC,CACF,oBE/CO5F,eAAyBlC,GAI9B,MAAQhC,MAAO+B,EAAU9E,OAAQoH,EAAS8I,MAAEA,GAAUnL,EAEtDnF,EAAOG,KAAKqH,GAAW,GACvB,IA0BE,aAtBMF,EAAU,CACdpC,WACAC,OAAQ,CACNC,kBAAkBkL,eAAAA,EAAOlL,mBAAoBxC,EAC7CoD,sBACEsK,eAAAA,EAAOtK,uBAAwBnD,EACjCyD,oBAAqBgK,aAAK,EAALA,EAAOhK,6BAM1B+I,EAAS,CACbxF,UAAW3E,EACX0H,WAAYpF,UCtBZ,SAAoBA,GACxBxH,EAAOmB,KAAK,mBACZ,MAAM8P,EAAqBjQ,EAAKC,KAAKuG,EAAWrF,GAChD,IAAI+O,EACJ,IACEA,EAAiB1K,KAAKC,MAAM7G,EAAG8G,aAAauK,EAAoB,SAClE,CAAE,MAAOtN,GAIP,YAHA3D,EAAOqB,MACL,aAAa4P,WAA4BtN,EAAIoN,UAGjD,CAEA,MAAM/L,EAAWkM,EAAelM,SAChC,GAAKA,GAAgC,iBAAbA,EAAxB,CAKA,IAAK,MAAM6H,KAAWnE,OAAOC,KAAK3D,GAAW,CAC3C,MAAMmM,EAASnQ,EAAKC,KAAKuG,EAAWqF,GACpC,IAAKjN,EAAGC,WAAWsR,GAAS,CAC1BnR,EAAOsB,KAAK,kBAAkB6P,KAC9B,QACF,CAEA,MAAMrP,EAAQlC,EAAGmC,YAAYoP,GAC7B,IAAK,MAAMnP,KAAQF,EAAO,CACxB,MAAMoN,EAAUlO,EAAKC,KAAKkQ,EAAQnP,GAC5BmN,EAAWnO,EAAKC,KAAKuG,EAAWxF,GAEtC,IACE,MAAMwN,EAAO5P,EAAG+B,SAASuN,GACzB,GAAIM,EAAKlM,SACP1D,EAAGwP,aAAaF,EAASC,QACpB,GAAIK,EAAK5N,cACdhC,EAAG+Q,OAAOzB,EAASC,EAAU,CAAEpP,WAAW,SACrC,GAAIyP,EAAK4B,iBAAkB,CAChC,MAAMC,EAAazR,EAAG0R,aAAapC,GAE/BtP,EAAGC,WAAWsP,IAChBvP,EAAGsC,OAAOiN,EAAU,CAAEM,OAAO,IAE/B7P,EAAG2R,YACDF,EACAlC,EACAK,EAAK5N,cAAgB,MAAQ,OAEjC,CACA5B,EAAOmB,KAAK,YAAY+N,QAAcC,IACxC,CAAE,MAAOxL,GACP3D,EAAOqB,MAAM,WAAW6N,WAAiBvL,EAAIoN,UAC/C,CACF,CAGA,IACEnR,EAAGsC,OAAOiP,EAAQ,CAAEpR,WAAW,EAAM0P,OAAO,IAC5CzP,EAAOmB,KAAK,mBAAmBgQ,IACjC,CAAE,MAAOxN,GACP3D,EAAOqB,MAAM,oBAAoB8P,WAAgBxN,EAAIoN,UACvD,CACF,CAEA/Q,EAAOmB,KAAK,eA/CZ,MAFEnB,EAAOqB,MAAM,6BAkDjB,CDrCUmQ,CAAUhK,GAET,CACLsJ,WAAW,EAEf,CAAE,MAAOzP,GACP,MAAO,CACLyP,WAAW,EACXE,SAAU3P,EAAM0P,QAEpB,CACF,0BExCO1J,iBACL,MAAMoK,EAAWzQ,EAAKC,KAAKyQ,UAAW,QACjC9R,EAAGC,WAAW4R,IAAW7R,EAAGE,UAAU2R,GAC3C,MAAME,QCSDtK,iBAIL,OAAOzC,CAkBT,CD/BsBgN,GACpBrC,QAAQ/N,IAAI,YAAamQ,GCkCrB,SACJA,EAIAE,GAEA,IAAK,MAAMC,KAAQH,EAAO,CACxB,MAAQ9M,GAAIkN,EAAM/M,SAAEA,GAAa8M,EAC3BE,EAAUhR,EAAKC,KAAK4Q,EAASE,GAC9BnS,EAAGC,WAAWmS,IAAUpS,EAAGE,UAAUkS,GAE1C,IAAK,MAAMC,KAAejN,EAAU,CAClC,MAAMkN,EAAclN,EAASiN,IACvBhO,SAAEA,GAAaiO,EAEf5H,EAAO6H,QAAQ,iBAClBC,SAAS,YAAYnO,MACrBoK,WACHkB,QAAQ/N,IAAI,gCAAiCyC,GAC7C,MAAMoO,EAAW,GAAGJ,QACdzG,EAAWxK,EAAKC,KAAK+Q,EAASK,GACpCzS,EAAGkJ,cAAc0C,EAAUlB,EAC7B,CACF,CACF,CD1DEgI,CAAyBX,EAAOF,GAChC,MAAMc,EAAmB,CAAA,EACzB,IAAK,MAAMT,KAAQH,EAAO,CACxB,MAAQ9M,GAAIkN,EAAM/M,SAAEA,GAAa8M,EAC3BE,EAAUhR,EAAKC,KAAKwQ,EAAUM,GACpCQ,EAAiBR,GAAUjP,EAAekP,EAC5C,CAEA,MAAMQ,EAAgB,CAAA,EACtB7P,EAAuBiE,QAAQ6L,IAC7BD,EAAcC,GAAO,KAGvB,MAAMC,EAAgB,CAAA,EACtB,IAAK,MAAMZ,KAAQH,EAAO,CACxB,MAAQ9M,GAAIkN,EAAM/M,SAAEA,GAAa8M,EAC3BpM,EAAW6M,EAAiBR,GAClC,GAAIrM,EAAWhD,EAAmB,SAClC,IAAIiQ,EAAc,KAClB,IAAK,MAAMC,KAAUjQ,EAAwB,CAC3C,MAAMkQ,EAAY7R,EAAKC,KAAKwQ,EAAUmB,GACjChT,EAAGC,WAAWgT,IAAYjT,EAAGE,UAAU+S,GAK5C,GAJuBL,EAAcI,GAAQ5G,OAC3C,CAAC8G,EAAKC,IAAQD,EAAMP,EAAiBQ,GACrC,GAEmBrN,GAAYhD,EAAmB,CAElD,MAAMsQ,EAAShS,EAAKC,KAAKwQ,EAAUM,GAC7BkB,EAAUjS,EAAKC,KAAK4R,EAAWd,GACrCnS,EAAG+Q,OAAOqC,EAAQC,EAAS,CAAElT,WAAW,IACxCyS,EAAcI,GAAQvJ,KAAK0I,GAC3BY,EAAcC,EACd,KACF,CACF,CACA,GAAKD,EAAL,CAGAD,EAAcX,GAAU,CACtBU,IAAKE,EACL3N,SAAU,CAAA,GAEZ,IAAK,MAAMiN,KAAejN,EAAU,CAClC,MAAM4D,EAAM5D,EAASiN,GACrB1C,QAAQ/N,IAAI,iCAAkCyQ,EAAarJ,GAC3D8J,EAAcX,GAAQ/M,SAASiN,GAAe,CAC5C7N,KAAMwE,EAAIxE,KACVC,KAAMuE,EAAIvE,KAEVF,UAAWyE,EAAIzE,UACfD,UAAW0E,EAAI1E,UAEnB,CAjBkB,CAkBpB,CAEA,MAAMgP,EAAalS,EAAKC,KAAKwQ,EAAU,wBACvC7R,EAAGkJ,cAAcoK,EAAY1M,KAAKuC,UAAU2J,EAAe,KAAM,GAAI,SACrEnD,QAAQ/N,IAAI,4BAA6B0R,EAC3C,yBE3DO7L,eAA8BG,GACnCxH,EAAOmB,KAAK,gCACZ,MAAMoP,EAAavP,EAAKC,KAAKuG,EAAWrF,GAClCgD,EAASqB,KAAKC,MAAM7G,EAAG8G,aAAa6J,EAAY,UAChDvL,EAAWG,EAAOH,SAClBjB,EAAcoB,EAAOgO,cAAgB,CAAA,EAC3C,IAAK,MAAMtG,KAAW7H,EAAU,CAC9B,GAAI6H,EAAQpJ,SAASjB,GAAsB,CAIzC,MAAMuK,EAAY/H,EAAS6H,GACrBuG,EAAiBvG,EAAQ+C,MAAMpN,GAAqB,GACrDuB,EAAYqP,KACfrP,EAAYqP,GAAkB,CAAA,GAEhCrP,EAAYqP,GAAe1K,OAAAqD,OAAArD,OAAAqD,OAAA,GACtBhI,EAAYqP,IAAe,CAC9BhP,KAAM2I,EAAU3I,KAChBiP,YAAatG,EAAU3M,OACvBwQ,SAAU7D,EAAUpF,IACpBtD,KAAM0I,EAAU1I,cAEXW,EAAS6H,EAClB,CACA,GAAIA,EAAQpJ,SAAShB,GAAuB,CAC1C,MAAM2Q,EAAiBvG,EAAQ+C,MAAMnN,GAAsB,GACrDsK,EAAY/H,EAAS6H,GAC3B9I,EAAYqP,GAAe1K,OAAAqD,OAAArD,OAAAqD,OAAA,CAAA,EACtBhI,EAAYqP,IAAe,CAC9BhP,KAAM2I,EAAU3I,KAChBkP,aAAcvG,EAAU3M,OACxB+D,UAAW4I,EAAUpF,aAEhB3C,EAAS6H,EAClB,CACF,CACA1H,EAAOgO,aAAepP,EACtBnE,EAAGkJ,cAAcyH,EAAY/J,KAAKuC,UAAU5D,EAAQ,KAAM,IAC1DnF,EAAOmB,KAAK,6BACd"}
@@ -7,6 +7,6 @@ export declare function checkMainPackageSize({ entryDir, limit, }: {
7
7
  entryDir: string;
8
8
  limit: number;
9
9
  }): void;
10
- export declare function checkMainPackage(entryDir: string, context: {
10
+ export declare function checkMainPackage(entryDir: string, config: {
11
11
  mainPackageSizeLimit: number;
12
12
  }): void;
@@ -6,4 +6,4 @@ export declare function checkConfig(entryDir: string): void;
6
6
  * @returns
7
7
  */
8
8
  export declare function checkProjectSize(entryDir: string, limit: number): void;
9
- export declare function checkProject(entryDir: string, config?: Pick<CheckConfig, 'projectSizeLimit'>): void;
9
+ export declare function checkProject(entryDir: string, config: Pick<CheckConfig, 'projectSizeLimit'>): void;
@@ -0,0 +1,5 @@
1
+ import { BuildConfig } from '../../src/typings';
2
+ export declare function debugPkgs(config: BuildConfig): Promise<{
3
+ isSuccess: boolean;
4
+ errorMsg?: string;
5
+ }>;
@@ -1,2 +1,6 @@
1
- export { downloadOdrPkgs, writeOdrConfig } from './odrPkgs';
1
+ export { downloadOdrPkgs, writeOdrConfig, makeOdrPkgs } from './odrPkgs';
2
2
  export { buildPkgs } from './buildPkgs';
3
+ export { checkPkgs } from './checkPkgs';
4
+ export { makePkgs } from './makePkgs';
5
+ export { mergePkgs } from './mergePkgs';
6
+ export { debugPkgs } from './debugPkgs';
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "ttmg-pack",
3
3
  "author": "ttmg",
4
- "version": "0.0.8",
4
+ "version": "0.0.9",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "test": "node __test__/index.js",
9
9
  "build": "rollup -c && tsc-alias -p tsconfig.json",
10
10
  "prepublishOnly": "npm run build",
11
- "debug": "rollup -c --watch"
11
+ "watch": "rollup -c --watch",
12
+ "debug": "node __test__/debug.js"
12
13
  },
13
14
  "files": [
14
15
  "dist"