@ttmg/cli 0.2.7-beta.1 → 0.2.7-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,8 +12,8 @@
12
12
  rel="stylesheet"
13
13
  />
14
14
  <title>TikTok Mini Games DevTool</title>
15
- <script type="module" crossorigin src="/assets/index-8YuJCDkr.js"></script>
16
- <link rel="stylesheet" crossorigin href="/assets/index-DwF7jabB.css">
15
+ <script type="module" crossorigin src="/assets/index-D7NxtOrr.js"></script>
16
+ <link rel="stylesheet" crossorigin href="/assets/index-CkX8so1Z.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 子线程进行编译
2
+ * 子线程进行编译(Worker)
3
3
  */
4
4
  const { debugPkgs } = require('ttmg-pack');
5
5
  const https = require('https');
@@ -10,57 +10,92 @@ const semver = require('semver');
10
10
  const { parentPort } = require('worker_threads');
11
11
  const { execSync } = require('child_process');
12
12
 
13
- // 获取 npm 最新版本
13
+ /**
14
+ * 获取 npm 最新版本
15
+ */
14
16
  function getLatestVersion(pkgName) {
15
17
  return new Promise((resolve, reject) => {
16
- https
17
- .get(
18
- `https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`,
19
- res => {
20
- let data = '';
21
- res.on('data', chunk => (data += chunk));
22
- res.on('end', () => {
23
- try {
24
- const info = JSON.parse(data);
25
- resolve(info.version);
26
- } catch (err) {
27
- resolve(null);
28
- }
29
- });
30
- },
31
- )
32
- .on('error', reject);
18
+ const req = https.get(
19
+ `https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`,
20
+ res => {
21
+ if (res.statusCode && res.statusCode >= 400) {
22
+ // 2xx 状态码直接返回 null(不阻断主流程)
23
+ res.resume(); // 消耗流避免 socket 泄漏
24
+ return resolve(null);
25
+ }
26
+ let data = '';
27
+ res.setEncoding('utf8');
28
+ res.on('data', chunk => (data += chunk));
29
+ res.on('end', () => {
30
+ try {
31
+ const info = JSON.parse(data);
32
+ resolve(info?.version ?? null);
33
+ } catch {
34
+ resolve(null);
35
+ }
36
+ });
37
+ res.on('error', () => resolve(null));
38
+ },
39
+ );
40
+ req.on('error', () => resolve(null));
41
+ req.setTimeout(8000, () => {
42
+ req.destroy();
43
+ resolve(null);
44
+ });
33
45
  });
34
46
  }
35
47
 
36
- // 获取全局已安装版本
48
+ /**
49
+ * 获取全局已安装版本
50
+ * 显式设置 stdio,避免在 worker/CI/守护环境中继承到非法 fd 触发 EBADF
51
+ */
37
52
  function getGlobalVersion(pkgName) {
38
53
  try {
39
- const output = execSync(`npm ls -g ${pkgName} --depth=0 --json`).toString();
54
+ const output = execSync(`npm ls -g ${pkgName} --depth=0 --json`, {
55
+ stdio: ['ignore', 'pipe', 'pipe'],
56
+ });
40
57
  const json = JSON.parse(output);
41
- return json.dependencies[pkgName].version;
42
- } catch (e) {
58
+ return json?.dependencies?.[pkgName]?.version ?? null;
59
+ } catch {
43
60
  return null;
44
61
  }
45
62
  }
46
63
 
