@hile/micro 1.0.8 → 1.0.10
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/README.md +3 -25
- package/SKILL.md +6 -29
- package/dist/application.d.ts +0 -4
- package/dist/application.js +0 -31
- package/dist/client.d.ts +4 -0
- package/dist/client.js +31 -0
- package/dist/registry.d.ts +0 -3
- package/dist/registry.js +7 -25
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hile/micro
|
|
2
2
|
|
|
3
|
-
基于 `@hile/message-loader` 与 `@hile/message-ws` 的轻量级 **WebSocket
|
|
3
|
+
基于 `@hile/message-loader` 与 `@hile/message-ws` 的轻量级 **WebSocket 微服务框架**。提供服务注册与发现、心跳保活、熔断、请求超时、自动重试等功能。
|
|
4
4
|
|
|
5
5
|
## 架构分层
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ MessageLoader (路由) + MessageWs (请求/响应传输)
|
|
|
16
16
|
| **Server** | WebSocket 监听、连接管理、消息路由。不关心注册中心 |
|
|
17
17
|
| **Client** | 远端 Server 的代理,提供 `request()` / `push()` 通信接口 |
|
|
18
18
|
| **Registry** | 注册中心。维护 namespace → 实例列表,心跳检测剔除死实例 |
|
|
19
|
-
| **Application** |
|
|
19
|
+
| **Application** | 应用服务。集成注册发现、熔断、重试等功能 |
|
|
20
20
|
|
|
21
21
|
一个 `Application` 实例 **同时** 扮演 provider(`register` 暴露接口)和 consumer(`get` / `call` 调用其它服务)。
|
|
22
22
|
|
|
@@ -176,28 +176,6 @@ await app.call('svc', '/api', data, 5000, 0); // 超时 5s, 不重试
|
|
|
176
176
|
|
|
177
177
|
重试策略:失败 → `recordFailure`(peer 被排除)→ 递归 `call(retries-1)` → `getActiveExcludes` 排除已失败的 peer → Registry `/‑/find` 返回其他 peer。
|
|
178
178
|
|
|
179
|
-
### Correlation ID 链路追踪
|
|
180
|
-
|
|
181
|
-
`call()` 自动为每次调用注入唯一 `_correlationId`:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
provider.register('/api', async ({ data }) => {
|
|
185
|
-
console.log(data._correlationId); // 自动注入的 UUID
|
|
186
|
-
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
行为规则:
|
|
190
|
-
|
|
191
|
-
| 入参 data | 结果 |
|
|
192
|
-
|-----------|------|
|
|
193
|
-
| `null / undefined` | 包装为 `{ _correlationId, data: null }` |
|
|
194
|
-
| 字符串 / 数字 | 包装为 `{ _correlationId, data: '原始值' }` |
|
|
195
|
-
| 数组 | 包装为 `{ _correlationId, data: [原始数组] }` |
|
|
196
|
-
| `{ value: 1 }` (无 `_correlationId`) | 扩展为 `{ value: 1, _correlationId: 'uuid' }` |
|
|
197
|
-
| `{ _correlationId: 'trace-1' }` | 保留已有 ID,**不覆盖** |
|
|
198
|
-
|
|
199
|
-
> **注意:** 原 data 对象不会被修改(使用浅拷贝 `{ ...data, _correlationId }`)。
|
|
200
|
-
|
|
201
179
|
### 健康检查
|
|
202
180
|
|
|
203
181
|
每个 `Application` 自动注册 `/-/health` 端点:
|
|
@@ -380,7 +358,7 @@ class Application extends Server {
|
|
|
380
358
|
// 获取 namespace 对应的远端 Client(缓存 + 自动发现)
|
|
381
359
|
get(namespace: string, exclude?: string[]): Promise<Client>;
|
|
382
360
|
|
|
383
|
-
// 一站式调用:get + request + response + 熔断 + 重试
|
|
361
|
+
// 一站式调用:get + request + response + 熔断 + 重试
|
|
384
362
|
call<T = any>(
|
|
385
363
|
namespace: string,
|
|
386
364
|
url: string,
|
package/SKILL.md
CHANGED
|
@@ -30,7 +30,7 @@ description: Code generation and contribution rules for @hile/micro. Use when ed
|
|
|
30
30
|
| `Server` | `server.ts` | WebSocketServer 生命周期, 出入站连接, Client Map | 不感知 Registry |
|
|
31
31
|
| `Client` | `client.ts` | 远端 Server 的 WebSocket 会话代理 | `dispose()` 必须关闭底层 socket |
|
|
32
32
|
| `Registry` | `registry.ts` | namespace → Set\<host:port\>, 心跳检测, /-/find 随机返回, 环境变量管理 | 自动创建 `~/.registry/` 工作目录 |
|
|
33
|
-
| `Application` | `application.ts` | 注册发现 + 熔断 + 重试 +
|
|
33
|
+
| `Application` | `application.ts` | 注册发现 + 熔断 + 重试 + 心跳 + 远程环境变量读取 | `listen()` 后自动连 Registry |
|
|
34
34
|
|
|
35
35
|
### 应用模型
|
|
36
36
|
|
|
@@ -142,7 +142,7 @@ export class Application extends Server {
|
|
|
142
142
|
listen(port: number): Promise<() => Promise<void>>; // 自动连 Registry + 启心跳
|
|
143
143
|
|
|
144
144
|
get(namespace: string, exclude?: string[]): Promise<Client>;
|
|
145
|
-
// call() = get + request + response +
|
|
145
|
+
// call() = get + request + response + 熔断 + 重试 + 超时
|
|
146
146
|
call<T = any>(
|
|
147
147
|
namespace: string,
|
|
148
148
|
url: string,
|
|
@@ -226,27 +226,7 @@ peer 首次失败
|
|
|
226
226
|
|
|
227
227
|
**冷卻期:** `CB_COOLDOWN_MS = 30000` (30 秒)。到期后 `getActiveExcludes` 自动清除旧条目。
|
|
228
228
|
|
|
229
|
-
### 3.3
|
|
230
|
-
|
|
231
|
-
`call()` 自动处理 `_correlationId`:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
// 非对象/假值/数组 → 包装
|
|
235
|
-
!data || typeof data !== 'object' || Array.isArray(data)
|
|
236
|
-
→ data = { _correlationId: randomUUID(), data }
|
|
237
|
-
|
|
238
|
-
// 对象无 _correlationId → 浅拷贝注入
|
|
239
|
-
else if (!data._correlationId)
|
|
240
|
-
→ data = { ...data, _correlationId: randomUUID() }
|
|
241
|
-
|
|
242
|
-
// 对象已有 _correlationId → 保留(透传)
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
- 使用 `import { randomUUID } from 'node:crypto'`(Node >= 14.17)
|
|
246
|
-
- 永远不修改原始 data 对象(浅拷贝 `{ ...data }`)
|
|
247
|
-
- retry 递归时 data 已包含 `_correlationId`,自动透传
|
|
248
|
-
|
|
249
|
-
### 3.4 请求超时
|
|
229
|
+
### 3.3 请求超时
|
|
250
230
|
|
|
251
231
|
**配置链:**
|
|
252
232
|
|
|
@@ -547,8 +527,6 @@ pnpm --filter @hile/micro test # 必须全部通过
|
|
|
547
527
|
| call() 基本调用 | `circuit breaker > call() returns data on success` |
|
|
548
528
|
| 熔断排除 | `circuit breaker > excludes a failing peer and selects a different one` |
|
|
549
529
|
| 全排除重置 | `circuit breaker > resets breaker when all peers are excluded` |
|
|
550
|
-
| Correlation ID 注入 | `correlation ID > injects _correlationId into call() data` |
|
|
551
|
-
| Correlation ID 透传 | `correlation ID > preserves existing _correlationId` |
|
|
552
530
|
| 健康检查 | `health endpoint > /-/health returns status and registry state` |
|
|
553
531
|
| 超时 reject | `request timeout > rejects when request exceeds the timeout` |
|
|
554
532
|
| 超时充足则成功 | `request timeout > succeeds when timeout is long enough` |
|
|
@@ -585,9 +563,8 @@ pnpm --filter @hile/micro test # 必须全部通过
|
|
|
585
563
|
3. **不要在 `Client.dispose()` 中删除 `socket.close()`**(会导致 WebSocketServer.close 长时间等待)
|
|
586
564
|
4. **不要假设 `host:port` 可无损表达 IPv6** — 使用 `[IPv6]:port` 格式,`parseAddressKey` 按最后一个 `:` 切分
|
|
587
565
|
5. **不要传错 Registry 端口** — 丢失 Registry 连接时依赖 `reconnectToRegistry`,不要在外部缓存 registry Client
|
|
588
|
-
6.
|
|
589
|
-
7.
|
|
590
|
-
8. **不要给 call() 增加非可选参数** — `timeout` 和 `retries` 都在尾部且保持可选,不影响现有调用
|
|
566
|
+
6. **不要在其他文件中重复 Registry 的 helper 函数** — `selectRandomRegistryAddress`、`parseAddressKey`、`getRegistryConfigsDir`、`namespaceToConfigFile`、`parseConfigFilename` 都在 `registry.ts` 中导出复用
|
|
567
|
+
7. **不要给 call() 增加非可选参数** — `timeout` 和 `retries` 都在尾部且保持可选,不影响现有调用
|
|
591
568
|
|
|
592
569
|
---
|
|
593
570
|
|
|
@@ -617,7 +594,7 @@ pnpm --filter @hile/micro test # 必须全部通过
|
|
|
617
594
|
|------|------|
|
|
618
595
|
| `packages/micro/src/registry.ts` | 注册中心(含配置管理、路径工具函数) |
|
|
619
596
|
| `packages/micro/src/application.ts` | 应用服务(含 getEnvVariables) |
|
|
620
|
-
| `packages/micro/src/index.test.ts` | 主测试文件(
|
|
597
|
+
| `packages/micro/src/index.test.ts` | 主测试文件(27 个用例) |
|
|
621
598
|
| `packages/micro/src/env-config.test.ts` | 配置管理测试文件(13 个用例) |
|
|
622
599
|
| `packages/cli/src/index.ts` | CLI 入口(含 registry configs 子命令组) |
|
|
623
600
|
| `packages/cli/src/configs.ts` | CLI 配置管理 handler(list/get/set/del) |
|
package/dist/application.d.ts
CHANGED
|
@@ -34,16 +34,12 @@ export declare class Application extends Server {
|
|
|
34
34
|
private readonly _registryLookupTimeoutMs;
|
|
35
35
|
private readonly _requestTimeoutMs;
|
|
36
36
|
private readonly namespaces;
|
|
37
|
-
private static readonly HEARTBEAT_INTERVAL;
|
|
38
|
-
private heartbeatTimer?;
|
|
39
37
|
private static readonly CB_COOLDOWN_MS;
|
|
40
38
|
private readonly circuitBreakers;
|
|
41
39
|
constructor(props: ApplicationProps);
|
|
42
40
|
listen(port?: number): Promise<() => Promise<void>>;
|
|
43
41
|
private scheduleRegistryRetry;
|
|
44
42
|
private reconnectToRegistry;
|
|
45
|
-
private startHeartbeat;
|
|
46
|
-
private stopHeartbeat;
|
|
47
43
|
private recordSuccess;
|
|
48
44
|
private recordFailure;
|
|
49
45
|
private getActiveExcludes;
|
package/dist/application.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { Server } from './server.js';
|
|
3
2
|
var RegistryLookupStatus;
|
|
4
3
|
(function (RegistryLookupStatus) {
|
|
@@ -46,8 +45,6 @@ export class Application extends Server {
|
|
|
46
45
|
_registryLookupTimeoutMs;
|
|
47
46
|
_requestTimeoutMs;
|
|
48
47
|
namespaces = new Map();
|
|
49
|
-
static HEARTBEAT_INTERVAL = 10000;
|
|
50
|
-
heartbeatTimer;
|
|
51
48
|
static CB_COOLDOWN_MS = 30_000;
|
|
52
49
|
circuitBreakers = new Map();
|
|
53
50
|
constructor(props) {
|
|
@@ -69,7 +66,6 @@ export class Application extends Server {
|
|
|
69
66
|
const callback = await super.listen(port);
|
|
70
67
|
try {
|
|
71
68
|
await this.reconnectToRegistry();
|
|
72
|
-
this.startHeartbeat();
|
|
73
69
|
}
|
|
74
70
|
catch (err) {
|
|
75
71
|
try {
|
|
@@ -82,7 +78,6 @@ export class Application extends Server {
|
|
|
82
78
|
}
|
|
83
79
|
return async () => {
|
|
84
80
|
this.stopped = true;
|
|
85
|
-
this.stopHeartbeat();
|
|
86
81
|
if (this.reconnectTimeout) {
|
|
87
82
|
clearTimeout(this.reconnectTimeout);
|
|
88
83
|
this.reconnectTimeout = undefined;
|
|
@@ -134,25 +129,6 @@ export class Application extends Server {
|
|
|
134
129
|
});
|
|
135
130
|
return this.registryReconnectPromise;
|
|
136
131
|
}
|
|
137
|
-
startHeartbeat() {
|
|
138
|
-
this.stopHeartbeat();
|
|
139
|
-
this.heartbeatTimer = setInterval(() => {
|
|
140
|
-
if (!this.registry)
|
|
141
|
-
return;
|
|
142
|
-
try {
|
|
143
|
-
this.registry.push('/-/heartbeat', {});
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// registry connection may have dropped between null-check and push
|
|
147
|
-
}
|
|
148
|
-
}, Application.HEARTBEAT_INTERVAL);
|
|
149
|
-
}
|
|
150
|
-
stopHeartbeat() {
|
|
151
|
-
if (this.heartbeatTimer) {
|
|
152
|
-
clearInterval(this.heartbeatTimer);
|
|
153
|
-
this.heartbeatTimer = undefined;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
132
|
recordSuccess(ns, host, port) {
|
|
157
133
|
const excludes = this.circuitBreakers.get(ns);
|
|
158
134
|
if (excludes) {
|
|
@@ -263,13 +239,6 @@ export class Application extends Server {
|
|
|
263
239
|
});
|
|
264
240
|
}
|
|
265
241
|
async call(namespace, url, data, timeout, retries = 1) {
|
|
266
|
-
// Inject or preserve correlation ID (no mutation of original data)
|
|
267
|
-
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
268
|
-
data = { _correlationId: randomUUID(), data };
|
|
269
|
-
}
|
|
270
|
-
else if (!data._correlationId) {
|
|
271
|
-
data = { ...data, _correlationId: randomUUID() };
|
|
272
|
-
}
|
|
273
242
|
const exclude = this.getActiveExcludes(namespace);
|
|
274
243
|
let client;
|
|
275
244
|
try {
|
package/dist/client.d.ts
CHANGED
|
@@ -14,8 +14,12 @@ export declare class Client extends MessageWs {
|
|
|
14
14
|
readonly host: string;
|
|
15
15
|
readonly port: number;
|
|
16
16
|
private _online;
|
|
17
|
+
private lastHeartbeat;
|
|
18
|
+
private heartbeatTimer?;
|
|
19
|
+
private checkTimer?;
|
|
17
20
|
readonly events: EventEmitter<any>;
|
|
18
21
|
constructor(props: ClientProps);
|
|
22
|
+
private startHeartbeat;
|
|
19
23
|
protected exec(data: {
|
|
20
24
|
url: string;
|
|
21
25
|
data: any;
|
package/dist/client.js
CHANGED
|
@@ -7,6 +7,9 @@ export class Client extends MessageWs {
|
|
|
7
7
|
host;
|
|
8
8
|
port;
|
|
9
9
|
_online = true;
|
|
10
|
+
lastHeartbeat = Date.now();
|
|
11
|
+
heartbeatTimer;
|
|
12
|
+
checkTimer;
|
|
10
13
|
events = new EventEmitter();
|
|
11
14
|
constructor(props) {
|
|
12
15
|
const { server, ws, host, port } = props;
|
|
@@ -17,8 +20,32 @@ export class Client extends MessageWs {
|
|
|
17
20
|
this.port = port;
|
|
18
21
|
this.events.on('connect', () => this._online = true);
|
|
19
22
|
this.events.on('disconnect', () => this._online = false);
|
|
23
|
+
this.lastHeartbeat = Date.now();
|
|
24
|
+
this.startHeartbeat();
|
|
25
|
+
}
|
|
26
|
+
startHeartbeat() {
|
|
27
|
+
const interval = Number(process.env.MICRO_HEARTBEAT_INTERVAL) || 10_000;
|
|
28
|
+
const timeout = Number(process.env.MICRO_HEARTBEAT_TIMEOUT) || 20_000;
|
|
29
|
+
const checkInterval = Number(process.env.MICRO_HEARTBEAT_CHECK_INTERVAL) || 5_000;
|
|
30
|
+
this.heartbeatTimer = setInterval(() => {
|
|
31
|
+
try {
|
|
32
|
+
this._push({ url: '/-/heartbeat', data: {} });
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// connection closed — will be cleaned up by checkTimer or close event
|
|
36
|
+
}
|
|
37
|
+
}, interval);
|
|
38
|
+
this.checkTimer = setInterval(() => {
|
|
39
|
+
if (Date.now() - this.lastHeartbeat > timeout) {
|
|
40
|
+
this.dispose();
|
|
41
|
+
}
|
|
42
|
+
}, checkInterval);
|
|
20
43
|
}
|
|
21
44
|
async exec(data) {
|
|
45
|
+
if (data.url === '/-/heartbeat') {
|
|
46
|
+
this.lastHeartbeat = Date.now();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
22
49
|
if (!this._online)
|
|
23
50
|
throw new Error('Client is not online');
|
|
24
51
|
return this.server.dispatch(data.url, data.data, {
|
|
@@ -36,6 +63,10 @@ export class Client extends MessageWs {
|
|
|
36
63
|
return this._push({ url, data }, timeout);
|
|
37
64
|
}
|
|
38
65
|
dispose() {
|
|
66
|
+
if (this.heartbeatTimer)
|
|
67
|
+
clearInterval(this.heartbeatTimer);
|
|
68
|
+
if (this.checkTimer)
|
|
69
|
+
clearInterval(this.checkTimer);
|
|
39
70
|
super.dispose();
|
|
40
71
|
if (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING) {
|
|
41
72
|
this.socket.close();
|
package/dist/registry.d.ts
CHANGED
|
@@ -16,9 +16,6 @@ export declare function parseConfigFilename(filename: string): string | null;
|
|
|
16
16
|
export declare class Registry extends Server {
|
|
17
17
|
private readonly namespaces;
|
|
18
18
|
private unregisterFind?;
|
|
19
|
-
private static readonly HEARTBEAT_INTERVAL;
|
|
20
|
-
private static readonly HEARTBEAT_TIMEOUT;
|
|
21
|
-
private readonly heartbeats;
|
|
22
19
|
private readonly workspace;
|
|
23
20
|
private readonly configFileSuffix;
|
|
24
21
|
private readonly configs;
|
package/dist/registry.js
CHANGED
|
@@ -42,9 +42,6 @@ export function parseConfigFilename(filename) {
|
|
|
42
42
|
export class Registry extends Server {
|
|
43
43
|
namespaces = new Map();
|
|
44
44
|
unregisterFind;
|
|
45
|
-
static HEARTBEAT_INTERVAL = 1000;
|
|
46
|
-
static HEARTBEAT_TIMEOUT = 20000;
|
|
47
|
-
heartbeats = new Map();
|
|
48
45
|
workspace;
|
|
49
46
|
configFileSuffix = '.config.yaml';
|
|
50
47
|
configs = new Map();
|
|
@@ -57,7 +54,6 @@ export class Registry extends Server {
|
|
|
57
54
|
this.workspace = workspace;
|
|
58
55
|
this.events.on('connect', (client, extras) => {
|
|
59
56
|
const key = client.host + ':' + client.port;
|
|
60
|
-
this.heartbeats.set(key, Date.now());
|
|
61
57
|
const namespace = extras.join('/');
|
|
62
58
|
if (!this.namespaces.has(namespace)) {
|
|
63
59
|
this.namespaces.set(namespace, new Set());
|
|
@@ -66,7 +62,6 @@ export class Registry extends Server {
|
|
|
66
62
|
});
|
|
67
63
|
this.events.on('disconnect', (client, extras) => {
|
|
68
64
|
const key = client.host + ':' + client.port;
|
|
69
|
-
this.heartbeats.delete(key);
|
|
70
65
|
const namespace = extras.join('/');
|
|
71
66
|
if (this.namespaces.has(namespace)) {
|
|
72
67
|
const keys = this.namespaces.get(namespace);
|
|
@@ -80,12 +75,6 @@ export class Registry extends Server {
|
|
|
80
75
|
});
|
|
81
76
|
this.mountFindHandler();
|
|
82
77
|
this.registerEnvVariables();
|
|
83
|
-
this.register('/-/heartbeat', async ({ client }) => {
|
|
84
|
-
if (!client)
|
|
85
|
-
return;
|
|
86
|
-
const key = client.host + ':' + client.port;
|
|
87
|
-
this.heartbeats.set(key, Date.now());
|
|
88
|
-
});
|
|
89
78
|
}
|
|
90
79
|
watchEnvFile() {
|
|
91
80
|
const configFile = resolve(this.workspace, 'configs');
|
|
@@ -104,8 +93,14 @@ export class Registry extends Server {
|
|
|
104
93
|
return watch(configFile, (_, filename) => {
|
|
105
94
|
if (!filename?.endsWith(this.configFileSuffix))
|
|
106
95
|
return;
|
|
96
|
+
const fullPath = resolve(configFile, filename);
|
|
97
|
+
// 文件被删除(或重命名):移除对应配置
|
|
98
|
+
if (!existsSync(fullPath)) {
|
|
99
|
+
this.configs.delete(parseConfigFilename(filename));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
107
102
|
try {
|
|
108
|
-
const config = YAML.parse(readFileSync(
|
|
103
|
+
const config = YAML.parse(readFileSync(fullPath, 'utf8'));
|
|
109
104
|
if (typeof config !== 'object' || config === null)
|
|
110
105
|
return;
|
|
111
106
|
this.configs.set(parseConfigFilename(filename), config);
|
|
@@ -119,23 +114,10 @@ export class Registry extends Server {
|
|
|
119
114
|
if (!_port || _port <= 0)
|
|
120
115
|
throw new Error('Unable to resolve registry port: pass `port` in constructor options, or ensure process.env.REGISTRY_PORT is set.');
|
|
121
116
|
const teardown = await super.listen(_port);
|
|
122
|
-
const timer = setInterval(() => {
|
|
123
|
-
const now = Date.now();
|
|
124
|
-
for (const [key, lastTime] of this.heartbeats) {
|
|
125
|
-
if (now - lastTime >= Registry.HEARTBEAT_TIMEOUT) {
|
|
126
|
-
const client = this.clients.get(key);
|
|
127
|
-
if (client) {
|
|
128
|
-
this.heartbeats.delete(key);
|
|
129
|
-
client.dispose();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}, Registry.HEARTBEAT_INTERVAL);
|
|
134
117
|
const watcher = this.watchEnvFile();
|
|
135
118
|
return async () => {
|
|
136
119
|
if (watcher)
|
|
137
120
|
watcher.close();
|
|
138
|
-
clearInterval(timer);
|
|
139
121
|
await teardown();
|
|
140
122
|
};
|
|
141
123
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/micro",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"vitest": "^4.0.18"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@hile/message-loader": "^1.0.
|
|
26
|
+
"@hile/message-loader": "^1.0.9",
|
|
27
27
|
"@hile/message-ws": "^1.0.6",
|
|
28
28
|
"internal-ip": "^9.0.0",
|
|
29
29
|
"ws": "^8.19.0",
|
|
30
30
|
"yaml": "^2.9.0"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "be31521d206109a1ed6e915ec231a849870b538c"
|
|
33
33
|
}
|