@rg-dev/stdlib 1.0.21 → 1.0.22
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/lib/node-env.cjs +122 -0
- package/lib/node-env.d.cts +30 -1
- package/lib/node-env.d.ts +30 -1
- package/lib/node-env.js +122 -0
- package/package.json +2 -4
package/lib/node-env.cjs
CHANGED
|
@@ -187,6 +187,8 @@ var require_command_exists2 = __commonJS({
|
|
|
187
187
|
// src/node-env.ts
|
|
188
188
|
var node_env_exports = {};
|
|
189
189
|
__export(node_env_exports, {
|
|
190
|
+
SSEClient: () => SSEClient,
|
|
191
|
+
SSEResponse: () => SSEResponse,
|
|
190
192
|
checkCommandExistsOrThrow: () => checkCommandExistsOrThrow,
|
|
191
193
|
checkIfDirExistsOrThrow: () => checkIfDirExistsOrThrow,
|
|
192
194
|
checkIfFileExistsOrThrow: () => checkIfFileExistsOrThrow,
|
|
@@ -200,6 +202,126 @@ var fs = __toESM(require("fs-extra"), 1);
|
|
|
200
202
|
var import_os = __toESM(require("os"), 1);
|
|
201
203
|
var import_path = __toESM(require("path"), 1);
|
|
202
204
|
var import_command_exists = __toESM(require_command_exists2(), 1);
|
|
205
|
+
|
|
206
|
+
// src/SSEResponse.ts
|
|
207
|
+
var SSEResponse = class {
|
|
208
|
+
res;
|
|
209
|
+
isOpen = true;
|
|
210
|
+
constructor(res) {
|
|
211
|
+
this.res = res;
|
|
212
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
213
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
214
|
+
res.setHeader("Connection", "keep-alive");
|
|
215
|
+
}
|
|
216
|
+
flushHeaders() {
|
|
217
|
+
var _a;
|
|
218
|
+
(_a = this.res) == null ? void 0 : _a.flushHeaders();
|
|
219
|
+
}
|
|
220
|
+
/** Send JSON to client, optionally with a custom event type */
|
|
221
|
+
emit(data, event) {
|
|
222
|
+
if (!this.isOpen)
|
|
223
|
+
return;
|
|
224
|
+
try {
|
|
225
|
+
let payload = "";
|
|
226
|
+
if (event) {
|
|
227
|
+
payload += `event: ${event}
|
|
228
|
+
`;
|
|
229
|
+
}
|
|
230
|
+
payload += `data: ${JSON.stringify(data)}
|
|
231
|
+
|
|
232
|
+
`;
|
|
233
|
+
if (this.res.writable) {
|
|
234
|
+
this.res.write(payload);
|
|
235
|
+
}
|
|
236
|
+
} catch (e) {
|
|
237
|
+
console.log("SSE Write error", e);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** Close the SSE connection */
|
|
241
|
+
close() {
|
|
242
|
+
if (!this.isOpen) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.isOpen = false;
|
|
246
|
+
if (!this.res.writableEnded) {
|
|
247
|
+
this.res.end();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// src/SSEClient.ts
|
|
253
|
+
var import_events = require("events");
|
|
254
|
+
var SSEClient = class extends import_events.EventEmitter {
|
|
255
|
+
url;
|
|
256
|
+
payload;
|
|
257
|
+
headers;
|
|
258
|
+
controller;
|
|
259
|
+
constructor(options) {
|
|
260
|
+
super();
|
|
261
|
+
this.url = options.url;
|
|
262
|
+
this.payload = options.payload || {};
|
|
263
|
+
this.headers = {
|
|
264
|
+
"Content-Type": "application/json",
|
|
265
|
+
Accept: "*/*",
|
|
266
|
+
...options.headers
|
|
267
|
+
};
|
|
268
|
+
this.controller = new AbortController();
|
|
269
|
+
}
|
|
270
|
+
async connect() {
|
|
271
|
+
try {
|
|
272
|
+
const res = await fetch(this.url, {
|
|
273
|
+
method: "POST",
|
|
274
|
+
headers: this.headers,
|
|
275
|
+
body: JSON.stringify(this.payload),
|
|
276
|
+
signal: this.controller.signal
|
|
277
|
+
});
|
|
278
|
+
if (!res.ok) {
|
|
279
|
+
const data = await res.text();
|
|
280
|
+
this.emit("error", new Error(`HTTP error: ${res.status} ${data}`));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const reader = res.body.getReader();
|
|
284
|
+
const decoder = new TextDecoder("utf-8");
|
|
285
|
+
let buffer = "";
|
|
286
|
+
let eventName = "message";
|
|
287
|
+
while (true) {
|
|
288
|
+
const { value, done } = await reader.read();
|
|
289
|
+
if (done)
|
|
290
|
+
break;
|
|
291
|
+
buffer += decoder.decode(value, { stream: true });
|
|
292
|
+
let lines = buffer.split("\n");
|
|
293
|
+
buffer = lines.pop();
|
|
294
|
+
for (let line of lines) {
|
|
295
|
+
line = line.trim();
|
|
296
|
+
if (!line)
|
|
297
|
+
continue;
|
|
298
|
+
if (line.startsWith("event:")) {
|
|
299
|
+
eventName = line.slice(6).trim();
|
|
300
|
+
} else if (line.startsWith("data:")) {
|
|
301
|
+
let data = line.slice(5).trim();
|
|
302
|
+
try {
|
|
303
|
+
data = JSON.parse(data);
|
|
304
|
+
} catch {
|
|
305
|
+
}
|
|
306
|
+
this.emit(eventName, data);
|
|
307
|
+
eventName = "message";
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
this.emit("end");
|
|
312
|
+
} catch (err) {
|
|
313
|
+
if (err.name !== "AbortError") {
|
|
314
|
+
this.emit("error", err);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
close() {
|
|
319
|
+
this.controller.abort();
|
|
320
|
+
this.emit("close");
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
// src/node-env.ts
|
|
203
325
|
function isWindows() {
|
|
204
326
|
return import_os.default.platform() === "win32";
|
|
205
327
|
}
|
package/lib/node-env.d.cts
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
|
|
4
|
+
declare class SSEResponse<Events extends string = 'message'> {
|
|
5
|
+
private res;
|
|
6
|
+
private isOpen;
|
|
7
|
+
constructor(res: Response);
|
|
8
|
+
flushHeaders(): void;
|
|
9
|
+
/** Send JSON to client, optionally with a custom event type */
|
|
10
|
+
emit(data: unknown, event?: Events): void;
|
|
11
|
+
/** Close the SSE connection */
|
|
12
|
+
close(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface SSEClientOptions {
|
|
16
|
+
url: string;
|
|
17
|
+
payload?: Record<string, any>;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
declare class SSEClient extends EventEmitter {
|
|
21
|
+
private url;
|
|
22
|
+
private payload;
|
|
23
|
+
private headers;
|
|
24
|
+
private controller;
|
|
25
|
+
constructor(options: SSEClientOptions);
|
|
26
|
+
connect(): Promise<void>;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
1
30
|
declare function isWindows(): boolean;
|
|
2
31
|
declare function chmodPlusX(filePath: string): void;
|
|
3
32
|
declare function checkIfDirExistsOrThrow(path: string): Promise<void>;
|
|
@@ -6,4 +35,4 @@ declare function throwIfDirNotEmpty(dir_path: string): Promise<void>;
|
|
|
6
35
|
declare function checkCommandExistsOrThrow(cmd: string): Promise<void>;
|
|
7
36
|
declare function checkIfFileExistsOrThrow(the_path: string): Promise<void>;
|
|
8
37
|
|
|
9
|
-
export { checkCommandExistsOrThrow, checkIfDirExistsOrThrow, checkIfFileExistsOrThrow, chmodPlusX, createTempDir, isWindows, throwIfDirNotEmpty };
|
|
38
|
+
export { SSEClient, SSEResponse, checkCommandExistsOrThrow, checkIfDirExistsOrThrow, checkIfFileExistsOrThrow, chmodPlusX, createTempDir, isWindows, throwIfDirNotEmpty };
|
package/lib/node-env.d.ts
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
|
|
4
|
+
declare class SSEResponse<Events extends string = 'message'> {
|
|
5
|
+
private res;
|
|
6
|
+
private isOpen;
|
|
7
|
+
constructor(res: Response);
|
|
8
|
+
flushHeaders(): void;
|
|
9
|
+
/** Send JSON to client, optionally with a custom event type */
|
|
10
|
+
emit(data: unknown, event?: Events): void;
|
|
11
|
+
/** Close the SSE connection */
|
|
12
|
+
close(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface SSEClientOptions {
|
|
16
|
+
url: string;
|
|
17
|
+
payload?: Record<string, any>;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
declare class SSEClient extends EventEmitter {
|
|
21
|
+
private url;
|
|
22
|
+
private payload;
|
|
23
|
+
private headers;
|
|
24
|
+
private controller;
|
|
25
|
+
constructor(options: SSEClientOptions);
|
|
26
|
+
connect(): Promise<void>;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
1
30
|
declare function isWindows(): boolean;
|
|
2
31
|
declare function chmodPlusX(filePath: string): void;
|
|
3
32
|
declare function checkIfDirExistsOrThrow(path: string): Promise<void>;
|
|
@@ -6,4 +35,4 @@ declare function throwIfDirNotEmpty(dir_path: string): Promise<void>;
|
|
|
6
35
|
declare function checkCommandExistsOrThrow(cmd: string): Promise<void>;
|
|
7
36
|
declare function checkIfFileExistsOrThrow(the_path: string): Promise<void>;
|
|
8
37
|
|
|
9
|
-
export { checkCommandExistsOrThrow, checkIfDirExistsOrThrow, checkIfFileExistsOrThrow, chmodPlusX, createTempDir, isWindows, throwIfDirNotEmpty };
|
|
38
|
+
export { SSEClient, SSEResponse, checkCommandExistsOrThrow, checkIfDirExistsOrThrow, checkIfFileExistsOrThrow, chmodPlusX, createTempDir, isWindows, throwIfDirNotEmpty };
|
package/lib/node-env.js
CHANGED
|
@@ -191,6 +191,126 @@ var import_command_exists = __toESM(require_command_exists2(), 1);
|
|
|
191
191
|
import * as fs from "fs-extra";
|
|
192
192
|
import os from "os";
|
|
193
193
|
import path from "path";
|
|
194
|
+
|
|
195
|
+
// src/SSEResponse.ts
|
|
196
|
+
var SSEResponse = class {
|
|
197
|
+
res;
|
|
198
|
+
isOpen = true;
|
|
199
|
+
constructor(res) {
|
|
200
|
+
this.res = res;
|
|
201
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
202
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
203
|
+
res.setHeader("Connection", "keep-alive");
|
|
204
|
+
}
|
|
205
|
+
flushHeaders() {
|
|
206
|
+
var _a;
|
|
207
|
+
(_a = this.res) == null ? void 0 : _a.flushHeaders();
|
|
208
|
+
}
|
|
209
|
+
/** Send JSON to client, optionally with a custom event type */
|
|
210
|
+
emit(data, event) {
|
|
211
|
+
if (!this.isOpen)
|
|
212
|
+
return;
|
|
213
|
+
try {
|
|
214
|
+
let payload = "";
|
|
215
|
+
if (event) {
|
|
216
|
+
payload += `event: ${event}
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
219
|
+
payload += `data: ${JSON.stringify(data)}
|
|
220
|
+
|
|
221
|
+
`;
|
|
222
|
+
if (this.res.writable) {
|
|
223
|
+
this.res.write(payload);
|
|
224
|
+
}
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.log("SSE Write error", e);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/** Close the SSE connection */
|
|
230
|
+
close() {
|
|
231
|
+
if (!this.isOpen) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
this.isOpen = false;
|
|
235
|
+
if (!this.res.writableEnded) {
|
|
236
|
+
this.res.end();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// src/SSEClient.ts
|
|
242
|
+
import { EventEmitter } from "events";
|
|
243
|
+
var SSEClient = class extends EventEmitter {
|
|
244
|
+
url;
|
|
245
|
+
payload;
|
|
246
|
+
headers;
|
|
247
|
+
controller;
|
|
248
|
+
constructor(options) {
|
|
249
|
+
super();
|
|
250
|
+
this.url = options.url;
|
|
251
|
+
this.payload = options.payload || {};
|
|
252
|
+
this.headers = {
|
|
253
|
+
"Content-Type": "application/json",
|
|
254
|
+
Accept: "*/*",
|
|
255
|
+
...options.headers
|
|
256
|
+
};
|
|
257
|
+
this.controller = new AbortController();
|
|
258
|
+
}
|
|
259
|
+
async connect() {
|
|
260
|
+
try {
|
|
261
|
+
const res = await fetch(this.url, {
|
|
262
|
+
method: "POST",
|
|
263
|
+
headers: this.headers,
|
|
264
|
+
body: JSON.stringify(this.payload),
|
|
265
|
+
signal: this.controller.signal
|
|
266
|
+
});
|
|
267
|
+
if (!res.ok) {
|
|
268
|
+
const data = await res.text();
|
|
269
|
+
this.emit("error", new Error(`HTTP error: ${res.status} ${data}`));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const reader = res.body.getReader();
|
|
273
|
+
const decoder = new TextDecoder("utf-8");
|
|
274
|
+
let buffer = "";
|
|
275
|
+
let eventName = "message";
|
|
276
|
+
while (true) {
|
|
277
|
+
const { value, done } = await reader.read();
|
|
278
|
+
if (done)
|
|
279
|
+
break;
|
|
280
|
+
buffer += decoder.decode(value, { stream: true });
|
|
281
|
+
let lines = buffer.split("\n");
|
|
282
|
+
buffer = lines.pop();
|
|
283
|
+
for (let line of lines) {
|
|
284
|
+
line = line.trim();
|
|
285
|
+
if (!line)
|
|
286
|
+
continue;
|
|
287
|
+
if (line.startsWith("event:")) {
|
|
288
|
+
eventName = line.slice(6).trim();
|
|
289
|
+
} else if (line.startsWith("data:")) {
|
|
290
|
+
let data = line.slice(5).trim();
|
|
291
|
+
try {
|
|
292
|
+
data = JSON.parse(data);
|
|
293
|
+
} catch {
|
|
294
|
+
}
|
|
295
|
+
this.emit(eventName, data);
|
|
296
|
+
eventName = "message";
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
this.emit("end");
|
|
301
|
+
} catch (err) {
|
|
302
|
+
if (err.name !== "AbortError") {
|
|
303
|
+
this.emit("error", err);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
close() {
|
|
308
|
+
this.controller.abort();
|
|
309
|
+
this.emit("close");
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// src/node-env.ts
|
|
194
314
|
function isWindows() {
|
|
195
315
|
return os.platform() === "win32";
|
|
196
316
|
}
|
|
@@ -256,6 +376,8 @@ function removeQuotes(str) {
|
|
|
256
376
|
}
|
|
257
377
|
}
|
|
258
378
|
export {
|
|
379
|
+
SSEClient,
|
|
380
|
+
SSEResponse,
|
|
259
381
|
checkCommandExistsOrThrow,
|
|
260
382
|
checkIfDirExistsOrThrow,
|
|
261
383
|
checkIfFileExistsOrThrow,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rg-dev/stdlib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"lib"
|
|
13
13
|
],
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
14
|
"typesVersions": {
|
|
18
15
|
"*": {
|
|
19
16
|
"lib/common-env": [
|
|
@@ -58,6 +55,7 @@
|
|
|
58
55
|
"@types/node": "^18.19.3",
|
|
59
56
|
"builtin-modules": "^3.3.0",
|
|
60
57
|
"command-exists": "^1.2.9",
|
|
58
|
+
"express": "^5.1.0",
|
|
61
59
|
"node-fetch": "^3.3.2",
|
|
62
60
|
"tsup": "^8.0.1",
|
|
63
61
|
"typescript": "^4.9.5"
|