47
64
  async function compile(context = {}) {
48
65
  try {
49
- const { clientKey, outputDir, entryDir, devPort } = context;
66
+ const { clientKey, outputDir, entryDir, devPort, mode } = context;
67
+
68
+ // 参数校验
50
69
  if (!clientKey) {
51
- if (context?.mode !== 'watch') {
52
- // 通知主线程错误
53
- parentPort.postMessage({ type: 'error', error: msg });
70
+ const message = '缺少 clientKey';
71
+ if (mode !== 'watch') {
72
+ parentPort?.postMessage({ type: 'error', error: message });
54
73
  return;
55
74
  }
56
- throw new Error(msg);
75
+ throw new Error(message);
57
76
  }
58
- if (!fs.existsSync(outputDir)) {
59
- fs.mkdirSync(outputDir, { recursive: true });
77
+
78
+ // 输出目录重建
79
+ try {
80
+ console.log(chalk(`🔍 Game local debug assets temp directory`, chalk.yellow.underline(outputDir)));
81
+ if (outputDir && fs.existsSync(outputDir)) {
82
+ fs.rmSync(outputDir, { recursive: true, force: true });
83
+ }
84
+ if (outputDir) {
85
+ fs.mkdirSync(outputDir, { recursive: true });
86
+ }
87
+ } catch (e) {
88
+ // 目录操作失败也上报
89
+ parentPort?.postMessage({
90
+ type: 'error',
91
+ error: `初始化输出目录失败: ${e?.message || e}`,
92
+ });
93
+ return;
60
94
  }
61
95
 
62
- parentPort.postMessage({ type: 'status', status: 'start' });
96
+ parentPort?.postMessage({ type: 'status', status: 'start' });
63
97
 
98
+ // 调用打包
64
99
  const { isSuccess, errorMsg, packages } = await debugPkgs({
65
100
  entry: entryDir,
66
101
  output: outputDir,
@@ -78,17 +113,20 @@ async function compile(context = {}) {
78
113
  mainPkgSizeLimit: 4 * 1024 * 1024,
79
114
  independentSubPkgSizeLimit: 4 * 1024 * 1024,
80
115
  },
116
+ // 如果 ttmg-pack 支持透传选项,可考虑加上 stdio/并发等设置:
117
+ // spawnOptions: { stdio: ['ignore', 'pipe', 'pipe'] },
118
+ // concurrency: 4,
81
119
  });
82
120
 
83
121
  if (!isSuccess) {
84
- parentPort.postMessage({
122
+ parentPort?.postMessage({
85
123
  type: 'status',
86
124
  status: 'end',
87
125
  isSuccess: false,
88
- errorMsg,
126
+ errorMsg: errorMsg || '构建失败',
89
127
  });
90
128
  } else {
91
- parentPort.postMessage({
129
+ parentPort?.postMessage({
92
130
  type: 'status',
93
131
  status: 'end',
94
132
  isSuccess: true,
@@ -96,40 +134,47 @@ async function compile(context = {}) {
96
134
  });
97
135
  }
98
136
  } catch (err) {
99
- parentPort.postMessage({ type: 'error', error: err.message || err });
137
+ parentPort?.postMessage({
138
+ type: 'error',
139
+ error: err?.message || String(err),
140
+ });
100
141
  }
101
142
  }
102
143
 
103
144
  async function checkUpdate() {
104
- const pkgName = '@ttmg/cli';
105
- const oldVersion = getGlobalVersion(pkgName);
106
- const newVersion = await getLatestVersion(pkgName);
107
- if (!newVersion) {
108
- return;
109
- }
145
+ try {
146
+ const pkgName = '@ttmg/cli';
147
+ const [oldVersion, newVersion] = await Promise.all([
148
+ getGlobalVersion(pkgName),
149
+ getLatestVersion(pkgName),
150
+ ]);
110
151
 
111
- if (!oldVersion) {
112
- console.log(chalk.yellow(`未检测到全局安装的 ${pkgName}`));
113
- return;
114
- }
152
+ if (!newVersion) {
153
+ return;
154
+ }
115
155
 
116
- if (oldVersion !== newVersion) {
117
- const oldVersionIsBeta = oldVersion.includes('beta');
118
- const newVersionIsBeta = newVersion.includes('beta');
119
- if (oldVersionIsBeta && newVersionIsBeta) {
156
+ if (!oldVersion) {
157
+ console.log(chalk.yellow(`未检测到全局安装的 ${pkgName}`));
120
158
  return;
121
159
  }
160
+
161
+ if (oldVersion === newVersion) return;
162
+
163
+ const oldVersionIsBeta = oldVersion.includes('beta');
164
+ const newVersionIsBeta = newVersion.includes('beta');
165
+ if (oldVersionIsBeta && newVersionIsBeta) return;
166
+
122
167
  const oldVersionMajor = semver.major(oldVersion);
123
168
  const newVersionMajor = semver.major(newVersion);
124
- if (oldVersionIsBeta && oldVersionMajor >= newVersionMajor) {
125
- return;
126
- }
169
+ if (oldVersionIsBeta && oldVersionMajor >= newVersionMajor) return;
127
170
 
128
171
  const message = `
129
172
  ${chalk.bold('Update available!')} ${chalk.red(oldVersion)} ${chalk.white('→')} ${chalk.green(newVersion)}.
130
173
  ${chalk.magenta('Changelog:')} ${chalk.cyan(`https://npmjs.com/package/${pkgName}/v/${newVersion}`)}
131
174
  To update, run: ${chalk.magenta(`npm i -g ${pkgName}`)}
132
175
  `.trim();
176
+
177
+ // 动态引入 boxen,避免主线程初始化时不必要的 require
133
178
  const boxen = require('boxen').default;
134
179
  console.log(
135
180
  boxen(message, {
@@ -139,15 +184,22 @@ To update, run: ${chalk.magenta(`npm i -g ${pkgName}`)}
139
184
  borderColor: 'yellowBright',
140
185
  }),
141
186
  );
187
+ } catch (e) {
188
+ // 更新检查失败不影响主流程
142
189
  }
143
190
  }
144
191
 
145
- // worker入口
146
- parentPort.on('message', async msg => {
147
- if (msg.type === 'compile') {
148
- await compile(msg.context);
149
- }
150
- if (msg.type === 'checkUpdate') {
151
- await checkUpdate();
152
- }
153
- });
192
+ // worker 入口
193
+ if (parentPort) {
194
+ parentPort.on('message', async msg => {
195
+ try {
196
+ if (msg?.type === 'compile') {
197
+ await compile(msg.context);
198
+ } else if (msg?.type === 'checkUpdate') {
199
+ await checkUpdate();
200
+ }
201
+ } catch (e) {
202
+ parentPort.postMessage({ type: 'error', error: e?.message || String(e) });
203
+ }
204
+ });
205
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttmg/cli",
3
- "version": "0.2.7-beta.1",
3
+ "version": "0.2.7-beta.2",
4
4
  "description": "TikTok Mini Game Command Line Tool",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -47,7 +47,7 @@
47
47
  "prettier": "^3.6.2",
48
48
  "qrcode": "^1.5.4",
49
49
  "semver": "^7.7.2",
50
- "ttmg-pack": "0.1.8",
50
+ "ttmg-pack": "0.2.1",
51
51
  "ws": "^8.18.3"
52
52
  },
53
53
  "devDependencies": {