asaihost-nodejs

中文文档
0.0.35发布于 2026/11/03ISCTypeScriptESM + CJS

AsaiWeb CMS Node.js主机插件- HTTP/WebSocket服务器,sysserver平台API, IEC 62443安全内核

中文使用文档
文档目录39 节
  1. 目录结构
  2. 目录
  3. 快速开始
  4. 安装
  5. 最小引导(app.ts 模式)
  6. 在 AsaiCMS monorepo 内使用
  7. 独立项目集成
  8. 1. 项目结构建议
  9. 2. TypeScript
  10. 3. 运行方式
  11. 4. 与传输层插件协作
  12. 启动与校验流程
  13. 默认导出 API 形状
  14. 配置文件总览
  15. 欧盟合规:密钥如何保存(CRA / NIS2 / GDPR Art.32 / IEC 62443-4-2)
  16. 用户数据存储( dataStores.user )
  17. 日志子系统已下线
  18. 完整配置 — asaihost.json(合成示例)
  19. 密钥侧车
  20. 环境变量(等价)
  21. 配置 → 运行时映射
  22. 站点合并规则
  23. 请求路由
  24. 公开 API 参考
  25. 配置与密钥
  26. 路由注册
  27. 安全与基础设施
  28. 传输桥接(供 TCP/gRPC/RS485 插件)
  29. 类型导出
  30. 字段速查
  31. security
  32. hosts.default 常用
  33. aes
  34. 开发与发布 npm 包
  35. package.json exports 约定
  36. 注意事项
  37. 近期修复(鉴权 / 会话 / WS)
  38. 测试
  39. 约束与前端对应

asaihost-nodejs

Node.js HTTP/WebSocket 服务器宿主:多站点监听、静态资源、反向代理、内置 sysserver 平台 API(登录/RBAC/日志/数据库),以及 IEC 62443 安全内核。

项值
npm 包名asaihost-nodejs
插件入口index.ts(monorepo 源码)/ dist/asaihost-nodejs.es.js(发布后)
运行时配置asaihost.json + 密钥侧车 / 环境变量
Node 版本>= 20
对等依赖ws ^8.18(mysql / sqlite3 按数据存储选配)

目录结构

asaihost-nodejs/
├── index.ts              # 包入口(默认导出 initAsaiHostNodejs + 命名 API)
├── package.json
├── tsup.config.ts
├── README.md
└── src/
    ├── index.ts          # StartAsaiHostNodejs 启动链
    ├── host-api.ts       # 对外公开 API 聚合
    ├── types.ts          # AsaiRuntime / HostConfig 等类型
    ├── core/             # init、host-config、network
    ├── http/             # server、static、security
    ├── ws/               # server、auth、message
    ├── proxy/            # 反向代理
    ├── config/           # validate、secrets
    ├── infra/            # registry、security
    ├── common/server/    # ServerApi / ServerSys / ServerWs / WsClient 基类
    └── sysserver/        # 内置 api/ws/db/lib

目录

  1. 快速开始
  2. 在 AsaiCMS monorepo 内使用
  3. 独立项目集成
  4. 启动与校验流程
  5. 配置文件总览
  6. 配置 → 运行时映射
  7. 公开 API 参考
  8. 字段速查
  9. 开发与发布 npm 包
  10. 约束与前端对应

快速开始

安装

npm install asaihost-nodejs ws
# 若使用 MySQL / SQLite 数据存储
npm install mysql sqlite3

最小引导(app.ts 模式)

import fs from 'node:fs/promises';
import path from 'node:path';
import AsaiHostNodejs from 'asaihost-nodejs';

const $asai: any = {
  $lib: { /* 业务工具库 */ },
  connectionshttp: {},
  connectionsws: {},
  taskshttp: {},
  tasksws: {},
  servershttp: {},
  serversws: {},
  tm: 0,
  tmpdata: {},
};

// 1. 挂载 sysserver 平台能力(api/ws/db/lib);sqlite/mysql 驱动由独立插件注入
import AsaiHostNodejsDbsqlite from './src/plugs/asaihost-nodejs-dbsqlite/index';
import AsaiHostNodejsDbmysql from './src/plugs/asaihost-nodejs-dbmysql/index';
AsaiHostNodejs.sysserver($asai, {
  db: { sqlite: AsaiHostNodejsDbsqlite, mysql: AsaiHostNodejsDbmysql },
});

