@inferencesh/sdk 0.1.0 → 0.1.3
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/CHANGELOG.md +14 -1
- package/README.md +4 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +47 -5
- package/dist/client.test.d.ts +1 -0
- package/dist/client.test.js +212 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.js +61 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -1
- package/dist/stream.d.ts +8 -1
- package/dist/stream.js +27 -2
- package/dist/stream.test.d.ts +1 -0
- package/dist/stream.test.js +168 -0
- package/dist/types.d.ts +1364 -436
- package/dist/types.js +167 -23
- package/package.json +1 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const stream_1 = require("./stream");
|
|
4
|
+
describe('StreamManager', () => {
|
|
5
|
+
let mockEventSource;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
mockEventSource = {
|
|
8
|
+
onmessage: null,
|
|
9
|
+
onerror: null,
|
|
10
|
+
close: jest.fn(),
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
describe('constructor', () => {
|
|
14
|
+
it('should create instance with default options', () => {
|
|
15
|
+
const manager = new stream_1.StreamManager({
|
|
16
|
+
createEventSource: async () => mockEventSource,
|
|
17
|
+
});
|
|
18
|
+
expect(manager).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe('connect', () => {
|
|
22
|
+
it('should call createEventSource', async () => {
|
|
23
|
+
const createEventSource = jest
|
|
24
|
+
.fn()
|
|
25
|
+
.mockResolvedValue(mockEventSource);
|
|
26
|
+
const manager = new stream_1.StreamManager({ createEventSource });
|
|
27
|
+
await manager.connect();
|
|
28
|
+
expect(createEventSource).toHaveBeenCalled();
|
|
29
|
+
});
|
|
30
|
+
it('should call onStart when connected', async () => {
|
|
31
|
+
const onStart = jest.fn();
|
|
32
|
+
const manager = new stream_1.StreamManager({
|
|
33
|
+
createEventSource: async () => mockEventSource,
|
|
34
|
+
onStart,
|
|
35
|
+
});
|
|
36
|
+
await manager.connect();
|
|
37
|
+
expect(onStart).toHaveBeenCalled();
|
|
38
|
+
});
|
|
39
|
+
it('should parse JSON messages and call onData', async () => {
|
|
40
|
+
const onData = jest.fn();
|
|
41
|
+
const manager = new stream_1.StreamManager({
|
|
42
|
+
createEventSource: async () => mockEventSource,
|
|
43
|
+
onData,
|
|
44
|
+
});
|
|
45
|
+
await manager.connect();
|
|
46
|
+
// Simulate receiving a message
|
|
47
|
+
const testData = { status: 'running', id: 'task-123' };
|
|
48
|
+
mockEventSource.onmessage?.({ data: JSON.stringify(testData) });
|
|
49
|
+
expect(onData).toHaveBeenCalledWith(testData);
|
|
50
|
+
});
|
|
51
|
+
it('should extract data from partial data wrapper and call onData', async () => {
|
|
52
|
+
const onData = jest.fn();
|
|
53
|
+
const manager = new stream_1.StreamManager({
|
|
54
|
+
createEventSource: async () => mockEventSource,
|
|
55
|
+
onData,
|
|
56
|
+
});
|
|
57
|
+
await manager.connect();
|
|
58
|
+
// Simulate receiving a partial data wrapper from server
|
|
59
|
+
const innerData = { status: 7, id: 'task-123', logs: ['log1'] };
|
|
60
|
+
const partialWrapper = { data: innerData, fields: ['status', 'logs'] };
|
|
61
|
+
mockEventSource.onmessage?.({ data: JSON.stringify(partialWrapper) });
|
|
62
|
+
// onData should receive the extracted inner data, not the wrapper
|
|
63
|
+
expect(onData).toHaveBeenCalledWith(innerData);
|
|
64
|
+
});
|
|
65
|
+
it('should call onPartialData with data and fields for partial updates', async () => {
|
|
66
|
+
const onData = jest.fn();
|
|
67
|
+
const onPartialData = jest.fn();
|
|
68
|
+
const manager = new stream_1.StreamManager({
|
|
69
|
+
createEventSource: async () => mockEventSource,
|
|
70
|
+
onData,
|
|
71
|
+
onPartialData,
|
|
72
|
+
});
|
|
73
|
+
await manager.connect();
|
|
74
|
+
// Simulate receiving a partial data wrapper
|
|
75
|
+
const innerData = { status: 7, id: 'task-123' };
|
|
76
|
+
const fields = ['status'];
|
|
77
|
+
const partialWrapper = { data: innerData, fields };
|
|
78
|
+
mockEventSource.onmessage?.({ data: JSON.stringify(partialWrapper) });
|
|
79
|
+
expect(onPartialData).toHaveBeenCalledWith(innerData, fields);
|
|
80
|
+
expect(onData).toHaveBeenCalledWith(innerData);
|
|
81
|
+
});
|
|
82
|
+
it('should not call onPartialData for non-partial data', async () => {
|
|
83
|
+
const onData = jest.fn();
|
|
84
|
+
const onPartialData = jest.fn();
|
|
85
|
+
const manager = new stream_1.StreamManager({
|
|
86
|
+
createEventSource: async () => mockEventSource,
|
|
87
|
+
onData,
|
|
88
|
+
onPartialData,
|
|
89
|
+
});
|
|
90
|
+
await manager.connect();
|
|
91
|
+
// Regular data without partial wrapper
|
|
92
|
+
const regularData = { status: 9, id: 'task-123' };
|
|
93
|
+
mockEventSource.onmessage?.({ data: JSON.stringify(regularData) });
|
|
94
|
+
expect(onPartialData).not.toHaveBeenCalled();
|
|
95
|
+
expect(onData).toHaveBeenCalledWith(regularData);
|
|
96
|
+
});
|
|
97
|
+
it('should call onError for invalid JSON', async () => {
|
|
98
|
+
const onError = jest.fn();
|
|
99
|
+
const manager = new stream_1.StreamManager({
|
|
100
|
+
createEventSource: async () => mockEventSource,
|
|
101
|
+
onError,
|
|
102
|
+
});
|
|
103
|
+
await manager.connect();
|
|
104
|
+
mockEventSource.onmessage?.({ data: 'invalid json' });
|
|
105
|
+
expect(onError).toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('stop', () => {
|
|
109
|
+
it('should close the event source', async () => {
|
|
110
|
+
const onStop = jest.fn();
|
|
111
|
+
const manager = new stream_1.StreamManager({
|
|
112
|
+
createEventSource: async () => mockEventSource,
|
|
113
|
+
onStop,
|
|
114
|
+
});
|
|
115
|
+
await manager.connect();
|
|
116
|
+
manager.stop();
|
|
117
|
+
expect(mockEventSource.close).toHaveBeenCalled();
|
|
118
|
+
expect(onStop).toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
it('should not process messages after stop', async () => {
|
|
121
|
+
const onData = jest.fn();
|
|
122
|
+
const manager = new stream_1.StreamManager({
|
|
123
|
+
createEventSource: async () => mockEventSource,
|
|
124
|
+
onData,
|
|
125
|
+
});
|
|
126
|
+
await manager.connect();
|
|
127
|
+
manager.stop();
|
|
128
|
+
mockEventSource.onmessage?.({ data: '{"status":"running"}' });
|
|
129
|
+
expect(onData).not.toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('reconnection', () => {
|
|
133
|
+
it('should attempt reconnection on error when autoReconnect is true', async () => {
|
|
134
|
+
jest.useFakeTimers();
|
|
135
|
+
const createEventSource = jest
|
|
136
|
+
.fn()
|
|
137
|
+
.mockResolvedValue(mockEventSource);
|
|
138
|
+
const manager = new stream_1.StreamManager({
|
|
139
|
+
createEventSource,
|
|
140
|
+
autoReconnect: true,
|
|
141
|
+
reconnectDelayMs: 100,
|
|
142
|
+
});
|
|
143
|
+
await manager.connect();
|
|
144
|
+
expect(createEventSource).toHaveBeenCalledTimes(1);
|
|
145
|
+
// Simulate error
|
|
146
|
+
mockEventSource.onerror?.({});
|
|
147
|
+
// Fast-forward past reconnect delay
|
|
148
|
+
jest.advanceTimersByTime(100);
|
|
149
|
+
await Promise.resolve(); // Flush promises
|
|
150
|
+
expect(createEventSource).toHaveBeenCalledTimes(2);
|
|
151
|
+
jest.useRealTimers();
|
|
152
|
+
});
|
|
153
|
+
it('should not reconnect when autoReconnect is false', async () => {
|
|
154
|
+
const createEventSource = jest
|
|
155
|
+
.fn()
|
|
156
|
+
.mockResolvedValue(mockEventSource);
|
|
157
|
+
const manager = new stream_1.StreamManager({
|
|
158
|
+
createEventSource,
|
|
159
|
+
autoReconnect: false,
|
|
160
|
+
});
|
|
161
|
+
await manager.connect();
|
|
162
|
+
mockEventSource.onerror?.({});
|
|
163
|
+
// Wait a bit
|
|
164
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
165
|
+
expect(createEventSource).toHaveBeenCalledTimes(1);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|