@maiyunnet/kebab 7.1.2 → 7.2.0

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/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "7.1.2";
8
+ export declare const VER = "7.2.0";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  export declare const LIB_PATH: string;
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '7.1.2';
9
+ export const VER = '7.2.0';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/core.d.ts CHANGED
@@ -146,7 +146,9 @@ export declare function passThroughAppend(passThrough: stream.PassThrough, data:
146
146
  * --- 执行命令行 ---
147
147
  * @param command 命令字符串
148
148
  */
149
- export declare function exec(command: string): Promise<string | false>;
149
+ export declare function exec(command: string, options?: {
150
+ 'cwd'?: string;
151
+ }): Promise<string | false>;
150
152
  /**
151
153
  * --- 向主进程(或局域网同代码机子)发送广播将进行 reload 操作,等待回传 ---
152
154
  * --- 主要作用除代码热更新以外的其他情况 ---
@@ -166,6 +168,12 @@ export type TPm2Action = 'start' | 'stop' | 'restart';
166
168
  * @param hosts 局域网列表
167
169
  */
168
170
  export declare function sendPm2(name: string, action?: TPm2Action, hosts?: string[] | 'config'): Promise<string[]>;
171
+ /**
172
+ * --- 向本机或局域网 RPC 发送 npm install 操作 ---
173
+ * @param path 路径,如 /home/kebab/
174
+ * @param hosts 局域网列表
175
+ */
176
+ export declare function sendNpm(path: string, hosts?: string[] | 'config'): Promise<string[]>;
169
177
  /** --- 跨进程全局变量 --- */
170
178
  export declare const global: Record<string, any>;
171
179
  /**
@@ -182,7 +190,7 @@ export declare function setGlobal(key: string, data: any, hosts?: string[] | 'co
182
190
  */
183
191
  export declare function removeGlobal(key: string, hosts?: string[]): Promise<string[]>;
184
192
  /**
185
- * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新建 ---
193
+ * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新创建 ---
186
194
  * @param sourcePath zip 文件
187
195
  * @param path 要更新的目标路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路径开始算起
188
196
  * @param hosts 局域网多机部署,不设置默认本机部署
package/lib/core.js CHANGED
@@ -403,9 +403,11 @@ export async function passThroughAppend(passThrough, data, end = true) {
403
403
  * --- 执行命令行 ---
404
404
  * @param command 命令字符串
405
405
  */
406
- export function exec(command) {
406
+ export function exec(command, options = {}) {
407
407
  return new Promise(function (resolve) {
408
- cp.exec(command, function (err, stdout) {
408
+ cp.exec(command, {
409
+ 'cwd': options.cwd,
410
+ }, function (err, stdout) {
409
411
  if (err) {
410
412
  resolve(false);
411
413
  return;
@@ -514,7 +516,7 @@ export async function sendPm2(name, action = 'restart', hosts) {
514
516
  'name': name,
515
517
  'pm2Action': action
516
518
  }), globalConfig.rpcSecret), {
517
- 'timeout': 10
519
+ 'timeout': 2
518
520
  });
519
521
  const content = await res.getContent();
520
522
  if (!content) {
@@ -530,6 +532,42 @@ export async function sendPm2(name, action = 'restart', hosts) {
530
532
  }
531
533
  return rtn;
532
534
  }
535
+ /**
536
+ * --- 向本机或局域网 RPC 发送 npm install 操作 ---
537
+ * @param path 路径,如 /home/kebab/
538
+ * @param hosts 局域网列表
539
+ */
540
+ export async function sendNpm(path, hosts) {
541
+ if (hosts === 'config') {
542
+ hosts = globalConfig.hosts;
543
+ }
544
+ hosts ??= ['127.0.0.1'];
545
+ // --- 局域网模式 ---
546
+ const time = lTime.stamp();
547
+ /** --- 返回成功的 host --- */
548
+ const rtn = [];
549
+ for (const host of hosts) {
550
+ const res = await lNet.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
551
+ 'action': 'npm',
552
+ 'time': time,
553
+ 'path': path
554
+ }), globalConfig.rpcSecret), {
555
+ 'timeout': 2
556
+ });
557
+ const content = await res.getContent();
558
+ if (!content) {
559
+ continue;
560
+ }
561
+ const str = content.toString();
562
+ if (str === 'Done') {
563
+ rtn.push(host);
564
+ }
565
+ else {
566
+ debug('[CORE][sendNpmInstall] rpc server content error:', str);
567
+ }
568
+ }
569
+ return rtn;
570
+ }
533
571
  /** --- 跨进程全局变量 --- */
534
572
  export const global = {};
535
573
  /**
@@ -582,7 +620,7 @@ export async function removeGlobal(key, hosts) {
582
620
  return setGlobal(key, null, hosts);
583
621
  }
584
622
  /**
585
- * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新建 ---
623
+ * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新创建 ---
586
624
  * @param sourcePath zip 文件
587
625
  * @param path 要更新的目标路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路径开始算起
588
626
  * @param hosts 局域网多机部署,不设置默认本机部署
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maiyunnet/kebab",
3
- "version": "7.1.2",
3
+ "version": "7.2.0",
4
4
  "description": "Simple, easy-to-use, and fully-featured Node.js framework that is ready-to-use out of the box.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -34,19 +34,19 @@
34
34
  "jszip": "^3.10.1",
35
35
  "mysql2": "^3.15.3",
36
36
  "node-cron": "^4.2.1",
37
- "openai": "^6.9.1",
37
+ "openai": "^6.10.0",
38
38
  "pg": "^8.16.3",
39
39
  "ssh2": "^1.17.0",
40
40
  "svg-captcha": "^1.4.0",
41
- "tencentcloud-sdk-nodejs": "^4.1.152"
41
+ "tencentcloud-sdk-nodejs": "^4.1.153"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@litert/eslint-plugin-rules": "^0.3.1",
45
45
  "@types/ejs": "^3.1.5",
46
46
  "@types/node": "^24.10.1",
47
47
  "@types/pg": "^8.15.6",
48
- "@typescript/native-preview": "^7.0.0-dev.20251203.1",
49
48
  "typedoc": "^0.28.15",
50
- "typedoc-plugin-markdown": "^4.9.0"
49
+ "typedoc-plugin-markdown": "^4.9.0",
50
+ "typescript": "^5.9.3"
51
51
  }
52
52
  }
package/sys/master.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Project: Kebab, User: JianSuoQiYue
3
3
  * Date: 2019-5-2 21:03:42
4
- * Last: 2020-3-7 10:33:17, 2022-07-22 13:40:10, 2022-09-06 22:40:58, 2024-2-7 01:44:59, 2024-7-2 15:17:09, 2025-6-13 13:06:43
4
+ * Last: 2020-3-7 10:33:17, 2022-07-22 13:40:10, 2022-09-06 22:40:58, 2024-2-7 01:44:59, 2024-7-2 15:17:09, 2025-6-13 13:06:43, 2025-12-5 13:15:03
5
5
  */
6
6
  import * as os from 'os';
7
7
  import * as cluster from 'cluster';
@@ -161,6 +161,25 @@ function createRpcListener() {
161
161
  }
162
162
  break;
163
163
  }
164
+ case 'npm': {
165
+ // --- 执行 npm install 操作 ---
166
+ if (!msg.path || typeof msg.path !== 'string') {
167
+ res.end('Invalid path');
168
+ return;
169
+ }
170
+ if (!await lFs.isDir(msg.path)) {
171
+ res.end('Path not found');
172
+ return;
173
+ }
174
+ const rtn = await lCore.exec('npm i --omit=dev --omit=optional', {
175
+ 'cwd': msg.path,
176
+ });
177
+ if (!rtn) {
178
+ res.end('Exec failed');
179
+ return;
180
+ }
181
+ break;
182
+ }
164
183
  case 'code': {
165
184
  // --- 更新 code 代码包 ---
166
185
  const rtn = await sRoute.getFormData(req);
@@ -48,6 +48,7 @@ export default class extends sCtr.Ctr {
48
48
  coreReload(): Promise<string>;
49
49
  coreRestart(): Promise<string>;
50
50
  corePm2(): Promise<string>;
51
+ coreNpm(): Promise<any>;
51
52
  coreGlobal(): Promise<string>;
52
53
  crypto(): Promise<string>;
53
54
  db(): Promise<kebab.Json>;
@@ -140,6 +140,7 @@ export default class extends sCtr.Ctr {
140
140
  `<br><a href="${this._config.const.urlBase}test/core-reload">View "test/core-reload"</a>`,
141
141
  `<br><a href="${this._config.const.urlBase}test/core-restart">View "test/core-restart"</a>`,
142
142
  `<br><a href="${this._config.const.urlBase}test/core-pm2?name=cron&action=restart">View "test/core-pm2"</a>`,
143
+ `<br><a href="${this._config.const.urlBase}test/core-npm">View "test/core-npm"</a>`,
143
144
  `<br><a href="${this._config.const.urlBase}test/core-global">View "test/core-global"</a>`,
144
145
  `<br><a href="${this._config.const.urlBase}test/core-updatecode">View "test/core-updatecode"</a>`,
145
146
  '<br><br><b>Crypto:</b>',
@@ -1288,6 +1289,21 @@ to: ${to}`
1288
1289
  const list = await lCore.sendPm2(name, action);
1289
1290
  return `PM2 ${action} request has been sent for "${name}".<br>Success hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
1290
1291
  }
1292
+ async coreNpm() {
1293
+ // --- 创建一个临时目录 ---
1294
+ const path = kebab.ROOT_CWD + 'temp_npm_test/';
1295
+ await lFs.mkdir(path);
1296
+ // --- 创建一个 package.json ---
1297
+ await lFs.putContent(path + 'package.json', JSON.stringify({
1298
+ 'name': 'temp-npm-test',
1299
+ 'version': '1.0.0',
1300
+ 'dependencies': {
1301
+ 'is-number': '^7.0.0'
1302
+ }
1303
+ }));
1304
+ const list = await lCore.sendNpm(path);
1305
+ return `NPM request has been sent.<br>Success hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
1306
+ }
1291
1307
  async coreGlobal() {
1292
1308
  const ts = lTime.stamp().toString();
1293
1309
  const echo = [