$asai.serverRoot = process.cwd();
const cfg = JSON.parse(
  await fs.readFile(path.join($asai.serverRoot, 'websys/sys/asaihost.json'), 'utf8'),
);

// 2. 配置校验与密钥注入
const stripped = AsaiHostNodejs.stripForbiddenSecretsFromHostConfig(cfg);
if (stripped.length) {
  console.warn(`[AsaiHostNodejs] 已从 asaihost.json 剥离敏感字段: ${stripped.join(', ')}`);
}
$asai.hostconfig = AsaiHostNodejs.normalizeHostConfig(cfg);
AsaiHostNodejs.normalizeSecurityConfig($asai.hostconfig);
const errors = AsaiHostNodejs.validateHostConfig($asai.hostconfig);
if (errors.length) throw new Error(errors.join('; '));

const { secrets } = await AsaiHostNodejs.loadAsaiSecrets($asai.serverRoot);
AsaiHostNodejs.applySecretsToHostConfig($asai.hostconfig, secrets);
await AsaiHostNodejs.resolveHttpsCertFromPaths($asai.serverRoot, $asai.hostconfig);

// 3. 注册业务 work 处理器并启动
$asai.asaihost = AsaiHostNodejs;
const { sysWork } = sysMod($asai);
const { apiWork } = apiMod($asai);
const { wsWork } = wsMod($asai);
const { jsonpWork } = jsonpMod($asai);

const { StartAsaiHostNodejs } = AsaiHostNodejs.fn($asai, { sysWork, apiWork, wsWork, jsonpWork });
StartAsaiHostNodejs();

完整 monorepo 示例见仓库根目录 webserver/app.ts。


在 AsaiCMS monorepo 内使用

本仓库 webserver 通过相对路径引用插件源码,开发时无需先 npm pack:

// webserver/app.ts
import AsaiHostNodejsMod from './src/plugs/asaihost-nodejs/index';

本地构建 npm 产物:

cd webserver/src/plugs/asaihost-nodejs
npm install
npm run build

构建产物位于 dist/:asaihost-nodejs.es.js(ESM)、asaihost-nodejs.cjs(CJS)、index.d.ts(类型声明)。


独立项目集成

1. 项目结构建议

your-server/
├── app.ts                 # 引导入口(见上文)
├── websys/sys/
│   ├── asaihost.json      # 非敏感配置(可进 Git)
│   └── asaihost.secrets.local.json   # 本地密钥(勿提交)
├── .env                   # 生产推荐:环境变量注入密钥
├── webclient/             # 静态前端(hostdirs 指向)
└── src/work/              # 业务 api/sys/ws 模块

2. TypeScript

{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true
  }
}

从 npm 安装后:

import AsaiHostNodejs, { PLUGIN_NAME, type AsaiRuntime, type HostConfig } from 'asaihost-nodejs';

3. 运行方式

  • 开发:tsx app.ts 或 ts-node --esm app.ts
  • 生产:先 npm run build(若打包业务代码),再 node dist/app.js

4. 与传输层插件协作

TCP / gRPC / RS485 等传输插件通过 $asai.asaihost 挂载,禁止跨包 deep import src/。在 asaihost.json 中配置 tcp / grpc / rs485 块,由对应 npm 插件读取。


启动与校验流程

读取 asaihost.json
  → stripForbiddenSecretsFromHostConfig(敏感字段不得写在 JSON)
  → normalizeHostConfig + normalizeSecurityConfig
  → validateHostConfig(结构 fail-fast)
  → validateProductionSecurity(生产 IEC 62443 检查)
  → loadAsaiSecrets(.env / secrets.local.json / process.env)
  → applySecretsToHostConfig + resolveHttpsCertFromPaths
  → sysserver($asai) 已提前执行
  → fn($asai, { sysWork, apiWork, wsWork, jsonpWork })
  → StartAsaiHostNodejs()  → 多端口 HTTP/WS + 反向代理

默认导出 API 形状

