rjweb-server
Version:
Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS
240 lines (239 loc) • 7.42 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var WsConnect_exports = {};
__export(WsConnect_exports, {
default: () => WSConnect
});
module.exports = __toCommonJS(WsConnect_exports);
var import_Base = __toESM(require("./Base"));
var import_parseContent = __toESM(require("../../functions/parseContent"));
class WSConnect extends import_Base.default {
/**
* Initializes a new Instance of a Web Context
* @since 7.0.0
*/
constructor(controller, localContext, ws) {
super(controller, localContext);
/**
* The Type of this Request
* @since 5.7.0
*/
this.type = "connect";
this.rawWs = ws;
}
/**
* Close the Socket and send a Code + Message to the Client (automatically Formatted)
*
* This will instantly close the socket connection with a status code and
* message of choice, after calling and successfully closing the `.onClose()`
* callback will be called to finish the task.
* @example
* ```
* ctr.close(401, {
* message: 'this is json!'
* })
*
* // or
*
* ctr.close(401, 'this is text!')
* ```
* @since 5.4.0
*/
close(code, message) {
this.ctx.continueSend = false;
{
(async () => {
let result;
try {
result = await (0, import_parseContent.default)(message, false, this.ctg.logger);
} catch (err) {
this.ctx.handleError(err);
return true;
}
try {
this.rawWs.cork(() => this.rawWs.end(code, result.content));
} catch {
}
return true;
})();
}
return this;
}
/**
* Print a Message to the Client (automatically Formatted)
*
* This will send a new websocket message to the client as soon
* as the event loop allows it to execute the async task of parsing
* the message content.
* @example
* ```
* ctr.print({
* message: 'this is json!'
* })
*
* // or
*
* ctr.print('this is text!')
* ```
* @since 5.4.0
*/
print(message, options = {}) {
const prettify = options?.prettify ?? false;
{
(async () => {
let result;
try {
result = await (0, import_parseContent.default)(message, prettify, this.ctg.logger);
} catch (err) {
this.ctx.handleError(err);
return true;
}
try {
this.rawWs.cork(() => this.rawWs.send(result.content));
this.ctg.webSockets.messages.outgoing.increase();
this.ctg.data.outgoing.increase(result.content.byteLength);
} catch {
}
return true;
})();
}
return this;
}
/**
* Print a references value every time it changes
*
* This will print when the provided reference changes state similarly
* to the `.printStream()` method which listen to a streams `data` event.
* @example
* ```
* const ref = new Reference('Hello')
*
* ctr.printRef(ref)
*
* ref.set('Ok')
* ```
* @since 7.2.0
*/
printRef(reference, options = {}) {
const prettify = options?.prettify ?? false;
const ref = reference["onChange"](async (value) => {
let data;
try {
data = (await (0, import_parseContent.default)(value, prettify, this.ctg.logger)).content;
} catch (err) {
return this.ctx.handleError(err);
}
try {
this.rawWs.send(data);
this.ctg.webSockets.messages.outgoing.increase();
this.ctg.data.outgoing.increase(data.byteLength);
} catch {
}
});
this.ctx.refListeners.push({
ref: reference,
refListener: ref
});
return this;
}
/**
* Remove a reference subscription
*
* This will remove the listener of a reference from the
* current socket. May be slow when having many references
* attached to the socket.
* @example
* ```
* const ref = new Reference('Hello')
*
* ctr.printRef(ref)
*
* ref.set('Ok')
*
* ctr.removeRef(ref)
* ```
* @since 7.2.0
*/
removeRef(reference) {
const index = this.ctx.refListeners.findIndex(({ ref }) => Object.is(ref, reference));
if (index >= 0) {
reference["removeOnChange"](this.ctx.refListeners[index].refListener);
this.ctx.refListeners.splice(index, 1);
}
return this;
}
/**
* Print the `data` event of a Stream to the Client
*
* This will print the `data` event of a stream to the client
* in real time. This shouldnt be used over `.printRef()` but is
* useful when working with something like a `fs.ReadStream` for
* some reason.
* @example
* ```
* const fileStream = fs.createReadStream('./profile.png')
* ctr.printStream(fileStream)
* ```
* @since 5.4.0
*/
printStream(stream, options = {}) {
const prettify = options?.prettify ?? false;
const destroyAbort = options?.destroyAbort ?? true;
const destroyStream = () => {
stream.destroy();
};
const dataListener = async (data) => {
try {
data = (await (0, import_parseContent.default)(data, prettify, this.ctg.logger)).content;
} catch (err) {
return this.ctx.handleError(err);
}
try {
this.rawWs.send(data);
this.ctg.webSockets.messages.outgoing.increase();
this.ctg.data.outgoing.increase(data.byteLength);
} catch {
}
}, closeListener = () => {
if (destroyAbort)
this.ctx.events.unlist("requestAborted", destroyStream);
}, errorListener = (error) => {
this.ctx.handleError(error);
stream.removeListener("data", dataListener).removeListener("close", closeListener).removeListener("error", errorListener);
};
if (destroyAbort)
this.ctx.events.listen("requestAborted", destroyStream);
stream.on("data", dataListener).once("close", closeListener).once("error", errorListener);
this.ctx.events.listen(
"requestAborted",
() => stream.removeListener("data", dataListener).removeListener("close", closeListener).removeListener("error", errorListener)
);
return this;
}
}