@raolin2025/claude-code-node 2.7.8 → 2.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raolin2025/claude-code-node",
3
- "version": "2.7.8",
3
+ "version": "2.7.9",
4
4
  "description": "Node.js AI Code Agent CLI - Zero dependencies, pure JavaScript, security hardened, multi-channel notifications, Telegram & QQ Bot remote programming, rich media upload, multi-account management",
5
5
  "type": "module",
6
6
  "main": "src/core/index.js",
@@ -12,7 +12,7 @@ import { mkdtempSync, writeFileSync, rmSync } from 'fs'
12
12
  import { tmpdir } from 'os'
13
13
  import { join } from 'path'
14
14
 
15
- import { npmPublishTool } from '../tools/npm-publish.js'
15
+ import { npmPublishTool, parsePackJson } from '../tools/npm-publish.js'
16
16
 
17
17
  describe('NpmPublish 工具结构', () => {
18
18
  test('工具元数据正确', () => {
@@ -24,6 +24,29 @@ describe('NpmPublish 工具结构', () => {
24
24
  })
25
25
  })
26
26
 
27
+ describe('parsePackJson 打包解析', () => {
28
+ test('解析真实 npm pack --json 输出(冒号后有空格),不产生 EISDIR 目录 bug', () => {
29
+ // npm pack --json 实际输出:嵌套包名键,且 "filename" 冒号后带空格
30
+ const packJson = JSON.stringify({
31
+ '@raolin2025/claude-code-node': {
32
+ id: '@raolin2025/claude-code-node@2.7.8',
33
+ name: '@raolin2025/claude-code-node',
34
+ version: '2.7.8',
35
+ filename: 'raolin2025-claude-code-node-2.7.8.tgz',
36
+ },
37
+ }, null, 2) // 带缩进,模拟真实输出
38
+ assert.strictEqual(parsePackJson(packJson), 'raolin2025-claude-code-node-2.7.8.tgz')
39
+ })
40
+
41
+ test('无 filename 时抛错', () => {
42
+ assert.throws(() => parsePackJson(JSON.stringify({ '@x/y': { version: '1.0.0' } })), /filename/)
43
+ })
44
+
45
+ test('非法 JSON 抛错', () => {
46
+ assert.throws(() => parsePackJson('not-json'), SyntaxError)
47
+ })
48
+ })
49
+
27
50
  describe('bumpVersion 版本增量', () => {
28
51
  let tmp
29
52
  after(() => { if (tmp) rmSync(tmp, { recursive: true, force: true }) })
@@ -87,6 +87,21 @@ function sh(cmd, cwd) {
87
87
  return execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
88
88
  }
89
89
 
90
+ /**
91
+ * 解析 `npm pack --json` 输出,提取 tarball 文件名。
92
+ * 输出形如 `{"@scope/pkg":{"filename":"pkg-1.0.0.tgz",...}}`(嵌套包名键)。
93
+ * @param {string} packJson npm pack --json 的原始输出
94
+ * @returns {string} tarball 文件名
95
+ * @throws 无法解析时抛错
96
+ */
97
+ export function parsePackJson(packJson) {
98
+ const data = JSON.parse(packJson)
99
+ const meta = Object.values(data)[0] || {}
100
+ const filename = meta.filename
101
+ if (!filename) throw new Error('npm pack --json 输出缺少 filename')
102
+ return filename
103
+ }
104
+
90
105
  /** 读取 ~/.npmrc 中的 token */
91
106
  function getNpmToken() {
92
107
  try {
@@ -261,7 +276,10 @@ async function doPublish({ cwd, version, commitMessage, squash, doGitPush, doNpm
261
276
  // 3. 打包
262
277
  let tarballPath = ''
263
278
  try {
264
- tarballPath = join(cwd, sh('npm pack --json', cwd).match(/"filename":"([^"]+)"/)?.[1] || '')
279
+ // JSON 解析提取 filename(旧正则 /"filename":"([^"]+)"/ 因冒号后有空格而匹配不到,
280
+ // 导致 join(cwd,'') 得到目录 → 后续 readFileSync EISDIR,见 parsePackJson 注释)。
281
+ const filename = parsePackJson(sh('npm pack --json', cwd))
282
+ tarballPath = join(cwd, filename)
265
283
  steps.push(`打包: ${tarballPath.split('/').pop()}`)
266
284
  } catch (e) {
267
285
  return { ok: false, steps, error: `打包失败: ${e.message}` }