interface AsaiNodejsHostPlugin {
  readonly name: 'asaihost-nodejs';
  fn(runtime, options): { StartAsaiHostNodejs; asaiWs };
  sysserver(runtime, opt?: SysserverBootOptions): void;
  AsaiCommon: { ServerApi; ServerWs; ServerSys; WsClient };
  AsaiUtils: { deUserInfoWithAsai; wsMock };
  // …配置、路由、安全、传输桥接等(见 host-api.ts)
}

配置文件总览

本插件的配置由 两份 组成,启动时合并到 $asai.hostconfig:

文件位置(monorepo 惯例)进 Git说明
asaihost.jsonwebserver/websys/sys/asaihost.json✅ 是结构与非敏感运维项
asaihost.secrets.local.jsonwebserver/websys/sys/❌ 否本地开发密钥(复制 example)
.envwebserver/.env❌ 否环境变量注入(生产推荐)

加载优先级(高 → 低):process.env > webserver/.env > asaihost.secrets.local.json → 仅注入内存 hostconfig(不写回 JSON)。

敏感字段(password / asaisn / aes.keybase64 / PEM 内联 / sessionSecret / wssec[0])禁止写入 asaihost.json,启动时会剥离并报错。

欧盟合规:密钥如何保存(CRA / NIS2 / GDPR Art.32 / IEC 62443-4-2)

层级做法是否合规
❌ Git / asaihost.json明文密钥进仓库不合规(CRA 默认安全、CR 4.1)
🟡 开发asaihost.secrets.local.json 或 .env(gitignore,权限 600)可接受(仅本机)
✅ 生产部署平台环境变量 / Docker secrets / K8s Secret / Vault / TPM推荐
✅ 严格生产设 ASAI_REQUIRE_ENV_SECRETS=1,禁止只靠侧车文件NIS2 加固

密钥分离(必做)

变量用途生产要求
ASAI_ASAISNUserinfo 编解码盐≥32 随机;不得等于 sessionSecret
ASAI_SESSION_SECRET会话 HMAC≥32 随机;禁止用 asaisn 派生
ASAI_AES_KEYBASE64AES-256-GCMBase64 解码 = 32 字节;与前端 VITE_ASAI_AES_KEYBASE64 一致
ASAI_HOST_PASSWORDbootstrap 密码≥12;禁止弱口令

生成随机密钥

cd webserver
npm run secrets:gen              # 打印 .env 片段
npm run secrets:gen:write        # 写入 .env(已存在则拒绝覆盖)
npm run secrets:gen:json         # 打印 secrets.local 模板

落盘后建议:chmod 600 .env(Linux);Windows 限制 ACL 仅服务账户可读。轮换时分别更新 ASAI_ASAISN / ASAI_SESSION_SECRET,避免一钥多用。

用户数据存储(dataStores.user)

默认 file(webdata/webdb/users/users.json + sessions.json)。在 websys/sys/asaihost.json 中修改 dataStores.user 即可切换,重启 webserver 后生效(app.ts 须已注入 sqlite/mysql 驱动)。

type说明opt 主要字段
file默认,JSON 文件dir, ext, create
sqlite单文件库,表 auth_users / auth_sessionsdatabase, create
mysql远程 MySQLhost, user, password, database, create
"dataStores": {
  "user": {
    "type": "file",
    "opt": { "dir": "webdata/webdb/users/", "ext": ".json", "create": 1 }
  }
}

切换 SQLite:

"user": {
  "type": "sqlite",
  "opt": { "database": "./webdata/webdb/users/users.db", "create": 1 }
}

切换 MySQL:

"user": {
  "type": "mysql",
  "opt": {
    "host": "127.0.0.1",
    "user": "root",
    "password": "",
    "database": "asai",
    "create": 1
  }
}

运行时可通过 GET /api/user/login/config/ 查看 userStore.type(file / sqlite / mysql)。兼容旧字段 userStore,但推荐只维护 dataStores.user。

日志子系统已下线

