@ttmg/cli 0.1.0-beta.12 → 0.1.0-beta.14

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +155 -120
  3. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -26,3 +26,11 @@ feat: 先关闭自动上传能力
26
26
  ## 0.1.0-beta.12
27
27
 
28
28
  feat: 支持文件变更监听,告知浏览器文件变更,提醒开发者重新加载游戏
29
+
30
+ ## 0.1.0-beta.13
31
+
32
+ 1. 支持 sourcemap
33
+ 2. 优化上传环节产物,过滤 sourcemap 文件,提高上传效率
34
+
35
+ ## 0.1.0-beta.14
36
+ 1. 修复 client key 未成功写入 mock meta 的问题,导致不一致
package/dist/index.js CHANGED
@@ -16,11 +16,31 @@ var require$$6 = require('crypto');
16
16
  var require$$5$1 = require('archiver');
17
17
  var multer = require('multer');
18
18
  var WebSocket = require('ws');
19
+ var glob = require('glob');
19
20
  var got = require('got');
20
21
  var FormData = require('form-data');
21
22
  var ttmgPack = require('ttmg-pack');
22
23
  var qrcode = require('qrcode-terminal');
23
24
 
25
+ function _interopNamespaceDefault(e) {
26
+ var n = Object.create(null);
27
+ if (e) {
28
+ Object.keys(e).forEach(function (k) {
29
+ if (k !== 'default') {
30
+ var d = Object.getOwnPropertyDescriptor(e, k);
31
+ Object.defineProperty(n, k, d.get ? d : {
32
+ enumerable: true,
33
+ get: function () { return e[k]; }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ n.default = e;
39
+ return Object.freeze(n);
40
+ }
41
+
42
+ var glob__namespace = /*#__PURE__*/_interopNamespaceDefault(glob);
43
+
24
44
  function getDefaultExportFromCjs (x) {
25
45
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
26
46
  }
@@ -275,10 +295,10 @@ async function openUrl(url) {
275
295
  '--auto-open-devtools-for-tabs', // 自动打开 DevTools
276
296
  '--no-default-browser-check',
277
297
  '--allow-insecure-localhost',
278
- '--ignore-certificate-errors',
279
298
  '--allow-running-insecure-content',
280
299
  '--remote-allow-origins=*',
281
300
  '--user-data-dir=/tmp/chrome-debug-profile',
301
+ '--disable-popup-blocking',
282
302
  ],
283
303
  });
284
304
  await new Promise(() => { });
@@ -676,6 +696,79 @@ function requireBundle () {
676
696
  var bundleExports = requireBundle();
677
697
  var index = /*@__PURE__*/getDefaultExportFromCjs(bundleExports);
678
698
 
699
+ const CONFIG_DIR = path.join(os.homedir(), '.ttmg-cli');
700
+ path.join(CONFIG_DIR, 'config.json');
701
+ /**
702
+ * 获取 Client Key(选择或输入)
703
+ */
704
+ function getClientKey() {
705
+ /**
706
+ * 读取 project.config.json 中的 appid/appId
707
+ */
708
+ const projectConfigPath = path.join(process.cwd(), 'project.config.json');
709
+ let clientKey;
710
+ try {
711
+ const projectConfig = JSON.parse(fs.readFileSync(projectConfigPath, 'utf-8'));
712
+ clientKey = projectConfig.appid || projectConfig.appId;
713
+ }
714
+ catch (e) {
715
+ console.log('read project.config.json failed', e);
716
+ clientKey = '';
717
+ }
718
+ if (clientKey) {
719
+ return clientKey;
720
+ }
721
+ else {
722
+ console.log(chalk.red.bold('No appid found in project.config.json, you should provide it in project.config.json'));
723
+ process.exit(1);
724
+ }
725
+ // const keys = readClientKeys();
726
+ // if (keys.length > 0) {
727
+ // // 有历史 key,展示选择框
728
+ // const { selectedKey } = await inquirer.prompt([
729
+ // {
730
+ // type: 'list',
731
+ // name: 'selectedKey',
732
+ // message: 'Please select your game id(client_key):',
733
+ // choices: [...keys, new inquirer.Separator(), 'Add new game id'],
734
+ // },
735
+ // ]);
736
+ // if (selectedKey === 'Add new game id') {
737
+ // // 输入新 key
738
+ // const { newKey } = await inquirer.prompt([
739
+ // {
740
+ // type: 'input',
741
+ // name: 'newKey',
742
+ // message: 'Please input your new game id(client_key):',
743
+ // validate: (input: string) => (input ? true : 'Please input game id'),
744
+ // },
745
+ // ]);
746
+ // saveClientKey(newKey);
747
+ // clientKey = newKey;
748
+ // } else {
749
+ // clientKey = selectedKey;
750
+ // }
751
+ // } else {
752
+ // // 没有历史 key,让用户输入
753
+ // const { newKey } = await inquirer.prompt([
754
+ // {
755
+ // type: 'input',
756
+ // name: 'newKey',
757
+ // message: 'Please input your game id(client_key):',
758
+ // validate: (input: string) => (input ? true : 'Please input game id'),
759
+ // },
760
+ // ]);
761
+ // saveClientKey(newKey);
762
+ // clientKey = newKey;
763
+ // }
764
+ // return clientKey;
765
+ }
766
+
767
+ function getOutputDir() {
768
+ const clientKey = getClientKey();
769
+ return path.join(os.homedir(), '__TTMG__', clientKey);
770
+ }
771
+
679
772
  class Store {
680
773
  constructor(initialState) {
681
774
  this.listeners = [];
@@ -746,6 +839,24 @@ async function createServer() {
746
839
  app.use(express.json());
747
840
  // 解析 FormData body
748
841
  app.use(express.urlencoded({ extended: true }));
842
+ /**
843
+ * 支持文件访问
844
+ */
845
+ const outputDir = getOutputDir();
846
+ /**
847
+ *
848
+ */
849
+ app.use(express.static(outputDir));
850
+ /**
851
+ * 支持获取文件
852
+ */
853
+ app.get('/game/files/:fileName', async (req, res) => {
854
+ const { fileName } = req.params;
855
+ res.sendFile(path.join(outputDir, fileName));
856
+ });
857
+ /**
858
+ * 支持文件访问
859
+ */
749
860
  /**
750
861
  * TODO: 提供的接口供客户端进行调用,告诉 NodeServer 客户端的 host 和 port
751
862
  */
@@ -797,79 +908,6 @@ function closeServer() {
797
908
  });
798
909
  }
799
910
 
800
- const CONFIG_DIR = path.join(os.homedir(), '.ttmg-cli');
801
- path.join(CONFIG_DIR, 'config.json');
802
- /**
803
- * 获取 Client Key(选择或输入)
804
- */
805
- function getClientKey() {
806
- /**
807
- * 读取 project.config.json 中的 appid/appId
808
- */
809
- const projectConfigPath = path.join(process.cwd(), 'project.config.json');
810
- let clientKey;
811
- try {
812
- const projectConfig = JSON.parse(fs.readFileSync(projectConfigPath, 'utf-8'));
813
- clientKey = projectConfig.appid || projectConfig.appId;
814
- }
815
- catch (e) {
816
- console.log('read project.config.json failed', e);
817
- clientKey = '';
818
- }
819
- if (clientKey) {
820
- return clientKey;
821
- }
822
- else {
823
- console.log(chalk.red.bold('No appid found in project.config.json, you should provide it in project.config.json'));
824
- process.exit(1);
825
- }
826
- // const keys = readClientKeys();
827
- // if (keys.length > 0) {
828
- // // 有历史 key,展示选择框
829
- // const { selectedKey } = await inquirer.prompt([
830
- // {
831
- // type: 'list',
832
- // name: 'selectedKey',
833
- // message: 'Please select your game id(client_key):',
834
- // choices: [...keys, new inquirer.Separator(), 'Add new game id'],
835
- // },
836
- // ]);
837
- // if (selectedKey === 'Add new game id') {
838
- // // 输入新 key
839
- // const { newKey } = await inquirer.prompt([
840
- // {
841
- // type: 'input',
842
- // name: 'newKey',
843
- // message: 'Please input your new game id(client_key):',
844
- // validate: (input: string) => (input ? true : 'Please input game id'),
845
- // },
846
- // ]);
847
- // saveClientKey(newKey);
848
- // clientKey = newKey;
849
- // } else {
850
- // clientKey = selectedKey;
851
- // }
852
- // } else {
853
- // // 没有历史 key,让用户输入
854
- // const { newKey } = await inquirer.prompt([
855
- // {
856
- // type: 'input',
857
- // name: 'newKey',
858
- // message: 'Please input your game id(client_key):',
859
- // validate: (input: string) => (input ? true : 'Please input game id'),
860
- // },
861
- // ]);
862
- // saveClientKey(newKey);
863
- // clientKey = newKey;
864
- // }
865
- // return clientKey;
866
- }
867
-
868
- function getOutputDir() {
869
- const clientKey = getClientKey();
870
- return path.join(os.homedir(), '__TTMG__', clientKey);
871
- }
872
-
873
911
  async function uploadGame() {
874
912
  const outputDir = getOutputDir();
875
913
  console.log(chalk.yellow.bold('Start compress game resource'));
@@ -881,58 +919,40 @@ async function uploadGame() {
881
919
  isSuccess: res?.statusCode === 200,
882
920
  };
883
921
  }
884
- function zipDirectory(sourceDir, outPath) {
885
- return new Promise((resolve, reject) => {
886
- const output = fs.createWriteStream(outPath); // 修正:传入输出路径
887
- const archive = require$$5$1('zip', { zlib: { level: 9 } });
888
- output.on('close', () => {
889
- // console.log('Compress directory done');
890
- resolve();
891
- });
892
- output.on('error', err => {
893
- // console.error('Compress directory error:', err);
894
- reject(err);
895
- });
896
- archive.on('error', err => {
897
- reject(err);
898
- });
922
+ async function zipDirectory(sourceDir, outPath) {
923
+ const output = fs.createWriteStream(outPath);
924
+ const archive = require$$5$1('zip', { zlib: { level: 9 } });
925
+ return new Promise(async (resolve, reject) => {
926
+ output.on('close', () => resolve());
927
+ output.on('error', err => reject(err));
928
+ archive.on('error', err => reject(err));
899
929
  archive.pipe(output);
900
- archive.directory(sourceDir, false);
901
- archive.finalize();
930
+ try {
931
+ // 注意这里用 await glob.glob
932
+ const files = await glob__namespace.glob('**/*', {
933
+ cwd: sourceDir,
934
+ nodir: true,
935
+ ignore: '**/*.js.map',
936
+ });
937
+ files.forEach(file => {
938
+ archive.file(path.join(sourceDir, file), { name: file });
939
+ });
940
+ archive.finalize();
941
+ }
942
+ catch (err) {
943
+ reject(err);
944
+ }
902
945
  });
903
946
  }
904
- /**
905
- * 上传 zip 文件到指定接口
906
- * @param zipFilePath zip 文件路径
907
- * @param uploadUrl 上传接口
908
- */
909
- // export async function uploadZip(zipPath: string) {
910
- // const form = new FormData();
911
- // form.append('file', fs.createReadStream(zipPath), 'upload.zip');
912
- // try {
913
- // console.log(chalk.yellow.bold('Start upload resource to client'));
914
- // const { clientServerHost, clientServerPort } = store.getState();
915
- // const res = await axios.post(
916
- // `http://${clientServerHost}:${clientServerPort}/game/upload`,
917
- // form,
918
- // {
919
- // headers: form.getHeaders(),
920
- // },
921
- // );
922
- // fs.unlinkSync(zipPath);
923
- // return res;
924
- // } catch (err: any) {
925
- // console.error('Upload resource to client failed:', err.message);
926
- // }
927
- // }
928
- // 使用 require 语法,完全兼容 CommonJS
929
947
  async function uploadZip(zipPath) {
930
948
  const form = new FormData();
931
949
  form.append('file', fs.createReadStream(zipPath), {
932
950
  filename: 'upload.zip',
933
951
  contentType: 'application/zip',
934
952
  });
935
- console.log(chalk.yellow.bold('Start upload resource to client'));
953
+ // 帮我计算下文件大小,变成 MB 为单位
954
+ const fileSize = fs.statSync(zipPath).size / 1024 / 1024;
955
+ console.log(chalk.yellow.bold(`Start upload resource to client, size: ${fileSize.toFixed(2)} MB`));
936
956
  const { clientServerHost, clientServerPort } = store.getState();
937
957
  const url = `http://${clientServerHost}:${clientServerPort}/game/upload`;
938
958
  try {
@@ -948,6 +968,7 @@ async function uploadZip(zipPath) {
948
968
  process.stdout.write(`\r${chalk.cyan('Uploading progress: ')}${chalk.green(percent + '%')}`);
949
969
  // 生成标准的 百分比
950
970
  wsServer?.sendUploadStatus('process', {
971
+ status: 'process',
951
972
  progress: `${percent}%`,
952
973
  });
953
974
  });
@@ -1015,18 +1036,22 @@ class WsServer {
1015
1036
  .then(res => {
1016
1037
  if (res.isSuccess) {
1017
1038
  this.sendUploadStatus('success', {
1039
+ status: 'success',
1018
1040
  packages: store.getState().packages,
1041
+ clientKey: getClientKey(),
1019
1042
  isSuccess: res.isSuccess,
1020
1043
  });
1021
1044
  }
1022
1045
  else {
1023
1046
  this.sendUploadStatus('error', {
1047
+ status: 'error',
1024
1048
  errMsg: res.errorMsg,
1025
1049
  });
1026
1050
  }
1027
1051
  })
1028
1052
  .catch(() => {
1029
1053
  this.sendUploadStatus('error', {
1054
+ status: 'error',
1030
1055
  isSuccess: false,
1031
1056
  });
1032
1057
  console.log(chalk.red.bold('Start upload resource to client failed!'));
@@ -1101,10 +1126,20 @@ async function prepareResource() {
1101
1126
  if (!fs.existsSync(outputDir)) {
1102
1127
  fs.mkdirSync(outputDir, { recursive: true });
1103
1128
  }
1104
- await console.log(entryDir);
1105
1129
  const { isSuccess, errorMsg, packages } = await ttmgPack.debugPkgs({
1106
1130
  entry: entryDir,
1107
1131
  output: outputDir,
1132
+ dev: {
1133
+ enable: true,
1134
+ port: DEV_PORT,
1135
+ host: 'localhost',
1136
+ enableSourcemap: true,
1137
+ enableLog: false,
1138
+ },
1139
+ build: {
1140
+ pkgSizeLimit: 30 * 1024 * 1024,
1141
+ mainPkgSizeLimit: 4 * 1024 * 1024,
1142
+ },
1108
1143
  });
1109
1144
  if (!isSuccess) {
1110
1145
  console.log(chalk.redBright('Build game package failed, Please check the error message below:'));
@@ -1123,12 +1158,12 @@ async function prepareResource() {
1123
1158
  async function watchChange() {
1124
1159
  let debounceTimer = null;
1125
1160
  fs.watch(process.cwd(), (eventType, filename) => {
1126
- console.log(chalk.yellow('game resource change, restart to upload'));
1127
1161
  // 清除之前的定时器
1128
1162
  if (debounceTimer)
1129
1163
  clearTimeout(debounceTimer);
1130
1164
  // 重新设置定时器
1131
1165
  debounceTimer = setTimeout(async () => {
1166
+ console.log(chalk.yellow('game resource change, restart to upload'));
1132
1167
  await prepareResource();
1133
1168
  wsServer.send({
1134
1169
  method: 'resourceChange',
@@ -1187,7 +1222,7 @@ async function dev() {
1187
1222
  await watchChange();
1188
1223
  }
1189
1224
 
1190
- var version = "0.1.0-beta.12";
1225
+ var version = "0.1.0-beta.14";
1191
1226
  var pkg = {
1192
1227
  version: version};
1193
1228
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttmg/cli",
3
- "version": "0.1.0-beta.12",
3
+ "version": "0.1.0-beta.14",
4
4
  "description": "TikTok Mini Game Command Line Tool",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -34,6 +34,7 @@
34
34
  "estraverse": "^5.3.0",
35
35
  "express": "^5.1.0",
36
36
  "form-data": "^4.0.4",
37
+ "glob": "^11.0.3",
37
38
  "got": "^11.8.5",
38
39
  "inquirer": "^12.7.0",
39
40
  "jsdom": "^26.1.0",
@@ -41,7 +42,7 @@
41
42
  "open": "^10.2.0",
42
43
  "prettier": "^3.6.2",
43
44
  "qrcode-terminal": "^0.12.0",
44
- "ttmg-pack": "^0.0.19",
45
+ "ttmg-pack": "^0.0.20",
45
46
  "ws": "^8.18.3"
46
47
  },
47
48
  "devDependencies": {