@hile/message-modem 1.0.6 → 2.0.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/dist/index.d.ts +25 -6
- package/dist/index.js +231 -108
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
1
2
|
export * from './exception.js';
|
|
2
3
|
export declare enum MESSAGE_MODEM_TYPE {
|
|
3
4
|
REQUEST = 0,
|
|
@@ -8,6 +9,7 @@ export interface MessageTransferFormat<T = any> {
|
|
|
8
9
|
id: number;
|
|
9
10
|
mode: MESSAGE_MODEM_TYPE;
|
|
10
11
|
twoway: boolean;
|
|
12
|
+
stream?: boolean;
|
|
11
13
|
data?: T;
|
|
12
14
|
}
|
|
13
15
|
export interface MessageReturnFormat<T = any> {
|
|
@@ -15,10 +17,17 @@ export interface MessageReturnFormat<T = any> {
|
|
|
15
17
|
data: T;
|
|
16
18
|
message: string;
|
|
17
19
|
}
|
|
20
|
+
export interface MessageStreamChunk<T = any> {
|
|
21
|
+
status: string | number;
|
|
22
|
+
seq: number;
|
|
23
|
+
payload: T;
|
|
24
|
+
final: boolean;
|
|
25
|
+
}
|
|
18
26
|
export declare abstract class MessageModem {
|
|
19
27
|
private id;
|
|
20
28
|
private readonly aborts;
|
|
21
29
|
private readonly stacks;
|
|
30
|
+
private readonly streams;
|
|
22
31
|
protected _dispose(): void;
|
|
23
32
|
/**
|
|
24
33
|
* 创建自增 ID
|
|
@@ -36,7 +45,7 @@ export declare abstract class MessageModem {
|
|
|
36
45
|
* @param data - 消息数据
|
|
37
46
|
* @returns
|
|
38
47
|
*/
|
|
39
|
-
protected abstract exec(data: any): Promise<any>;
|
|
48
|
+
protected abstract exec(data: any, signal?: AbortSignal): Promise<any>;
|
|
40
49
|
/**
|
|
41
50
|
* 创建发送消息数据
|
|
42
51
|
* @param mode - 消息类型
|
|
@@ -48,19 +57,27 @@ export declare abstract class MessageModem {
|
|
|
48
57
|
* 发送消息
|
|
49
58
|
* @param data - 消息数据
|
|
50
59
|
* @param timeout - 超时时间
|
|
60
|
+
* @param signal - 中止信号
|
|
51
61
|
* @returns 消息响应
|
|
52
62
|
*/
|
|
53
|
-
protected _send<T = any>(data:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
63
|
+
protected _send<T = any>(data: any, options?: {
|
|
64
|
+
timeout?: number;
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}): Promise<T>;
|
|
57
67
|
/**
|
|
58
68
|
* 推送消息
|
|
59
69
|
* @param data - 消息数据
|
|
60
70
|
* @param timeout - 超时时间
|
|
71
|
+
* @param signal - 中止信号
|
|
61
72
|
* @returns 消息响应
|
|
62
73
|
*/
|
|
63
|
-
protected _push<T = any>(data: T,
|
|
74
|
+
protected _push<T = any>(data: T, options?: {
|
|
75
|
+
timeout?: number;
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}): void;
|
|
78
|
+
protected _stream(data: any, options?: {
|
|
79
|
+
signal?: AbortSignal;
|
|
80
|
+
}): Readable;
|
|
64
81
|
/**
|
|
65
82
|
* 写入消息
|
|
66
83
|
* @param data - 消息数据
|
|
@@ -78,6 +95,8 @@ export declare abstract class MessageModem {
|
|
|
78
95
|
* @param msg - 消息数据
|
|
79
96
|
*/
|
|
80
97
|
private onResponse;
|
|
98
|
+
private onStreamRequest;
|
|
99
|
+
private onStreamResponse;
|
|
81
100
|
/**
|
|
82
101
|
* 接收消息
|
|
83
102
|
* @param msg - 消息数据
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AbortException, Exception, TimeoutException } from "./exception.js";
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
2
3
|
export * from './exception.js';
|
|
3
4
|
export var MESSAGE_MODEM_TYPE;
|
|
4
5
|
(function (MESSAGE_MODEM_TYPE) {
|
|
@@ -10,15 +11,20 @@ export class MessageModem {
|
|
|
10
11
|
id = 0;
|
|
11
12
|
aborts = new Map();
|
|
12
13
|
stacks = new Map();
|
|
14
|
+
streams = new Map();
|
|
13
15
|
_dispose() {
|
|
14
16
|
for (const { reject } of this.stacks.values()) {
|
|
15
17
|
reject(new AbortException());
|
|
16
18
|
}
|
|
17
|
-
for (const
|
|
18
|
-
|
|
19
|
+
for (const controller of this.aborts.values()) {
|
|
20
|
+
controller.abort();
|
|
21
|
+
}
|
|
22
|
+
for (const stream of this.streams.values()) {
|
|
23
|
+
stream.destroy(new AbortException());
|
|
19
24
|
}
|
|
20
25
|
this.aborts.clear();
|
|
21
26
|
this.stacks.clear();
|
|
27
|
+
this.streams.clear();
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* 创建自增 ID
|
|
@@ -38,13 +44,14 @@ export class MessageModem {
|
|
|
38
44
|
* @param data - 消息数据
|
|
39
45
|
* @returns 消息数据
|
|
40
46
|
*/
|
|
41
|
-
createPostData(mode, data, twoway = true) {
|
|
47
|
+
createPostData(mode, data, twoway = true, stream = false) {
|
|
42
48
|
const id = this.createIncrementId();
|
|
43
49
|
const state = {
|
|
44
|
-
id, twoway, data, mode,
|
|
50
|
+
id, twoway, data, mode, stream,
|
|
45
51
|
};
|
|
46
52
|
if (mode === MESSAGE_MODEM_TYPE.ABORT) {
|
|
47
53
|
state.twoway = false;
|
|
54
|
+
state.stream = false;
|
|
48
55
|
}
|
|
49
56
|
return state;
|
|
50
57
|
}
|
|
@@ -52,19 +59,50 @@ export class MessageModem {
|
|
|
52
59
|
* 发送消息
|
|
53
60
|
* @param data - 消息数据
|
|
54
61
|
* @param timeout - 超时时间
|
|
62
|
+
* @param signal - 中止信号
|
|
55
63
|
* @returns 消息响应
|
|
56
64
|
*/
|
|
57
|
-
_send(data,
|
|
58
|
-
return this._write(data,
|
|
65
|
+
_send(data, options) {
|
|
66
|
+
return this._write(data, {
|
|
67
|
+
timeout: options?.timeout ?? 30000,
|
|
68
|
+
twoway: true,
|
|
69
|
+
signal: options?.signal,
|
|
70
|
+
});
|
|
59
71
|
}
|
|
60
72
|
/**
|
|
61
73
|
* 推送消息
|
|
62
74
|
* @param data - 消息数据
|
|
63
75
|
* @param timeout - 超时时间
|
|
76
|
+
* @param signal - 中止信号
|
|
64
77
|
* @returns 消息响应
|
|
65
78
|
*/
|
|
66
|
-
_push(data,
|
|
67
|
-
this._write(data,
|
|
79
|
+
_push(data, options) {
|
|
80
|
+
this._write(data, {
|
|
81
|
+
timeout: options?.timeout ?? 30000,
|
|
82
|
+
twoway: false,
|
|
83
|
+
signal: options?.signal,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
_stream(data, options) {
|
|
87
|
+
const state = this.createPostData(MESSAGE_MODEM_TYPE.REQUEST, data, true, true);
|
|
88
|
+
const stream = new Readable({ objectMode: true, read() { } });
|
|
89
|
+
this.streams.set(state.id, stream);
|
|
90
|
+
this.post(state);
|
|
91
|
+
const onAbort = () => {
|
|
92
|
+
this.post(this.createPostData(MESSAGE_MODEM_TYPE.ABORT, state.id));
|
|
93
|
+
stream.destroy(new AbortException());
|
|
94
|
+
this.streams.delete(state.id);
|
|
95
|
+
};
|
|
96
|
+
if (options?.signal) {
|
|
97
|
+
options.signal.addEventListener('abort', onAbort);
|
|
98
|
+
}
|
|
99
|
+
stream.on('close', () => {
|
|
100
|
+
if (this.streams.has(state.id)) {
|
|
101
|
+
this.streams.delete(state.id);
|
|
102
|
+
}
|
|
103
|
+
options?.signal?.removeEventListener('abort', onAbort);
|
|
104
|
+
});
|
|
105
|
+
return stream;
|
|
68
106
|
}
|
|
69
107
|
/**
|
|
70
108
|
* 写入消息
|
|
@@ -72,7 +110,10 @@ export class MessageModem {
|
|
|
72
110
|
* @param timeout - 超时时间
|
|
73
111
|
* @returns 消息响应
|
|
74
112
|
*/
|
|
75
|
-
_write(data,
|
|
113
|
+
_write(data, options) {
|
|
114
|
+
const timeout = options?.timeout ?? 30000;
|
|
115
|
+
const twoway = !!options?.twoway;
|
|
116
|
+
const signal = options?.signal;
|
|
76
117
|
// 创建请求消息数据
|
|
77
118
|
const state = this.createPostData(MESSAGE_MODEM_TYPE.REQUEST, data, twoway);
|
|
78
119
|
// 发送消息
|
|
@@ -80,127 +121,101 @@ export class MessageModem {
|
|
|
80
121
|
// 如果消息是单向的,则直接返回
|
|
81
122
|
if (!twoway)
|
|
82
123
|
return;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
controller.signal.removeEventListener('abort', aborthandler);
|
|
98
|
-
clear();
|
|
99
|
-
};
|
|
100
|
-
// Abort 处理函数
|
|
101
|
-
const aborthandler = () => {
|
|
102
|
-
clearTimeout(timer);
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const clear = () => {
|
|
126
|
+
if (this.stacks.has(state.id)) {
|
|
127
|
+
this.stacks.delete(state.id);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const clean = () => {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
signal?.removeEventListener('abort', onAbort);
|
|
133
|
+
clear();
|
|
134
|
+
};
|
|
135
|
+
const onAbort = () => {
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
try {
|
|
103
138
|
this.post(this.createPostData(MESSAGE_MODEM_TYPE.ABORT, state.id));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
/* 例如 WebSocket 已关闭时 send 可能抛错 */
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
signal?.removeEventListener('abort', onAbort);
|
|
104
145
|
clear();
|
|
105
146
|
reject(new AbortException());
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}, timeout).unref();
|
|
126
|
-
// 添加 Abort 处理函数
|
|
127
|
-
controller.signal.addEventListener('abort', aborthandler);
|
|
128
|
-
// 添加栈
|
|
129
|
-
this.stacks.set(state.id, {
|
|
130
|
-
resolve: _resolve,
|
|
131
|
-
reject: _reject,
|
|
132
|
-
});
|
|
133
|
-
})
|
|
134
|
-
};
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
// 成功处理
|
|
150
|
+
const _resolve = (data) => {
|
|
151
|
+
clean();
|
|
152
|
+
resolve(data);
|
|
153
|
+
};
|
|
154
|
+
// 失败处理
|
|
155
|
+
const _reject = (e) => {
|
|
156
|
+
clean();
|
|
157
|
+
reject(e);
|
|
158
|
+
};
|
|
159
|
+
const timer = setTimeout(() => _reject(new TimeoutException()), timeout).unref();
|
|
160
|
+
signal?.addEventListener('abort', onAbort);
|
|
161
|
+
this.stacks.set(state.id, {
|
|
162
|
+
resolve: _resolve,
|
|
163
|
+
reject: _reject,
|
|
164
|
+
});
|
|
165
|
+
});
|
|
135
166
|
}
|
|
136
167
|
/**
|
|
137
168
|
* 处理请求消息
|
|
138
169
|
* @param msg - 消息数据
|
|
139
170
|
*/
|
|
140
171
|
onRequest(msg) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this.
|
|
145
|
-
|
|
146
|
-
]).then(value => {
|
|
147
|
-
// 如果消息执行失败
|
|
148
|
-
if (value?.e) {
|
|
149
|
-
// 如果消息是双向的,则发送响应消息
|
|
150
|
-
if (msg.twoway) {
|
|
151
|
-
this.post({
|
|
152
|
-
id: msg.id,
|
|
153
|
-
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
154
|
-
twoway: false,
|
|
155
|
-
data: {
|
|
156
|
-
status: value.e instanceof Exception ? value.e.status : 500,
|
|
157
|
-
data: null,
|
|
158
|
-
message: value.e.message,
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}
|
|
172
|
+
const controller = new AbortController();
|
|
173
|
+
this.aborts.set(msg.id, controller);
|
|
174
|
+
controller.signal.addEventListener('abort', () => {
|
|
175
|
+
if (this.aborts.has(msg.id)) {
|
|
176
|
+
this.aborts.delete(msg.id);
|
|
162
177
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
data: {
|
|
171
|
-
status: 200,
|
|
172
|
-
data: value,
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
178
|
+
});
|
|
179
|
+
this.exec(msg.data, controller.signal)
|
|
180
|
+
.then(value => {
|
|
181
|
+
if (controller.signal.aborted)
|
|
182
|
+
return;
|
|
183
|
+
if (isAsyncIterable(value)) {
|
|
184
|
+
throw new Exception(500, 'Async iterable is not supported');
|
|
176
185
|
}
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
if (msg.twoway) {
|
|
187
|
+
this.post({
|
|
188
|
+
id: msg.id,
|
|
189
|
+
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
190
|
+
twoway: false,
|
|
191
|
+
data: {
|
|
192
|
+
status: 200,
|
|
193
|
+
data: value,
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
.catch(e => {
|
|
199
|
+
if (controller.signal.aborted)
|
|
179
200
|
return;
|
|
180
|
-
// 如果消息是双向的,则发送响应消息
|
|
181
201
|
if (msg.twoway) {
|
|
182
|
-
// 发送响应消息
|
|
183
|
-
const code = e instanceof Exception ? e.status : 500;
|
|
184
202
|
this.post({
|
|
185
203
|
id: msg.id,
|
|
186
204
|
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
187
205
|
twoway: false,
|
|
188
206
|
data: {
|
|
189
|
-
status:
|
|
207
|
+
status: e instanceof Exception ? e.status : 500,
|
|
190
208
|
data: null,
|
|
191
209
|
message: e.message,
|
|
192
210
|
}
|
|
193
211
|
});
|
|
194
212
|
}
|
|
195
|
-
})
|
|
213
|
+
})
|
|
214
|
+
.finally(() => {
|
|
196
215
|
// 删除 Abort 处理函数
|
|
197
216
|
if (this.aborts.has(msg.id)) {
|
|
198
217
|
this.aborts.delete(msg.id);
|
|
199
218
|
}
|
|
200
|
-
// 清理栈
|
|
201
|
-
if (this.stacks.has(msg.id)) {
|
|
202
|
-
this.stacks.delete(msg.id);
|
|
203
|
-
}
|
|
204
219
|
});
|
|
205
220
|
}
|
|
206
221
|
/**
|
|
@@ -222,6 +237,99 @@ export class MessageModem {
|
|
|
222
237
|
}
|
|
223
238
|
}
|
|
224
239
|
}
|
|
240
|
+
onStreamRequest(msg) {
|
|
241
|
+
const controller = new AbortController();
|
|
242
|
+
this.aborts.set(msg.id, controller);
|
|
243
|
+
controller.signal.addEventListener('abort', () => {
|
|
244
|
+
if (this.aborts.has(msg.id)) {
|
|
245
|
+
this.aborts.delete(msg.id);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
this.exec(msg.data, controller.signal)
|
|
249
|
+
.then(async (value) => {
|
|
250
|
+
if (!isAsyncIterable(value)) {
|
|
251
|
+
throw new Exception(500, 'Invalid async iterable');
|
|
252
|
+
}
|
|
253
|
+
let i = 0;
|
|
254
|
+
for await (const chunk of value) {
|
|
255
|
+
if (controller.signal.aborted)
|
|
256
|
+
return;
|
|
257
|
+
this.post({
|
|
258
|
+
id: msg.id,
|
|
259
|
+
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
260
|
+
stream: true,
|
|
261
|
+
data: {
|
|
262
|
+
status: 200,
|
|
263
|
+
seq: i++,
|
|
264
|
+
payload: chunk,
|
|
265
|
+
final: false,
|
|
266
|
+
},
|
|
267
|
+
twoway: false,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
if (controller.signal.aborted)
|
|
271
|
+
return;
|
|
272
|
+
this.post({
|
|
273
|
+
id: msg.id,
|
|
274
|
+
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
275
|
+
stream: true,
|
|
276
|
+
data: {
|
|
277
|
+
status: 200,
|
|
278
|
+
seq: i++,
|
|
279
|
+
payload: undefined,
|
|
280
|
+
final: true,
|
|
281
|
+
},
|
|
282
|
+
twoway: false,
|
|
283
|
+
});
|
|
284
|
+
})
|
|
285
|
+
.catch(e => {
|
|
286
|
+
if (controller.signal.aborted)
|
|
287
|
+
return;
|
|
288
|
+
this.post({
|
|
289
|
+
id: msg.id,
|
|
290
|
+
mode: MESSAGE_MODEM_TYPE.RESPONSE,
|
|
291
|
+
stream: true,
|
|
292
|
+
data: {
|
|
293
|
+
status: e instanceof Exception ? e.status : 500,
|
|
294
|
+
seq: 0,
|
|
295
|
+
payload: e instanceof Exception ? e.message : 'Unknown error',
|
|
296
|
+
final: true,
|
|
297
|
+
},
|
|
298
|
+
twoway: false,
|
|
299
|
+
});
|
|
300
|
+
})
|
|
301
|
+
.finally(() => {
|
|
302
|
+
if (this.aborts.has(msg.id)) {
|
|
303
|
+
this.aborts.delete(msg.id);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
onStreamResponse(msg) {
|
|
308
|
+
const id = msg.id;
|
|
309
|
+
const res = msg.data;
|
|
310
|
+
// 如果栈中存在该消息,则处理响应消息
|
|
311
|
+
if (this.streams.has(id)) {
|
|
312
|
+
const stream = this.streams.get(id);
|
|
313
|
+
if (res) {
|
|
314
|
+
if (res.status === 200) {
|
|
315
|
+
if (res.final) {
|
|
316
|
+
stream.push(null);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
stream.push(res.payload);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
const err = new Exception(res.status, res.payload);
|
|
324
|
+
setImmediate(() => stream.destroy(err));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
const err = new Exception(404, 'Empty chunk data');
|
|
329
|
+
setImmediate(() => stream.destroy(err));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
225
333
|
/**
|
|
226
334
|
* 接收消息
|
|
227
335
|
* @param msg - 消息数据
|
|
@@ -231,20 +339,35 @@ export class MessageModem {
|
|
|
231
339
|
switch (msg.mode) {
|
|
232
340
|
// 处理请求消息
|
|
233
341
|
case MESSAGE_MODEM_TYPE.REQUEST:
|
|
234
|
-
|
|
342
|
+
if (msg.stream) {
|
|
343
|
+
this.onStreamRequest(msg);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
this.onRequest(msg);
|
|
347
|
+
}
|
|
235
348
|
break;
|
|
236
349
|
// 处理响应消息
|
|
237
350
|
case MESSAGE_MODEM_TYPE.RESPONSE:
|
|
238
|
-
|
|
351
|
+
if (msg.stream) {
|
|
352
|
+
this.onStreamResponse(msg);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
this.onResponse(msg);
|
|
356
|
+
}
|
|
239
357
|
break;
|
|
240
358
|
// 处理终止消息
|
|
241
359
|
case MESSAGE_MODEM_TYPE.ABORT:
|
|
242
360
|
const id = msg.data;
|
|
243
361
|
if (this.aborts.has(id)) {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
362
|
+
const controller = this.aborts.get(id);
|
|
363
|
+
if (!controller.signal.aborted) {
|
|
364
|
+
controller.abort();
|
|
365
|
+
}
|
|
247
366
|
}
|
|
367
|
+
break;
|
|
248
368
|
}
|
|
249
369
|
}
|
|
250
370
|
}
|
|
371
|
+
function isAsyncIterable(value) {
|
|
372
|
+
return value != null && typeof value[Symbol.asyncIterator] === 'function';
|
|
373
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/message-modem",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
"fix-esm-import-path": "^1.10.3",
|
|
22
22
|
"vitest": "^4.0.18"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "d28b20bc22ee08c45cbf4596672705cb96e8e461"
|
|
25
25
|
}
|