asaihost.json 不再有 logger 配置。控制台级别、干预日志(CEF / 哈希链 / 5 年留存)、SIEM 令牌与 /api/asailog/* 均已删除。

  • $asai.$log 是立即返回的空函数,不读配置、不向控制台输出;
  • 启动校验会丢弃历史 logger 字段,不再创建 webdata/webdb/log/intervention 目录;
  • WEB 操作记录(security.auditLog、接口追踪、日志只读门槛)已去掉,不再向控制台输出。

清理历史遗留日志

已下线前写出的文件不会自动消失,用根目录脚本一次性回收(默认只预览,不删除):

npm run logs:purge          # dry-run 预览清单与总大小
npm run logs:purge:apply    # 确认后真正删除

脚本清理 webdata/webdb/log/{client,server,access,store,intervention,intervention-test} 下的 .txt/.log/.jsonl/.gz/.cef。

完整配置 — asaihost.json(合成示例)

{
  "website": { "title": "WEB", "ver": "1.0.0.0" },
  "dataStores": {
    "user": {
      "type": "file",
      "opt": { "dir": "webdata/webdb/users/", "ext": ".json", "create": 1 }
    }
  },
  "security": {
    "requireAuth": 0,
    "csp": 0,
    "authSkipPaths": [
      "/api/sys/errorcodes/*",
      "/api/user/login/auth/*",
      "/api/user/login/register/*",
      "/sys/info/*",
      "/jsonp/*"
    ],
    "minUserLevel": 0,
    "allowRegister": 1,
    "lockoutMaxFails": 5,
    "lockoutMinutes": 15,
    "sessionTtlHours": 24,
    "passwordMinLength": 8,
    "quota": {
      "enabled": 0,
      "maxApiConcurrent": 500,
      "maxApiPerIp": 30,
      "maxApiPerIpPerMin": 120,
      "maxWsPerIp": 5,
      "maxLoginSessions": 100,
      "maxSessionsPerUser": 3,
      "onUserSessionOverflow": "reject"
    }
  },
  "hosts": {
    "default": {
      "port": 9198,
      "httptype": "http://",
      "maxhttp": 2000,
      "maxws": 2000,
      "maxonline": 100,
      "hostdirs": ["webclient", "websys", "webdata/upload"]
    },
    "asai": {
      "ws": 1,
      "port": 9199,
      "hostdirs": ["webclient", "websys", "webdata/upload"]
    }
  },
  "proxyhosts": {
    "default": {
      "proxyport": 9298,
      "port": 9198,
      "httptype": "http://",
      "proxyhttptype": "http://"
    }
  },
  "aes": {
    "lv": 1,
    "aad": "asai aes aad",
    "keylength": 256,
    "ivlength": 12,
    "algorithm": "aes-256-gcm"
  },
  "httpscert": {
    "keyPath": "websys/sys/certs/local.key",
    "certPath": "websys/sys/certs/local.crt"
  },
  "ip": "asai",
  "index": "index.html"
}

完整字段模板见 monorepo webserver/websys/sys/asaihost.json;校验规则以 validateHostConfig 源码为准。

密钥侧车

复制 websys/sys/asaihost.secrets.example.json 为 asaihost.secrets.local.json:

{
  "_comment": "禁止提交仓库。生产请改用环境变量或密钥托管。",
  "password": "<强密码≥12>",
  "asaisn": "<随机盐≥32,与 sessionSecret 不同>",
  "aesKeyBase64": "<与前端 VITE_ASAI_AES_KEYBASE64 一致>",
  "sessionSecret": "<随机密钥≥32,与 asaisn 不同>",
  "wssecToken": "<随机 token>"
}

环境变量(等价)

ASAI_HOST_PASSWORD=
ASAI_ASAISN=
ASAI_AES_KEYBASE64=
ASAI_SESSION_SECRET=
ASAI_WSSEC_TOKEN=
ASAI_REQUIRE_ENV_SECRETS=1
ASAI_HTTPS_KEY_PATH=websys/sys/certs/local.key
ASAI_HTTPS_CERT_PATH=websys/sys/certs/local.crt
环境变量注入到 hostconfig说明
ASAI_HOST_PASSWORDpassword系统 bootstrap 密码
ASAI_ASAISNasaisnUserinfo 编解码盐
ASAI_AES_KEYBASE64aes.keybase64AES-256-GCM 密钥
ASAI_SESSION_SECRETsecurity.sessionSecret会话 HMAC(须与 asaisn 分离)
ASAI_WSSEC_TOKENwssec[0]WS 安全令牌
ASAI_REQUIRE_ENV_SECRETS(校验开关)1=生产禁止仅靠 secrets.local

配置 → 运行时映射

asaihost.json + secrets
├── website / ip / index / mimetypes / pkg     → 全局
├── tm.*                                       → init, ws/auth, process
├── security.*                                 → access-control, user-store, quota
├── userStore.*                                → sysserver/api/login/store
├── aes.* (+ secrets.keybase64)                → API/WS 加解密
├── httpscert.*                                → https.createServer
├── hosts.default + hosts.<site>               → http/*, ws/*
│   ├── weburls.*                              → SPA fallback
│   └── ckhttp / ckws / max*                   → 连接监控与限流
├── proxyhosts.*                               → proxy/server
└── tcp|grpc|rs485                             → 传输插件(可选)

站点合并规则

  • 实际站点 = hosts.default 浅合并 hosts.<name>
  • default 仅作模板,不单独监听
  • asai 为内置守护站点;9199 端口冲突时 process.exit(1)

请求路由

URL处理器
/sys/*sysWork
/api/*apiWork(前缀匹配 hostserverapis)
/jsonp/*jsonpWork
其它静态(hostdirs 顺序查找)
WebSocketwsWork(msg.ty 最长前缀)

公开 API 参考

npm 消费者仅使用包入口导出,禁止 deep import src/。

配置与密钥

导出说明
normalizeHostConfig填充默认值、规范化结构
validateHostConfig结构校验,返回错误字符串数组
validateProductionSecurity生产环境 IEC 62443 检查
normalizeSecurityConfig安全策略默认值
stripForbiddenSecretsFromHostConfig剥离 JSON 中的敏感字段
loadAsaiSecrets / loadDotEnvFile加载密钥
applySecretsToHostConfig合并密钥到 hostconfig
resolveHttpsCertFromPaths从路径读取 PEM
validateAsaiSecrets / isDevDefaultPassword密钥校验

路由注册

导出说明
registerApi / registerWs注册业务路由工厂
initHostserverApi / initHostserverWs初始化平台路由表
syncApiRouteKeys / syncWsRouteKeys同步路由键列表

安全与基础设施

导出说明
secureCompare恒定时间字符串比较
resolvePathUnderRoots / getHostAllowedRoots防目录穿越
validateHttpAuth / validateHttpAuthAsyncHTTP Userinfo 鉴权(Async 版附加服务端 lv 与 session token 绑定)
logSecurityEvent / getClientIp安全审计
sanitizeString 等输入净化

传输桥接(供 TCP/gRPC/RS485 插件)

导出说明
getTransportBlock / getTransportDefault读取 hostconfig 传输配置
initTransportBridge初始化 $asai 传输桥
ensureDefaultConnection / createTransportDataHandler连接与数据回调

类型导出

AsaiRuntime、HostConfig、AsaiHostNodejsOptions、HostBootResult、AsaiSecrets、SecurityConfig 等见 import type { … } from 'asaihost-nodejs'。


字段速查

security

字段默认说明
requireAuth01=API 需登录(authSkipPaths 除外)
csp01=启用 Content-Security-Policy
quota.enabled0连接/频率配额

hosts.default 常用

字段默认说明
port9198监听端口
httptypehttp://或 https://
ws—1=同端口挂载 WebSocket
maxhttp / maxws / maxonline2000/2000/100限流
hostdirs—静态目录(按序查找)
close01=跳过启动

aes

字段说明
lv1=可选 AES;>1=全量 AES(须 secrets 注入 keybase64)
aad / algorithm / keylength / ivlengthGCM 参数

开发与发布 npm 包

cd webserver/src/plugs/asaihost-nodejs
npm install
npm run typecheck    # 仅类型检查
npm run build        # tsup 打包 + tsc 声明
npm pack             # 本地验证 .tgz 内容
npm publish --access public

package.json exports 约定

条件解析到
development./index.ts(monorepo + tsx 开发)
import./dist/asaihost-nodejs.es.js
require./dist/asaihost-nodejs.cjs
types./dist/asaihost-nodejs.d.ts

注意事项

  1. 修改 asaihost.json 后需重启 Node 进程。
  2. 端口冲突以 listen 的 EADDRINUSE 为准(启动前不再用 netstat 预告警,避免误报);排查 9198/9199。
  3. CONFIG_WARN 表示使用 dev 默认密码,生产请设 ASAI_HOST_PASSWORD。
  4. 业务处理器经模块级 workHandlers Map 注册,不污染 global。
  5. 静态路径经 resolvePathUnderRoots 防目录穿越。

近期修复(鉴权 / 会话 / WS)

项行为
WS 关闭清 sessionremoveSessionOnWsClose 用 Userinfo[2](pri)匹配会话表 s.pri(deUserInfoWithAsai 后 token 为 pri,非 pub/asencode)
禁用平台用户attachServerUserLevel:平台库命中且 status !== 'active' 时设 _serverUser = null,不再回落 channel json 伪装 active
已踢 WS 不计在线isUserOnlineOnWs / listOnlineWsEntries 跳过 _asaiKicked 连接(readyState 仍短暂 OPEN 时不占配额/误拦登录)
强制登录接管锁/api/user/login/force/ 仅给接管方 setForceTakeover;被踢用户不得持锁(防重连反踢);踢后刷新 TTL;名额仍满则再踢一轮可踢用户;loginWs 清锁窗口 800ms → 4s
admin/quota 只读/api/user/login/admin/quota/ 不再 purgeOfflineSessions;HTTP 刚登录尚未建 WS 的会话不会被误删
HTTP session 绑定validateHttpAuthAsync:用户已有 session 记录时校验 Userinfo[2] 与 s.pri/s.pub 且未过期;无 session 的历史/channel 用户保持原等级校验
clearWsServerTasksWS server 出错/关闭时清理定时任务,但保留 tasksws[hostdir].httpMonitor,避免 HTTP 限流监控静默失效

测试

单元测试目录:.youmengyu/test/unit/webserver/plugs/asaihost-nodejs/

# 仓库根目录
node .youmengyu/test/asaitest.mjs --no-open

# 或单文件(现有示例)
npx tsx --test .youmengyu/test/unit/webserver/plugs/asaihost-nodejs/login/resolve-user-lv.test.mjs
npx tsx --test .youmengyu/test/unit/webserver/plugs/asaihost-nodejs/ws/auth-isOkWs.test.mjs

约束与前端对应

  • 与 asaihost-vue(前端)配对使用时,保持 asaihost.json / aes 密钥 / VITE_ASAI_AES_KEYBASE64 一致。
  • 插件间禁止跨包 plugs/*/src/ 引用;消费方只走 import from 'asaihost-nodejs'。
  • 传输层插件仅通过 $asai.asaihost.* 与宿主协作。
