New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@ayonli/jsext

Package Overview
Dependencies
Maintainers
1
Versions
161
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ayonli/jsext - npm Package Compare versions

Comparing version 0.3.3 to 0.3.4

176

index.js

@@ -210,4 +210,180 @@ "use strict";

},
read(source, eventMap = undefined) {
var _a;
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
}
const iterable = {
ended: false,
error: null,
queue: [],
consumers: [],
next() {
return new Promise((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
}
else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0, done: true });
}
else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift(), done: false });
}
else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
const handleMessage = (data) => {
var _a;
if (iterable.consumers.length > 0) {
(_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });
}
else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev) => {
let err;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
}
else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup;
if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&
(eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== "message" &&
typeof source["addEventListener"] === "function") { // for EventSource listening on custom events
const es = source;
const eventName = eventMap.event;
const msgListener = (ev) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
}
else {
msgDesc.set.call(source, (ev) => {
handleMessage(ev.data);
});
cleanup = () => {
var _a;
(_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
};
}
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);
if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket
closeDesc.set.call(source, () => {
var _a, _b;
handleClose();
(_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
(_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
});
}
else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source;
const _close = es.close;
es.close = function close() {
var _a;
_close.call(es);
handleClose();
es.close = _close;
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
};
}
}
else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source;
ws.onmessage = (ev) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
}
else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source;
const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || "message";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
const msgListener = (ev) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
}
else if (typeof source["on"] === "function") { // EventEmitter
const target = source;
const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || "data";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
}
else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]: () => iterable
};
}
};
exports.default = jsext;
//# sourceMappingURL=index.js.map

@@ -63,2 +63,19 @@ import { isAsyncGenerator, isGenerator } from "check-iterable";

): Fn;
/**
* Wraps a source as an AsyncIterable object that can be used in the `for...await...` loop
* for reading streaming data.
*/
read<I extends AsyncIterable<any>>(iterable: I): I;
read(es: EventSource, options?: { event?: string; }): AsyncIterable<string>;
read<T extends Uint8Array | string>(ws: WebSocket): AsyncIterable<T>;
read<T>(target: EventTarget, eventMap?: {
message?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
read<T>(target: NodeJS.EventEmitter, eventMap?: {
data?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
}

@@ -283,4 +300,189 @@

},
read<T>(source: any, eventMap: {
event?: string; // for EventSource custom event
message?: string;
data?: string;
error?: string;
close?: string;
} | undefined = undefined): AsyncIterable<T> {
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
}
const iterable = {
ended: false,
error: null as Error | null,
queue: [] as T[],
consumers: [] as {
resolve: (data: IteratorResult<T>) => void;
reject: (err: any) => void;
}[],
next() {
return new Promise<IteratorResult<T>>((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
} else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0 as T, done: true });
} else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift() as T, done: false });
} else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
const handleMessage = (data: T) => {
if (iterable.consumers.length > 0) {
iterable.consumers.shift()?.resolve({ value: data, done: false });
} else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer: typeof iterable["consumers"][0] | undefined;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err: Error) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev: Event) => {
let err: Error;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
} else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if (msgDesc?.set && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup: () => void;
if (eventMap?.event &&
eventMap?.event !== "message" &&
typeof source["addEventListener"] === "function"
) { // for EventSource listening on custom events
const es = source as EventSource;
const eventName = eventMap.event;
const msgListener = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
} else {
msgDesc.set.call(source, (ev: MessageEvent<T>) => {
handleMessage(ev.data);
});
cleanup = () => {
msgDesc.set?.call(source, null);
};
}
errDesc?.set?.call(source, handleBrowserErrorEvent);
if (closeDesc?.set) { // WebSocket
closeDesc.set.call(source, () => {
handleClose();
closeDesc.set?.call(source, null);
errDesc?.set?.call(source, null);
cleanup?.();
});
} else if (!closeDesc?.set && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source as EventSource;
const _close = es.close;
es.close = function close() {
_close.call(es);
handleClose();
es.close = _close;
errDesc?.set?.call(source, null);
cleanup?.();
};
}
} else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source as WebSocket;
ws.onmessage = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
} else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source as EventTarget;
const msgEvent = eventMap?.message || "message";
const errEvent = eventMap?.error || "error";
const closeEvent = eventMap?.close || "close";
const msgListener = (ev: Event) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
} else if (typeof source["on"] === "function") { // EventEmitter
const target = source as NodeJS.EventEmitter;
const dataEvent = eventMap?.data || "data";
const errEvent = eventMap?.error || "error";
const endEvent = eventMap?.close || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
} else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]: () => iterable
};
}
};
export default jsext;

10

package.json
{
"name": "@ayonli/jsext",
"version": "0.3.3",
"version": "0.3.4",
"description": "Additional functions for JavaScript builtin types that are frequently used in practice.",

@@ -37,2 +37,3 @@ "main": "index.js",

"try",
"defer",
"sleep",

@@ -52,7 +53,12 @@ "promise"

"devDependencies": {
"@ayonli/sse": "^0.4.0",
"@types/eventsource": "^1.1.11",
"@types/mocha": "^10.0.1",
"@types/node": "^20.6.0",
"@types/websocket": "^1.0.6",
"eventsource": "1.1",
"mocha": "^10.2.0",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
"typescript": "^4.9.5",
"websocket": "^1.0.34"
},

@@ -59,0 +65,0 @@ "engines": {

@@ -26,5 +26,13 @@ # JsExt

- `try<E = Error, R = any>(job: Promise<R>): Promise<[E, R]>`
- `func<T, R = any, A extends any[] = any[]>(fn: (this: T, defer: (cb: () => void) => void, ...args: A) => R): (this: T, ...args: A) => R`
- `wrap<T, Fn extends (this: T, ...args: any[]) => any>(fn: Fn, wrapper: (this: T, fn: Fn, ...args: Parameters<Fn>) => ReturnType<Fn>): Fn`
- `read<I extends AsyncIterable<any>>(iterable: I): I`
- `read(es: EventSource, options?: { event?: string; }): AsyncIterable<string>`
- `read<T extends Uint8Array | string>(ws: WebSocket): AsyncIterable<T>`
- `read<T>(target: EventTarget, eventMap?: { message?: string; error?: string; close?: string; }): AsyncIterable<T>`
- `read<T>(target: NodeJS.EventEmitter, eventMap?: { data?: string; error?: string; close?: string; }): AsyncIterable<T>`
## Sub-packages

@@ -31,0 +39,0 @@

index.js.map

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc