@flink-app/streaming-plugin 0.12.1-alpha.45
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/LICENSE +21 -0
- package/README.md +476 -0
- package/dist/StreamingPlugin.d.ts +45 -0
- package/dist/StreamingPlugin.d.ts.map +1 -0
- package/dist/StreamingPlugin.js +276 -0
- package/dist/StreamingPlugin.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/examples/authenticated-stream.ts +88 -0
- package/examples/client-ndjson.html +157 -0
- package/examples/client-sse.html +202 -0
- package/package.json +41 -0
- package/spec/StreamingPlugin.spec.ts +513 -0
- package/spec/support/jasmine.json +7 -0
- package/src/StreamingPlugin.ts +281 -0
- package/src/index.ts +13 -0
- package/src/types.ts +101 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>SSE Streaming Example</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 50px auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
}
|
|
14
|
+
#output {
|
|
15
|
+
background: #f5f5f5;
|
|
16
|
+
padding: 20px;
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
min-height: 200px;
|
|
19
|
+
}
|
|
20
|
+
.event {
|
|
21
|
+
padding: 10px;
|
|
22
|
+
margin: 5px 0;
|
|
23
|
+
border-radius: 4px;
|
|
24
|
+
background: white;
|
|
25
|
+
border-left: 4px solid #007bff;
|
|
26
|
+
}
|
|
27
|
+
.event.update {
|
|
28
|
+
border-left-color: #28a745;
|
|
29
|
+
}
|
|
30
|
+
.event.notification {
|
|
31
|
+
border-left-color: #ffc107;
|
|
32
|
+
}
|
|
33
|
+
.event.alert {
|
|
34
|
+
border-left-color: #dc3545;
|
|
35
|
+
}
|
|
36
|
+
.event.error {
|
|
37
|
+
border-left-color: #dc3545;
|
|
38
|
+
background: #ffebee;
|
|
39
|
+
}
|
|
40
|
+
button {
|
|
41
|
+
background: #007bff;
|
|
42
|
+
color: white;
|
|
43
|
+
border: none;
|
|
44
|
+
padding: 10px 20px;
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
font-size: 16px;
|
|
48
|
+
margin-right: 10px;
|
|
49
|
+
}
|
|
50
|
+
button:hover {
|
|
51
|
+
background: #0056b3;
|
|
52
|
+
}
|
|
53
|
+
button:disabled {
|
|
54
|
+
background: #ccc;
|
|
55
|
+
cursor: not-allowed;
|
|
56
|
+
}
|
|
57
|
+
.controls {
|
|
58
|
+
margin-bottom: 20px;
|
|
59
|
+
}
|
|
60
|
+
.status {
|
|
61
|
+
display: inline-block;
|
|
62
|
+
padding: 5px 10px;
|
|
63
|
+
border-radius: 4px;
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
margin-left: 10px;
|
|
66
|
+
}
|
|
67
|
+
.status.connected {
|
|
68
|
+
background: #d4edda;
|
|
69
|
+
color: #155724;
|
|
70
|
+
}
|
|
71
|
+
.status.disconnected {
|
|
72
|
+
background: #f8d7da;
|
|
73
|
+
color: #721c24;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
76
|
+
</head>
|
|
77
|
+
<body>
|
|
78
|
+
<h1>SSE Streaming Example</h1>
|
|
79
|
+
<p>This example demonstrates consuming Server-Sent Events (SSE) from Flink for live updates.</p>
|
|
80
|
+
|
|
81
|
+
<div class="controls">
|
|
82
|
+
<button id="connectBtn" onclick="connect()">Connect</button>
|
|
83
|
+
<button id="disconnectBtn" onclick="disconnect()" disabled>Disconnect</button>
|
|
84
|
+
<button onclick="clearOutput()">Clear</button>
|
|
85
|
+
<span id="status" class="status disconnected">Disconnected</span>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<h3>Live Updates:</h3>
|
|
89
|
+
<div id="output"></div>
|
|
90
|
+
|
|
91
|
+
<script>
|
|
92
|
+
let eventSource = null;
|
|
93
|
+
|
|
94
|
+
function connect() {
|
|
95
|
+
const output = document.getElementById('output');
|
|
96
|
+
const connectBtn = document.getElementById('connectBtn');
|
|
97
|
+
const disconnectBtn = document.getElementById('disconnectBtn');
|
|
98
|
+
const status = document.getElementById('status');
|
|
99
|
+
|
|
100
|
+
// Create EventSource connection
|
|
101
|
+
eventSource = new EventSource('http://localhost:3333/live-updates');
|
|
102
|
+
|
|
103
|
+
// Connection opened
|
|
104
|
+
eventSource.onopen = () => {
|
|
105
|
+
console.log('SSE connection opened');
|
|
106
|
+
status.textContent = 'Connected';
|
|
107
|
+
status.className = 'status connected';
|
|
108
|
+
connectBtn.disabled = true;
|
|
109
|
+
disconnectBtn.disabled = false;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Message received
|
|
113
|
+
eventSource.onmessage = (event) => {
|
|
114
|
+
try {
|
|
115
|
+
const data = JSON.parse(event.data);
|
|
116
|
+
addEvent(data);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('Failed to parse event data:', error);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Error event
|
|
123
|
+
eventSource.addEventListener('error', (event) => {
|
|
124
|
+
if (event.data) {
|
|
125
|
+
try {
|
|
126
|
+
const error = JSON.parse(event.data);
|
|
127
|
+
addEvent({ type: 'error', message: error.message, timestamp: Date.now() });
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.error('Error event:', event);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Connection error
|
|
135
|
+
eventSource.onerror = (error) => {
|
|
136
|
+
console.error('SSE connection error:', error);
|
|
137
|
+
status.textContent = 'Disconnected';
|
|
138
|
+
status.className = 'status disconnected';
|
|
139
|
+
connectBtn.disabled = false;
|
|
140
|
+
disconnectBtn.disabled = true;
|
|
141
|
+
|
|
142
|
+
// EventSource will automatically try to reconnect
|
|
143
|
+
addEvent({
|
|
144
|
+
type: 'error',
|
|
145
|
+
message: 'Connection lost. Reconnecting...',
|
|
146
|
+
timestamp: Date.now()
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function disconnect() {
|
|
152
|
+
if (eventSource) {
|
|
153
|
+
eventSource.close();
|
|
154
|
+
eventSource = null;
|
|
155
|
+
|
|
156
|
+
const status = document.getElementById('status');
|
|
157
|
+
status.textContent = 'Disconnected';
|
|
158
|
+
status.className = 'status disconnected';
|
|
159
|
+
|
|
160
|
+
document.getElementById('connectBtn').disabled = false;
|
|
161
|
+
document.getElementById('disconnectBtn').disabled = true;
|
|
162
|
+
|
|
163
|
+
addEvent({
|
|
164
|
+
type: 'alert',
|
|
165
|
+
message: 'Manually disconnected',
|
|
166
|
+
timestamp: Date.now()
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function addEvent(data) {
|
|
172
|
+
const output = document.getElementById('output');
|
|
173
|
+
const eventDiv = document.createElement('div');
|
|
174
|
+
eventDiv.className = `event ${data.type || 'update'}`;
|
|
175
|
+
|
|
176
|
+
const time = new Date(data.timestamp).toLocaleTimeString();
|
|
177
|
+
eventDiv.innerHTML = `
|
|
178
|
+
<strong>${data.type || 'update'}</strong>: ${data.message}
|
|
179
|
+
<span style="float: right; color: #666; font-size: 12px;">${time}</span>
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
output.insertBefore(eventDiv, output.firstChild);
|
|
183
|
+
|
|
184
|
+
// Keep only last 20 events
|
|
185
|
+
while (output.children.length > 20) {
|
|
186
|
+
output.removeChild(output.lastChild);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function clearOutput() {
|
|
191
|
+
document.getElementById('output').innerHTML = '';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Clean up on page unload
|
|
195
|
+
window.addEventListener('beforeunload', () => {
|
|
196
|
+
if (eventSource) {
|
|
197
|
+
eventSource.close();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
</script>
|
|
201
|
+
</body>
|
|
202
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flink-app/streaming-plugin",
|
|
3
|
+
"version": "0.12.1-alpha.45",
|
|
4
|
+
"description": "Streaming response support for Flink Framework (SSE and NDJSON)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"watch": "tsc --watch",
|
|
10
|
+
"test": "ts-node -O '{\"module\":\"commonjs\"}' node_modules/jasmine/bin/jasmine",
|
|
11
|
+
"prepublishOnly": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"flink",
|
|
15
|
+
"streaming",
|
|
16
|
+
"sse",
|
|
17
|
+
"server-sent-events",
|
|
18
|
+
"ndjson",
|
|
19
|
+
"llm",
|
|
20
|
+
"chat"
|
|
21
|
+
],
|
|
22
|
+
"author": "Frost",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@flink-app/flink": "^0.12.1-alpha.40"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@flink-app/flink": "^0.12.1-alpha.45",
|
|
32
|
+
"@types/express": "^4.17.21",
|
|
33
|
+
"@types/jasmine": "^3.7.1",
|
|
34
|
+
"@types/node": "^20.10.0",
|
|
35
|
+
"jasmine": "^3.7.0",
|
|
36
|
+
"jasmine-spec-reporter": "^7.0.0",
|
|
37
|
+
"ts-node": "^10.0.0",
|
|
38
|
+
"typescript": "^5.3.3"
|
|
39
|
+
},
|
|
40
|
+
"gitHead": "af426a157217c110ac9c7beb48e2e746968bec33"
|
|
41
|
+
}
|