前端后端
asaihost-vueasaihost-nodejs
public/webmodel/cfg.jswebsys/sys/asaihost.json
VITE_ASAI_AES_KEYBASE64ASAI_AES_KEYBASE64

配置以本 README 与 validateHostConfig 源码为准;monorepo 实参见 webserver/websys/sys/asaihost.json 与 webserver/app.ts。

版本与发布记录

asaihost-nodejs 共发布 30 个版本,首次发布于 2026/07/03;过去 12 个月发布了 30 个版本。

版本发布日期距今
0.0.35latest2026/11/03今天
0.0.342026/10/286 天前
0.0.332026/10/277 天前
0.0.322026/10/268 天前
0.0.292026/09/012 个月前
0.0.282026/09/012 个月前

关于 asaihost-nodejs 的常见问题

asaihost-nodejs 是什么?

AsaiWeb CMS Node.js主机插件- HTTP/WebSocket服务器,sysserver平台API, IEC 62443安全内核

如何安装 asaihost-nodejs?

在项目目录运行 npm install asaihost-nodejs,或使用 pnpm add / yarn add / bun add。

asaihost-nodejs 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

asaihost-nodejs 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

asaihost-nodejs 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

asaihost-nodejs 可以商用吗?

asaihost-nodejs 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

asaihost-nodejs 还在维护吗?

最新版本 0.0.35 发布于 2026/11/03(今天);至今共发布 30 个版本,其中过去 12 个月发布了 30 个;首次发布于 2026/07/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。