This is the documentation of SvCoreLib (also referred to as SCL).
SvCoreLib, as the name suggests, is the core library used by most Node.js projects of the Sv443 Network.
This library supports CommonJS and has builtin Typescript declarations.
To understand how this documentation works, please first read this section.
If you find any bugs or want to suggest a new feature, please open a new issue on GitHub.
You can join the Sv443 Network Discord server if you need help or just want to chat:
>> To get started, please go to the installation section. <<
Otherwise, see the table of contents just below.
- Installation
- Usage
- How this documentation works
- In-IDE Documentation
- Functions
- Files
- downloadFile() - downloads a file from a provided URL
- exists() - reimplementation of the deprecated
fs.exists()
- existsSync() - synchronous counterpart to
exists()
- logger() - logs an error message to the console and/or a log file
- readdirRecursive() - async function that recursively searches through a directory
- readdirRecursiveSync() - synchronous counterpart to
readdirRecursive()
- ensureDirs() - ensures a set of directories exist and creates them if not
- ensureDirsSync() - synchronous counterpart to
ensureDirs()
- UUID
- alphanumerical() - generates an alphanumerical UUID
- binary() - generates a binary UUID
- custom() - generates a custom UUID
- decimal() - generates a decimal UUID
- hexadecimal() - generates a hexadecimal UUID
- HTTP
- getClientEncoding() - gets the most efficient encoding from a client request
- pipeFile() - sends a file to a client
- pipeString() - sends a string to a client
- ping() - pings a specified URL
- Seeded RNG
- randomSeed() - generates a random seed
- generateNumbers() - generates numbers based on a seed
- validateSeed() - validates a seed
- SQL
- sendQuery() - sends a SQL query
- System
- usedHeap() - how much of the heap space is used
- inDebugger() - checks if the process is running in a debugger
- noShutdown() - prevents process shutdown
- yesShutdown() - re-enables process shutdown
- softShutdown() - executes a synchronous function before the process exits
- setWindowTitle() - sets the terminal window's title (Windows & *nix)
- pause() - pauses code execution until the user presses a key
- Other
- allEqual() - checks if all values in an array are equal
- allOfType() - checks if all values in an array are of a certain type
- allInstanceOf() - checks if all values in an array are an instance of a certain class
- byteLength() - returns the length of a string in bytes
- error() - sends an error message and/or exits the process
- insertValues() - inserts values into a preformatted string
- isArrayEmpty() - checks if or how many items of an array are empty
- isEmpty() - checks if a value is considered empty
- isClass() - checks if a value is a reference to a class
- mapRange() - maps a number from one numerical range to another
- randomItem() - returns a random item from an array
- randomItemIndex() - returns a random item from an array, along with its index
- takeRandomItem() - deletes a random item from an array and returns it
- randomizeArray() - randomizes the items in an array
- randRange() - returns a random number in the provided range
- clamp() - makes sure a number is always in between a min and max limit
- readableArray() - converts an array to a better readable string
- removeDuplicates() - removes duplicate items in an array
- halves() - returns both halves of an array
- replaceAt() - replaces a character in a string with another string
- reserialize() - loses internal reference of a JSON-compatible object
- splitIntoParts() - splits an array into n parts
- splitIntoPartsOfLength() - splits an array into n parts with a max length
- parseDuration() - parses a duration in milliseconds to days, hours, mins, secs and ms
- formatDuration() - turns a millisecond duration into a string with a custom format
- unused() - indicates to a linter that one or more variables are unused
- Files
- Classes
- FolderDaemon - monitors a folder's contents for changes
- MenuPrompt - a prompt which users can select an option from
- ProgressBar - shows a progress bar in the console
- SelectionMenu - a menu that can be scrolled through
- StatePromise - wrapper around the Promise API that provides a way to check its state
- Errors
- SCLError - base class of all SCL error classes
- InvalidPathError - an invalid path was provided
- NotAFolderError - the provided path is not a folder
- PatternInvalidError - GLOB pattern is invalid
- NoStdinError - terminal doesn't have a stdin channel
- InvalidMimeTypeError - MIME type is not valid
- SqlConnectionNotEstablishedError - SQL connection is invalid
- Objects
- Legal Information
To install SvCoreLib (SCL), use the following command in a terminal inside your Node.js project:
npm i svcorelib
Troubleshooting: Make sure your workspace contains a package.json
file. If not, use npm init
to initialize your workspace with npm.
This explains how you can use SCL in your project.
- If your project runs on "vanilla" Node.js (or CommonJS), use the following at the top of the file you want to include SCL:
const scl = require("svcorelib");
- If your project runs on TypeScript, replace the above with this:
import * as scl from "svcorelib";
The variable scl
now contains all of SCL's functions, namespaces, classes and objects.
If you only want to import a select number of features and don't like always having to use a variable like scl
, you can also use the following syntaxes.
- "Vanilla" Node.js / CommonJS:
const { function1, namespace1, Class1 } = require("svcorelib");
- TypeScript:
import { function1, namespace1, Class1 } from "svcorelib";
Note: You need to replace the placeholder names above with the functions / namespaces / classes / objects you want to import.
- The first code block of each feature tells you about the parameters of the function / method and what type of value it returns.
- Each parameter name is followed by a colon and then a type name (for example
parameter: string
). - If the colon is prefixed by a question mark, this parameter is optional (for example:
parameter?: string
). - Everything after the colon or question mark is not needed for actually interfacing with the library. It is merely there to tell you of which type a parameter should be.
- If there are overloads to the method or function in question, they will be listed on a separate line each (
randRange()
for example).
- Each parameter name is followed by a colon and then a type name (for example
- Most features have a code example which is collapsed by default and can be expanded by clicking on it.
- Note that the code examples in this documentation are written in CommonJS.
- If you use ES or TypeScript, see import instructions in the usage section and modify the other code accordingly.
- All code examples don't require installing any third party packages (excluding SCL's dependencies which should get auto-installed).
- The example GIF included in some features uses the exact code that is included in that same feature under "example code".
- Custom objects (aka interfaces) are declared at the bottom of the class they are part of or at the bottom of the same section if they belong to a normal function.
- Class constructors start with the header
Constructor
and don't have a return type (since they return an instance of the class they belong to).- This instance, created with the
new
keyword, should then be used to call the methods that are part of that same class. - Do not use methods on the class directly unless the documentation explicitly states that they are static methods!
- This instance, created with the
SCL uses a TypeScript type declaration file (.d.ts
) in order to provide documentation directly in your IDE.
- Each piece of documentation will have a description. It is usually delimited from other sections by this emoji: 🔹, unless:
- you are looking at a namespace, for example
scl.files
, its description will instead be marked with this emoji: 🔸 - it is an event that uses the native module "events" with the
.on("event", (data) => {})
syntax, which is marked by this emoji: 📡
- you are looking at a namespace, for example
- Some of the functions / methods have special quirks to look out for or will be deprecated. This warning section is delimited from other sections with this emoji: ❗
- Deprecated features should be unlisted in your IDE but if not or you explicitly entered their name, they are indicated with a
@deprecated
tag and they will contain this emoji: ❌
Their descriptions should also tell you if there are alternatives. - You will always encounter a
@since
tag, which indicates with which version the feature was introduced. - The
@version
tag will tell you about (breaking) changes that have been made in a certain version. - If a function / method can throw an error, the
@throws
tag will tell you when this might happen and of which class the Error instance might be. - Private class methods should be unlisted but if not, they will start with an underscore, will be tagged with
@private
and their description will be delimited from other sections with this emoji: ❌
Private methods shouldn't be used, or else something might break.
This section tells you all about the static functions SCL offers.
You have to call these without creating a class instance (without using the new
keyword).
This namespace, accessed with scl.files
, contains a few filesystem-related functions.
This function logs a message to a file
scl.files.logger(path: string, content?: string, options?: LoggerOptions): void
Example Code - click to show
const scl = require("svcorelib"); let opts = { timestamp: true, append_bottom: true }; scl.files.logger("./error.log", "There was an error while ...", opts);
{ append_bottom: boolean, // set to false to overwrite the entire file instead of appending to the bottom timestamp: boolean // set to true to add a timestamp to the logged content }
Used to recursively search through a directory, returning an array of all files and folders contained within.
The returned paths are always absolute, meaning they start onC:\
(Windows) or/
(Unix).
If you want relative paths instead, use the functionrelative()
of Node's builtinpath
module.This is an asynchronous function. You can either pass a callback function as the second parameter or use the Promise API (
.then()
).
This function is less resource-heavy than the synchronous files.readdirRecursiveSync() and it doesn't block the execution of the rest of your code so it is recommended that you try to use this function over the synchronous one.scl.files.readdirRecursive(folder: string, callback?: function): Promise<string[]>
Example Code - click to show
const scl = require("svcorelib"); scl.files.readdirRecursive("./").then(result => { console.log(result); /* [ "C:/Users/Foo/Desktop/SCL/index.js", "C:/Users/Foo/Desktop/SCL/package.json", "C:/Users/Foo/Desktop/SCL/bar/test.txt" ] */ }).catch(err => console.error(err));
Basically the same thing as files.readdirRecursive(), but this function blocks code execution until it's finished, making it synchronous.
❗ This function uses blocking operations, contrary to the asynchronous files.readdirRecursive() so it is recommended that you try to use the async function over this synchronous one.
scl.files.readdirRecursiveSync(folder: string): string[]
Example Code - click to show
const scl = require("svcorelib"); let paths = scl.files.readdirRecursive("./"); console.log(paths); /* [ "C:/Users/Foo/Desktop/SCL/index.js", "C:/Users/Foo/Desktop/SCL/package.json", "C:/Users/Foo/Desktop/SCL/bar/test.txt" ] */
Downloads a file from the specified
url
and puts it in the folder at the specifieddestPath
.
The parameteroptions
needs to be an object of type DownloadOptions (scroll down for definition).
The function will return a Promise that resolves to a void value or rejects to an error message string.scl.files.downloadFile(url: string, destPath?: string, options?: DownloadOptions): Promise<string | void>
Example Code - click to show
const scl = require("svcorelib"); let opts = { fileName: "page.html", progressCallback: progress => { console.log(`Download progress: ${progress.currentB} / ${progress.totalB} bytes`); }, finishedCallback: err => { if(err) console.error(`Error while downloading: ${err}`); else console.log(`File was downloaded successfully`); } }; scl.files.downloadFile("https://example.org/", "./", opts);
{ fileName: string; // the name that the downloaded file should be saved as, including the file extension. Defaults to "download.txt" if left undefined. progressCallback: function; // a callback function that gets called every 50 milliseconds that gets passed an object containing info on the download progress (scroll down for more info) - sometimes the download progress can't be gotten so this callback won't contain the total size or will not be called a final time on finish. This behavior is normal. finishedCallback: function; // a callback function that gets called when the download finished and gets passed a parameter that is `null` if no error was encountered, or contains a string if an error was encountered }{ currentB: number; // current progress in bytes currentKB: number; // current progress in kilobytes currentMB: number; // current progress in megabytes totalB: number; // total file size in bytes totalKB: number; // total file size in kilobytes totalMB: number; // total file size in megabytes }
This function checks if a file exists at the given path.
(Reimplementation offs.exists()
based onfs.access()
)The parameter
path
specifies which file to check for its existence - This path gets passed throughpath.resolve()
A Promise is returned that always resolves to a boolean.
This function throws a
TypeError
if thepath
argument is not a string or couldn't be resolved to a valid path.scl.files.exists(path: string): Promise<boolean>;
Example Code - click to show
const scl = require("svcorelib"); async function checkExists() { let foo = await scl.files.exists("./index.js"); let bar = await scl.files.exists("./path/that/doesn't/exist.txt"); console.log(foo); // true console.log(bar); // false } checkExists();
Basically the same thing as files.exists(), but this function blocks code execution until it's finished, making it synchronous.
❗ This function uses blocking operations, contrary to the asynchronous files.exists() so it is recommended that you try to use the async function over this synchronous one.
scl.files.exists(path: string): boolean
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.files.existsSync("./index.js"); let bar = scl.files.existsSync("./path/that/doesn't/exist.txt"); console.log(foo); // true console.log(bar); // false
This function ensures a set of directories exists and creates them if not.
A path of the
directories
parameter can also contain sub-directories (see example).
In this case the full path will also be created if it doesn't exist.scl.files.ensureDirs(directories: string[]): Promise<void>;
Example Code - click to show
const { files } = require("svcorelib"); const dirs = [ "data/foo", "data/bar/baz" ]; async function init() { await files.ensureDirs(dirs); } init();
This function ensures a set of directories exists and creates them if not.
A path of the
directories
parameter can also contain sub-directories (see example).
In this case the full path will also be created if it doesn't exist.❗ This function blocks the main thread, contrary to the asynchronous files.ensureDirs() so it is recommended that you try to use the async function over this synchronous one.
scl.files.ensureDirsSync(directories: string[]): void;
Example Code - click to show
const { files } = require("svcorelib"); const dirs = [ "data/foo", "data/bar/baz" ]; function init() { files.ensureDirsSync(dirs); } init();
This namespace, accessed with scl.uuid
, offers a few functions to generate Universally Unique Identifiers (UUIDs).
One thing these functions all have in common is the uuidFormat
parameter.
This parameter is a string that should contain the characters x
and y
. These letters will be replaced by random letters or numbers, while any other characters are left untouched.
Prefixing an x
or y
with a caret (^
) will prevent it from being replaced with a random letter or number.
Example: a format of x^x-y^y
might produce a result similar to this: 1x-cy
This function generates an alphanumerical (
A-Z0-9
ora-z0-9
) UUID.
The parameteruuidFormat
is explained here.
If the parameterupperCase
is set totrue
, the resulting UUID will have its alphabetical letters in uppercase.scl.uuid.alphanumerical(uuidFormat: string, upperCase?: boolean): string
Example Code - click to show
const scl = require("svcorelib"); let uuid = scl.uuid.alphanumerical("xxxx-yyyy", true); console.log(uuid); // "U45A-AS6X"
This function generates a binary (
0-1
ortrue-false
) UUID.
The parameteruuidFormat
is explained here.
If the parameterasBooleanArray
is set totrue
, the resulting UUID will be an array of booleans. Any characters of theuuidFormat
that aren'tx
ory
will then be ignored.scl.uuid.binary(uuidFormat: string, asBooleanArray?: boolean): string | boolean[]
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.uuid.binary("xxxx-yyyy"); let bar = scl.uuid.binary("xxxx", true); console.log(foo); // "1110-1010" console.log(bar); // [ true, true, false, true ]
This function generates a custom UUID.
The parameter
uuidFormat
is explained here.The parameter
possibleValues
needs to be a string array of characters that should be used to generate the UUID.scl.uuid.custom(uuidFormat: string, possibleValues: string[]): string
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.uuid.custom("xxxx-yyyy", "abcd#+_!".split("")); let bar = scl.uuid.custom("xxxx-yyyy", ["1", "2"]); // binary system using 1s and 2s maybe? 👀 console.log(foo); // "b+_c-d#ad" console.log(bar); // "2212-1211"
This function generates a decimal (
0-9
) UUID.The parameter
uuidFormat
is explained here.scl.uuid.decimal(uuidFormat: string): string
Example Code - click to show
const scl = require("svcorelib"); let uuid = scl.uuid.decimal("xxxx-yyyy"); console.log(uuid); // "5563-0291"
This function generates a hexadecimal (
a-f0-9
orA-F0-9
) UUID.The parameter
uuidFormat
is explained here.
If the parameterupperCase
is set totrue
, the resulting UUID will have its alphabetical letters in uppercase.scl.uuid.hexadecimal(uuidFormat: string, upperCase?: boolean): string
Example Code - click to show
const scl = require("svcorelib"); let uuid = scl.uuid.hexadecimal("xxxx-yyyy", true); console.log(uuid); // "F6B6-EFA3"
This namespace, accessed with scl.http
, offers functions that make using Node's builtin http
and https
modules and third-party packages based on them easier to use.
This function parses the
Accept-Encoding
header of a clien't request and returns the most efficient and modern encoding methods the client supports.
If no header was provided or the client doesn't support any encodings,"identity"
is returned, meaning the client wants the original, non-encoded data.scl.http.getClientEncoding(req: http.IncomingMessage): stringCurrently supported encoding methods (sorted by priority, highest priority first) are:
Encoding Name Priority br
Brotli 4 gzip
Gzip / Lempel-Ziv / LZ77 3 deflate
Deflate 2 compress
Lempel-Ziv-Welch / LZW 1 identity
No Encoding / Raw Data 0
Example Code - click to show
const http = require("http"); const scl = require("svcorelib"); http.createServer((req, res) => { if(req.method == "GET") { console.log(`Client accepts encodings: ${req.headers["accept-encoding"]}`); // "Client accepts encodings: gzip, deflate" // let SCL determine the encoding that's highest on the priority list and also supported by the client (present in the "Accept-Encoding" header) const clientEncoding = scl.http.getClientEncoding(req); res.writeHead(200, { "Content-Type": "text/plain; utf-8" }); res.end(`Selected encoding: ${clientEncoding}`); // "Selected encoding: gzip" } }).listen(80, undefined, err => { if(err) console.error(`Error while setting up HTTP server: ${err}`); else console.log(`HTTP server is listening at http://127.0.0.1/`); });
This function responds to a client's request by efficiently sending them the contents of a file.
Because it streams / pipes the file to the client directly from your drive and it doesn't need to be loaded entirely into RAM first, it is less resource-heavy.The parameter
res
contains the server's response to the client's request.
Put the path to the file you want to send to the client in the parameterfilePath
.
The parametermimeType
needs to be passed a valid MIME (Multipurpose Internet Mail Extensions) type. If left empty, this will default totext/plain
.
ThestatusCode
parameter needs to be passed a HTTP status code number. If left empty, this will default to200
.The function will return
null
if everything went according to plan or will return a string containing an error message if not.scl.http.pipeFile(res: http.ServerResponse, filePath: string, mimeType?: string, statusCode?: number): null | string
Example Code - click to show
const http = require("http"); const scl = require("svcorelib"); const path = require("path"); http.createServer((req, res) => { if(req.method == "GET") { // requires a file "index.html" to exist at the project's root dir (where package.json sits) // using resolve() of Node's builtin "path" module will ensure that the path is valid and can be understood by SCL scl.http.pipeFile(res, path.resolve("./index.html"), "text/html", 200); } }).listen(80, undefined, err => { if(err) console.error(`Error while setting up HTTP server: ${err}`); else console.log(`HTTP server listening at 127.0.0.1:80`); });
This function responds to a client's request by efficiently sending them a string.
Because it streams / pipes the string to the client and it doesn't need to be stored in a variable, there's not that big of a toll on your RAM.The parameter
res
contains the server's response to the client's request.
Put the string you want to send to the client in the parametertext
.
The parametermimeType
needs to be passed a valid MIME (Multipurpose Internet Mail Extensions) type. If left empty, this will default totext/plain
.
ThestatusCode
parameter needs to be passed a HTTP status code number. If left empty, this will default to200
The function will return
null
if everything went according to plan or will return a string containing an error message if not.scl.http.pipeString(res: http.ServerResponse, text: string, mimeType?: string, statusCode?: number): null | string
Example Code - click to show
const http = require("http"); const scl = require("svcorelib"); http.createServer((req, res) => { if(req.method == "GET") { scl.http.pipeString(res, `Hello, World!\nThis is my website running on Node.js ${process.version}`, "text/plain", 200); } }).listen(80, undefined, err => { if(err) console.error(`Error while setting up HTTP server: ${err}`); else console.log(`HTTP server listening at 127.0.0.1:80`); });
Pings the specified URL and returns its status code, status message, response time and
Content-Type
header.The param
url
needs to be passed a valid URL.
Usetimeout
to specify a maximum timeout in milliseconds after which the ping should be cancelled. Defaults to 5000.
The function returns a promise that resolves with an object containing all the values you need (scroll down for more info) or a string containing an error message.scl.http.ping(url: string, timeout?: number): Promise<PingReturnValues>
Example Code - click to show
const scl = require("svcorelib"); scl.http.ping("https://example.org/", 5000) .then(res => { console.log(`Status ${res.statusCode} (${res.statusMessage}) - Ping: ${res.responseTime}ms`); // Status 200 (OK) - Ping: 526ms }) .catch(err => { console.error(`Error while pinging URL: ${err}`); });
{ statusCode: number; // The ping's returned status code (eg. 200 or 404) statusMessage: string; // The status message of the ping - Could be something like "OK" for status 200 or "Not Found" for status 404 responseTime: number; // The response time in milliseconds as an integer contentType: string; // The `Content-Type` header - this will contain the MIME type and the content encoding, for example: "text/html; charset=UTF-8" }
This namespace, accessed with scl.seededRNG
, offers a few functions to generate numbers based on a seed.
This means that using the same seed, you will be able to generate the same numbers over and over again, just like Minecraft's world seeds for example.
Seeds in SCL need to be of a certain format. Some other functions in this section will help you accomplish just that.
This function generates a random seed to be used in generateNumbers()
Since seeds in SCL need to be of a certain format (a number or string containing only numbers that can't start with a0
), I recommend you use this function to randomize the seeds.The parameter
digitCount
specifies how many digits the resulting seed should have (default is 10).scl.seededRNG.randomSeed(digitCount?: number): number
Example Code - click to show
const scl = require("svcorelib"); let seed = scl.seededRNG.randomSeed(5); console.log(seed); // 35091
This function generates the actual pseudo-random numbers based on a passed seed.
Seeds in SCL need to be of a certain format (a number or string containing only numbers that can't start with a
0
).
That's why I recommend generating them with randomSeed() or validating them with validateSeed().With the parameter
count
you can specify how many pseudo-random numbers you want to receive. Defaults to 16 if left undefined.
Theseed
parameter is where you should provide your seed. If no seed is provided, a random seed will be generated using randomSeed(). You will be able to view the generated seed in the returned object.scl.seededRNG.generateNumbers(count?: number, seed?: number | string): SeededRandomNumbers
Example Code - click to show
const scl = require("svcorelib"); let seed = scl.seededRNG.randomSeed(5); // 58157 let foo = scl.seededRNG.generateNumbers(8, seed); let bar = scl.seededRNG.generateNumbers(8, seed); console.log(foo.integer === bar.integer); // true - the numbers are identical since the seed is identical console.log(foo); // { ... } - (see below for how this object is structured)
{ numbers: number[], // the generated numbers as an array of numbers stringified: string, // the generated numbers as a string integer: number, // the generated numbers as a single integer / number seed: number // the seed that was used to generate the numbers }
This function validates a seed to be used in generateNumbers()
It is especially useful to validate user-entered seeds.Seeds in SCL need to be of a certain format (a number or string containing only numbers that can't start with a
0
).
This function does exactly those checks to ensure the seed is valid.The
seed
parameter is where you should provide your seed. It can be a string or a number.scl.seededRNG.validateSeed(seed: number | string): boolean
Example Code - click to show
const scl = require("svcorelib"); let foo = jsl.seededRNG.validateSeed(35091); let bar = jsl.seededRNG.validateSeed("35091"); let baz = jsl.seededRNG.validateSeed("hello I am a string"); console.log(foo); // true console.log(bar); // true console.log(baz); // false
This namespace, accessed with scl.sql
, offers functions to interface with SQL databases.
These functions depend on the package mysql
.
Sends a formatted (SQLI-protected) query.
The param
connection
needs to be passed an SQL connection instantiated withmysql.createConnection()
The paramquery
needs to be passed the SQL query with question marks where the inserted values should be.
The paramoptions
needs to be passed an object of options of this query. Here are the possible properties - leave undefined to choose the default options.
The rest parameterinsertValues
needs to be passed the values to be inserted into the question marks - use the primitive typenull
for an empty value.The returned promise resolves to an object containing the response from the database or rejects to an error string.
scl.sql.sendQuery(connection: mysql.Connection, query: string, options?: mysql.QueryOptions, ...insertValues: null | string | number): Promise<object>
Example Code - click to show
const { sql } = require("svcorelib"); const mysql = require("mysql"); const options = { timeout: 2000 // after how many milliseconds the queries should time out if they didn't get a response }; const database = "database_name"; // set the database name here // create SQL connection let sqlConnection = mysql.createConnection({ host: "127.0.0.1", // IP address of the SQL server (127.0.0.1 means the server runs locally) user: process.env.DB_USER, // requires setting these values in the environment variables - I recommend using the "dotenv" package for this password: process.env.DB_PASSWORD, // see above ^ insecureAuth: true // this is required on newer version of MySQL (like 8.0) since they require some weird ass more secure auth }); // try to connect with the above settings sqlConnection.connect(err => { if(err) return console.error(`Error: ${err}`); // send the actual query sql.sendQuery(sqlConnection, "SELECT * FROM ??.tablename LIMIT 10", options, database).then(res => { console.log(JSON.stringify(res, undefined, 4)); }).catch(err => { console.error(`Error: ${err}`); }); });
This namespace, accessed with scl.system
, offers functions that refer to the system the process is executed on or the process itself.
Returns the percentage of heap space that is used by the process as a floating point number between 0 and 100.
scl.system.usedHeap(): number
Example Code - click to show
const { system } = require("svcorelib"); console.log(`Used heap space: ${system.usedHeap().toFixed(2)}%`);
Checks if the process is currently running in a debugger.
This can be useful because some features like child processes and reading from stdin do not work in most debuggers.
Should support all major Node.js debuggers, but this is not guaranteed.
Returnstrue
if the current process runs in a debugger - else returnsfalse
If
checkArg
is provided, the function searches for a matching command line argument and returnstrue
if it was found.
This enables you to explicitly set the debugger state, for example if your debugger isn't properly detected by this function.scl.system.inDebugger(checkArg?: string): boolean
Basic example code - click to show
const { system, MenuPrompt } = require("svcorelib"); if(!system.inDebugger()) { // SCL's MenuPrompt doesn't work in some debuggers since it needs to read from process.stdin const mp = new MenuPrompt(); // ... }
Example with custom CLI argument - click to show
const { system } = require("svcorelib"); console.log(process.argv); // [ '.../node.exe', '.../this_file.js', '--debugger-enabled' ] // explicitly test if `--debugger-enabled` is present in the CLI arguments if(system.inDebugger("--debugger-enabled")) { console.log("in debugger"); }
Prevents the process from being shut down.
This can prevent people from exiting the process using CTRL+C.
Usingprocess.exit()
in your script will still exit the process though!
If you want the process to be able to be shut down again, usescl.yesShutdown()
.Note: this only listens for the signals "SIGINT" and "SIGTERM".
Due to many OSes not supporting it, using "SIGKILL" will still kill the process.scl.system.noShutdown(): void
Removes the script shut down prevention that was previously enabled with
scl.noShutdown()
.scl.system.yesShutdown(): void
Executes a function or Promise before the process is exited.
Rejecting the Promise will prevent a shutdown.❗ Warning:
- If
scl.noShutdown()
was used, the passed function will be executed, but the process will not exit- Due to how the Promise API works, you will need to call this function again if the passed Promise is rejected
scl.system.softShutdown(funct: function | Promise, code?: number): void
Example Code - click to show
const { system } = require("svcorelib"); const promise = new Promise((res) => { console.log("Goodbye!"); // sqlConnection.close(); // someOtherStuff.end(); setTimeout(() => res(), 1000); }); system.softShutdown(promise); // trigger shutdown: process.exit();
Sets the window title of the CLI / terminal.
This function supports most OSes (tested on Windows, Linux and macOS).scl.system.setWindowTitle(title: string): void
Example Code - click to show
const { system } = require("svcorelib"); const packageJson = require("./package.json"); // adjust this path if you're not in the project root dir system.setWindowTitle(`${packageJson.name} v${packageJson.version}`);
Asks the user for a key press and then resolves a promise.
Specify the text to display with the param
text
- if left empty this defaults to "Press any key to continue..."
The promise gets passed the key that the user has pressed.scl.system.pause(text?: string): Promise<string>
Example Code - click to show
const scl = require("svcorelib"); console.log("Hello, World!"); scl.system.pause("Press any key to exit").then(key => { console.log(`Pressed key: ${key}\nGoodbye, World!`); process.exit(); });
This namespace, accessed with just scl
, offers many miscellaneous functions.
This function checks whether or not all items of an array are equal or not.
Setloose
to true to switch to loose equality comparison (==
) instead of the default strict equality comparison (===
).
It returnstrue
if all items are equal orfalse
if not.scl.allEqual(array: any[], loose?: boolean): boolean
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.allEqual([ 1, 1, 1, 1 ]); let bar = scl.allEqual([ 1, 1, 2, 1 ]); let bazLoose = scl.allEqual([ 1, true, "1" ], true); let bazStrict = scl.allEqual([ 1, true, "1" ]); console.log(foo); // true console.log(bar); // false console.log(bazLoose); // true console.log(bazStrict); // false
This function checks if all values of an array are of a certain JS primitive type.
It does the same check you would do withif(typeof val === "whatever")
Valid type names are:
bigint
,boolean
,function
,number
,object
,string
,symbol
,undefined
scl.allOfType(array: any[], type: JSPrimitiveTypeName): boolean
Example Code - click to show
const { allOfType } = require("svcorelib"); console.log(allOfType([ 1, 2, 3, NaN ], "number")); // true console.log(allOfType([ { foo: 1 }, null ], "object")); // true console.log(allOfType([ 1, 2, "yo" ], "number")); // false
This function checks whether or not all items of an array are an instance of a passed class reference.
Make sure not to pass an instance of the class in the second parameter, but rather the actual class itself.
scl.allInstanceOf(array: any[], Class: AnyClass): boolean
Example Code - click to show
const { allInstanceOf } = require("svcorelib"); class MyClass {} abstract class AnotherClass {} class YetAnotherClass extends AnotherClass {} const foo = [ new MyClass(), new MyClass(), new MyClass(), ]; const bar = [ new YetAnotherClass(), ]; const baz = [ new MyClass(), 123, "yo", ]; console.log(allInstanceOf(foo, MyClass)); // true console.log(allInstanceOf(bar, AnotherClass)); // true console.log(allInstanceOf(bar, YetAnotherClass)); // true console.log(allInstanceOf(baz, MyClass)); // false
This function returns the length / size of a string in bytes.
If the paramstr
is not of type string, the function will return-1
.scl.byteLength(str: string): number
Example Code - click to show
const scl = require("svcorelib"); let str1 = "hello 👋"; let str2 = "𒈘"; // this character is U+12218 let foo = scl.byteLength(str1); let bar = scl.byteLength(str2); console.log(str1.length); // 8 console.log(foo); // 10 console.log(str2.length); // 2 console.log(bar); // 4
Sends a red console message and optionally exits the process with a certain status code.
The param
cause
specifies the actual error message.
If you want the error to be logged to a log file, specify the path to it with thelog_file_path
parameter. Make sure the path up to the file exists!
Ifshutdown
is set totrue
, SCL will exit the process.
Set an exit code with the paramstatus
. Leaving it empty will default to1
If you don't want to log the error to the console, setconsoleMsg
tofalse
scl.error(cause: string, log_file_path?: string, shutdown?: boolean, status?: number, consoleMsg?: boolean): void
Example Code - click to show
const scl = require("svcorelib"); const { resolve } = require("path"); scl.error("Couldn't establish a connection to the API", resolve("./errors/fatal.log"), true, 1); // Logs a red message to the console, puts it in the log file at "./errors/fatal.log", then exits the process with code 1
Checks how many values of an array are empty (does the same check as
scl.isEmpty()
, but on each array item).
Returnstrue
if all items are empty,false
if none are empty, or returns a number of how many items are empty.scl.isArrayEmpty(array: any[]): boolean | number
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.isArrayEmpty([ 1, 2, 3, 4, "", null, 5 ]); let bar = scl.isArrayEmpty([ "", null, undefined ]); let baz = scl.isArrayEmpty([ 1, 2, 3, 4, 5, NaN ]); console.log(foo); // 2 console.log(bar); // true console.log(baz); // false
Returns true, if the
input
is undefined, null, an empty string, an empty array or an object with length = 0.
Otherwise returns false. The number 0 and NaN will return false though, so check them independently if needed!scl.isEmpty(input: any): boolean
Example Code - click to show
const scl = require("svcorelib"); console.log(scl.isEmpty("")); // true console.log(scl.isEmpty([])); // true console.log(scl.isEmpty({})); // true console.log(scl.isEmpty({ a: 1 })); // false console.log(scl.isEmpty(0)); // false console.log(scl.isEmpty(1)); // false console.log(scl.isEmpty(null)); // true console.log(scl.isEmpty(undefined)); // true console.log(scl.isEmpty(NaN)); // false console.log(scl.isEmpty("foo")); // false
Returns true, if the
input
is a reference to a class, else returns false.
The check here is done for a reference to the actual class, not an instance of the class!scl.isClass(input: any): boolean
Example Code - click to show
const { isClass } = require("svcorelib"); class MyClass {} const foo = new MyClass(); const bar = "hello"; console.log(isClass(MyClass)); // true console.log(isClass(foo)); // false console.log(isClass(bar)); // false
Transforms the
value
parameter from the numerical rangerange_1_min
-range_1_max
to the numerical rangerange_2_min
-range_2_max
.
For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
It can be especially useful when calculating percentages, like when usingfiles.downloadFile()
or theProgressBar
class.
This function is the same as the map() function in Arduino.scl.mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number
Example Code - click to show
const scl = require("svcorelib"); let foo = scl.mapRange(10, 0, 100, 0, 10); let bar = scl.mapRange(3, 0, 10, 0, 50); console.log(foo); // 1 console.log(bar); // 15
Returns a random item of an array.
scl.randomItem(array: any[]): any
Example Code - click to show
const scl = require("svcorelib"); let array = [ 0, 1, null, 2, NaN, 3, { foo: "bar" }, 4, 5, 6 ]; let foo = scl.randomItem(array); let bar = scl.randomItem(array); let baz = scl.randomItem(array); console.log(foo); // { "foo": "bar" } console.log(bar); // 3 console.log(baz); // null
Chooses a random item in an array and returns it, along with its index in the array.
The returned value is a tuple array with two entries; either the item and its index or two times undefined, if the array is empty.scl.randomItemIndex(array: any[]): [item: any, index: number]
Example Code - click to show
const { randomItemIndex } = require("svcorelib"); const foo = [ "a", "b", "c", "d" ]; console.log(randomItemIndex(foo)); // ["b", 1] console.log(randomItemIndex(foo)); // ["d", 3] const [itm, idx] = randomItemIndex(foo); console.log(itm, idx); // a 0 console.log(randomItemIndex([ ])); // [undefined, undefined]
Chooses a random item in an array and returns it.
Also mutates the original array so the chosen item is no longer contained!scl.takeRandomItem(array: any[]): any
Example Code - click to show
const { takeRandomItem } = require("svcorelib"); const foo = [ "a", "b", "c" ]; console.log(takeRandomItem(foo)); // "b" console.log(foo); // [ "a", "c" ] console.log(takeRandomItem(foo)); // "c" console.log(foo); // [ "a" ] console.log(takeRandomItem(foo)); // "a" console.log(foo); // [ ] console.log(takeRandomItem(foo)); // undefined console.log(foo); // [ ]
Randomizes the order of items of an array and returns it.
scl.randomizeArray(array: any[]): any[]
Example Code - click to show
const scl = require("svcorelib"); let array = [ 0, 1, 2, 3, 4, 5, 6 ]; let foo = scl.randomizeArray(array); let bar = scl.randomizeArray(array); console.log(foo); // [ 1, 0, 2, 3, 5, 4, 6 ] console.log(bar); // [ 6, 1, 5, 2, 3, 4, 0 ]
Pseudo-random number generator where you can specify an upper and lower boundary.
Specify the upper and lower boundary with the parameters
min
andmax
Ifmin
is not provided, it will be set to the default of0
❗ Warning! This RNG is not cryptographically secure, so don't do any password hashing or stuff that needs to be highly secure with this function!
scl.randRange(min: number, max: number): number scl.randRange(max: number): number
Example Code - click to show
const { randRange } = require("svcorelib"); let foo = randRange(50, 60); let bar = randRange(10); console.log(foo); // 57 console.log(bar); // 3
Makes sure the provided number
num
is always in between a set boundary.Specify the upper and lower boundary with the parameters
min
andmax
scl.clamp(num: number, min: number, max: number): number
Example Code - click to show
const { clamp } = require("svcorelib"); for(let i = 1; i <= 10; i++) console.log(clamp(i, 3, 6)); // output: // 3, 3, 3, 4, 5, 6, 6, 6, 6, 6
Converts an array to a better readable string.
You can specify separators with the param
separators
- this will default to,
The last separator can be set with the paramlastSeparator
- this will default toand
scl.readableArray(array: any[], separators?: string, lastSeparator?: string): string
Example Code - click to show
const scl = require("svcorelib"); console.log(scl.readableArray([ 1, 2, 3, 4 ])); // "1, 2, 3 and 4"
Removes duplicate items of an array.
scl.removeDuplicates(array: any[]): any[]
Example Code - click to show
const scl = require("svcorelib"); let array = scl.removeDuplicates([ 1, 2, 4, 3, 3, 1, 3 ]); console.log(array); // [ 1, 2, 4, 3 ]
Returns both halves of an array as a tuple.
If you need more than two parts, usesplitIntoParts()
instead.If the passed array has one entry, the second value in the returned tuple will be an empty array.
If the passed array is empty, the returned array will be empty.scl.halves(array: any[]): [any[], any[]]
Example Code - click to show
const scl = require("svcorelib"); const halves = scl.halves([ 1, 2, 3, 4, 5, 6, 7 ]); const [first, second] = halves; console.log(halves); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7 ] ] console.log(first); // [ 1, 2, 3, 4 ] console.log(second); // [ 5, 6, 7 ]
Inserts values into a preformatted string containing so called insertion marks.
If there are no insertion marks, this function returns the unmodified input string.The parameter
str
is a string containing numbered insertion marks in the format%1
,%2
,%99
,%999
, ...
Thevalues
param is a rest parameter containing any values that can be converted to a string.This function throws a
TypeError
if the parameterstr
is not a string or if one of the values could not be converted to a string.insertValues(str: string, ...values: any[]): string;
Example Code - click to show
const scl = require("svcorelib"); class Person { constructor(name, age) { this.name = name; this.age = age; } text() { return scl.insertValues("%1 is %2 years old", this.name, this.age); } } let sven = new Person("Sven", 20); console.log(sven.text()); // "Sven is 20 years old"
Replaces a character from the specified
string
at the specifiedindex
with the value ofreplacement
scl.replaceAt(input: string, index: number, replacement: string): string
Example Code - click to show
const scl = require("svcorelib"); let text = scl.replaceAt("Hello, World!", 5, ", beautiful"); console.log(text); // Hello, beautiful World!
Reserializes a JSON-compatible object. This means it copies the value of an object and loses the internal reference to it.
Using an object that contains special JavaScript classes or a circular structure will result in unexpected behavior.Set
immutable
totrue
to freeze the returned object, making it non-modifiable.
Ifobj
is not of typeobject
, this function will just return the unmodified original value.scl.reserialize(obj: object, immutable?: boolean): object
Example Code - click to show
const scl = require("svcorelib"); // without reserialize: { let x = { foo: "bar" }; let y = x; y.foo = "test"; // sets "foo" to "test" on both x and y console.log(x.foo); // test console.log(y.foo); // test } // with reserialize: { let x = { foo: "bar" }; let y = scl.reserialize(x); y.foo = "test"; // sets "foo" to "test" only on y and not on x console.log(x.foo); // bar console.log(y.foo); // test } // example with setting it to immutable: { let x = { foo: "bar" }; let y = scl.reserialize(x, true); y.foo = "test"; // doesn't work, y.foo is still set to "bar" console.log(x.foo); // bar console.log(y.foo); // bar }
Splits an array into a certain amount of parts.
Use the parameter
partsAmt
to specify how many parts.
A value below 2 will return the input array as the only part.
balanced
is set to false by default. This way all returned subarrays have the same length except the last one, which is used as a buffer for uneven splits.
Set this parameter totrue
to make the returned parts equally balanced. This makes them have similar lengths.
See the example for a visual demonstration.The returned value is an array that contains the parts of the original array.
scl.splitIntoParts(array: any[], partsAmt: number, balanced?: boolean): any[][]
Example Code - click to show
const { splitIntoParts } = require("svcorelib"); // length: 22 const bugsnax = [ "Bunger", "Buffalocust", "Charmallow", "Cheepoof", "Cheery", "Cheezer", "Chillynilly", "Chippie", "Cinnasnail", "Clawbsteroni", "Cobhopper", "Eggler", "Flapjackarak", "Flutterjam", "Fryder", "Sweet Fryder", "Green Grapeskeeto", "Grapeskeeto", "Hunnabee", "Incherrito", "Inchwrap", "Instabug", ]; const unbalanced = splitIntoParts(bugsnax, 3); // [ [...], [...], [...] ] const balanced = splitIntoParts(bugsnax, 3, true); // [ [...], [...], [...] ] // using .map() to show how many items are in the subarrays: console.log(unbalanced.map(subArr => subArr.length)); // [ 10, 10, 2 ] - only last one has shorter length console.log(balanced.map(subArr => subArr.length)); // [ 8, 7, 7 ] - all have a similar length
Splits an array into any number of parts with a max length each.
maxLength
has to be a number that's at least 1 or higher.If the provided array is empty, an empty array will also be returned.
scl.splitIntoPartsOfLength(array: any[], maxLength: number): any[][]
Example Code - click to show
const { splitIntoPartsOfLength } = require("svcorelib"); // length: 22 const bugsnax = [ "Bunger", "Buffalocust", "Charmallow", "Cheepoof", "Cheery", "Cheezer", "Chillynilly", "Chippie", "Cinnasnail", "Clawbsteroni", "Cobhopper", "Eggler", "Flapjackarak", "Flutterjam", "Fryder", "Sweet Fryder", "Green Grapeskeeto", "Grapeskeeto", "Hunnabee", "Incherrito", "Inchwrap", "Instabug", ]; const foo = splitIntoPartsOfLength(bugsnax, 5); const bar = splitIntoPartsOfLength(bugsnax, 2); // using .map() to show how many items are in the subarrays: console.log(foo.map(subArr => subArr.length)); // [ 5, 5, 5, 5, 2 ] console.log(bar.map(subArr => subArr.length)); // [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]
Parses a duration in milliseconds into the larger units; days, hours, minutes, seconds and milliseconds.
The returned value is an object of type
ParseDurationResult
(see below).Throws a TypeError if the
millis
argument is not a number or less than 0.scl.parseDuration(millis: number): ParseDurationResult
Example Code - click to show
const scl = require("svcorelib"); console.log(scl.parseDuration(61419000)); // { days: 0, hrs: 17, mins: 3, secs: 39, ms: 0 }
{ days: number; // days hrs: number; // hours mins: number; // minutes secs: number; // seconds ms: number; // milliseconds }
Formats a duration in milliseconds to a human-friendly string, according to a provided format.
The format string can contain the following placeholders:
%d
for days,%h
for hours,%m
for minutes,%s
for seconds and%ms
for milliseconds.
Note that plurality (1 second vs 2 seconds) isn't supported yet. UseparseDuration()
instead.
leadingZeroes
defaults to true. Set it to false to leave every number as-is, and not add leading zeroes.Throws a TypeError if the arguments are invalid or the
millis
argument is less than 0.scl.formatDuration(millis: number, format: string, leadingZeroes?: boolean): string
Example Code - click to show
const scl = require("svcorelib"); const dur = 234219005; const foo = scl.formatDuration(dur, "%dd, %h:%m:%s.%ms"); const bar = scl.formatDuration(dur, "%dd, %h:%m:%s.%ms", false); console.log(foo); // 2d, 17:03:39.005 console.log(bar); // 2d, 17:3:39.5
Use this if you are using a linter that complains about unused vars.
As this function basically does nothing, you can even leave it in once the variable is used again and nothing will break.
The function accepts a virtually infinite amount of parameters of any type.scl.unused(...any: any): void
Example Code - click to show
const { unused } = require("svcorelib"); let my_unused_var = "Hello, World!"; // linter doesn't warn you about this line when using unused() unused(my_unused_var);
This section contains all of SCL's classes.
If you don't know about Object Oriented Programming in JavaScript, you can learn about it here.
Classes need to be created with the new
keyword unless a method explicitly states that it is static.
The FolderDaemon supervises a directory and optionally its subdirectories and executes a callback function if one or more of the files have changed.
Changed means if a file's content or metadata was modified, a file has been removed or a file has been added.
Constructs a new object of the class
FolderDaemon
.Specify the path to the directory you want to supervise with the param
dirPath
.
The optional parameteroptions
has to be an object of typeFolderDaemonOptions
new FolderDaemon(dirPath: string, options?: FolderDaemonOptions)
This method sets a callback function to be executed when files have changed.
It can both call a function passed in the paramcallback_fn
and it also returns a Promise.The promise will only be resolved once though. This is a limitation of the Promise API.
If you need to use the promise API and want multiple callbacks, you can just re-call this method after the promise has resolved every single time.
If the promise is resolved, you will get a single parameter, which is an array of strings, which contain the absolute file paths of all changed files.The callback function gets passed two parameters:
error
which can be eithernull
or a string containing an error messagedaemonResult
which is an array of strings containing absolute file paths to the changed filesFolderDaemon.onChanged(callback_fn: (error: null | string, daemonResult: string[]) => void): Promise<string[]>
This method removes the callback function(s) which have been registered with
FolderDaemon.onChanged()
FolderDaemon.removeCallbacks(): void
This method causes the FolderDaemon to re-scan the directory.
It is mandatory if you set theupdateInterval
to 0.FolderDaemon.intervalCall(): void
This object is used in the construction of a FolderDaemon.
If you set
recursive
totrue
, the FolderDaemon will recursively look through all subdirectories of the specified directory.
TheupdateInterval
property can be used to set an interval at which the daemon should check all files. Defaults to500
ms - set to0
to disable the interval, then callintervalCall()
to manually scan the directory.The property
blacklist
can be passed an array of strings which contain glob patterns. If a file matches any of these patterns, the file will be ignored.
Similarly, if thewhitelist
property, which is also an array of strings containing glob patterns, is set, only the matched files will be supervised by the daemon.Note: You can only use either the whitelist or the blacklist, not both at the same time - else a
TypeError
is thrown.{ recursive?: true, // default is false updateInterval?: 1000, // default is 500 blacklist?: [ "*.txt" ], // default is [] whitelist?: [] // default is [] }
Example Code - Click to view
const scl = require("svcorelib"); let dirPath = "./"; // supervises your entire project workspace let blacklist = [ "*.txt" ]; // ignores all files with the extension .txt let recursive = true; // scans through all subdirectories too let updateInterval = 1000; // the interval in milliseconds of when to scan all files let fd = new scl.FolderDaemon(dirPath, blacklist, recursive, updateInterval); fd.onChanged((err, result) => { if(err) console.error(`Error: ${err}`); else console.log(`Files have changed:\n- ${result.join("\n- ")}`); });
The class
MenuPrompt
creates an interactive prompt with one or many menus - add them usingMenuPrompt.addMenu()
To translate the messages, you can use theMenuPromptLocalization
object, which is where all text variables are stored.❗ Warning: After creating a MenuPrompt object, the process will no longer exit automatically until the MenuPrompt has finished or was explicitly closed. You have to explicitly use process.exit() until the menu has finished or is closed.
❗ 2nd Warning: Don't log anything to the console or write anything toprocess.stdin
while the MenuPrompt is opened as it would completely mess it up.
Constructs a new object of the class
MenuPrompt
.The only parameter
options
can be passed an object of typeMenuPromptOptions
.
Leaving this param empty will make the MenuPrompt use default values.new MenuPrompt(options?: MenuPromptOptions)
Adds a new menu to the menu prompt.
A single menu prompt can hold a virtually infinite amount of menus.
You can even dynamically add new menus while the MenuPrompt is still open.The param
menu
needs to be an object of typeMenuPromptMenu
This method either returns
true
if it was successful or it returns a string containing an error message.MenuPrompt.addMenu(menu: MenuPromptMenu): boolean | string
Opens the MenuPrompt.
Make sure to add menus to the MenuPrompt usingMenuPrompt.addMenu()
before calling this method!
❗ Warning: While the menu is opened you shouldn't write anything to the console / to the stdout and stderr as this could mess up the layout of the menu and/or make stuff unreadable.This method either returns
true
if it was successful or it returns a string containing an error message.MenuPrompt.open(): boolean | string
Closes the MenuPrompt and returns the results of all menus that have been completed up to this point.
This method returns the results of the MenuPrompt as an array of objects of type
MenuPromptResult
MenuPrompt.close(): MenuPromptResult[]
Returns the (zero-based) index of the currently open menu of the MenuPrompt.
If the MenuPrompt hasn't been opened yet, this will return-1
MenuPrompt.currentMenu(): number
Returns the current results of the MenuPrompt as an array of objects of type
MenuPromptResult
This does not close the menu prompt, unlikeclose()
If there aren't any completed menus yet, this method will return
null
MenuPrompt.result(): MenuPromptResult | null
Checks a menu object for valid syntax.
The param
menu
needs to be a single object of typeMenuPromptMenu
The method either returns
true
if the menu is valid or an array of strings containing error messages.MenuPrompt.validateMenu(menu: MenuPromptMenu): boolean | string[]
This specifies a single menu of a MenuPrompt.
{ title: "Example Menu", // the title of the menu options: [ // an array of options the user can select { "key": "1", // the key the user needs to press to select this option "description": "Foo" // the name / description of this option }, { "key": "2", "description": "Bar" }, // ... ] }
This object is used in the constructor of a MenuPrompt.
Here you can specify a few settings that affect all menus of a MenuPrompt.{ exitKey: string; // The key or keys that need to be entered to exit the prompt - if left empty, the menu can't be exited with a key optionSeparator: string; // The separator character(s) between the option key and the option description cursorPrefix: string; // Character(s) that should be prefixed to the cursor. Will default to this arrow: "─►" retryOnInvalid: boolean; // Whether the menu should be retried if the user entered a wrong option - defaults to true - if set to false, continues to next menu when an invalid option was selected onFinished: function; // A function that gets called when the user is done with all of the menus of the prompt or entered the exit key(s). The only passed parameter is an array containing all selected option keys autoSubmit: boolean; // If set to true, the MenuPrompt will only accept a single character of input and will then automatically submit the current menu - make sure the option keys are only a single character in length! If set to false, the user will have to explicitly press the Enter key to submit a value. }
This object contains information about what option a user selected in a single menu.
You will only encounter these objects inside of arrays.{ key: string; // The key of the selected option description: string; // The description of the selected option menuTitle: string; // The title of the menu optionIndex: number; // The zero-based index of the selected option menuIndex: number; // The zero-based index of the menu }
You can access this object directly on the MenuPrompt with the property
localization
(example is below).{ wrongOption: string; // The text that's displayed when a wrong key was pressed invalidOptionSelected: string; // A different text that's displayed when a wrong key was pressed exitOptionText: string; // The name of the exit option }
Example Localization - click to show
const scl = require("svcorelib"); /** @type {scl.MenuPromptOptions} */ let opts = { exitKey: "x", autoSubmit: true, /** @param {scl.MenuPromptResult[]} res */ onFinished: (res) => { // if the user selected an option if(res.length > 0) console.log(`Finished. Selected option: ${res[0].key} (${res[0].description})`); else console.log(`User selected "Exit"`); } }; let mp = new scl.MenuPrompt(opts); let menu = { title: "Example Menu", options: [ { key: "1", description: "Foo" }, { key: "2", description: "Bar" } ] }; // Make sure menu is valid let menuValid = mp.validateMenu(menu); if(menuValid) { // Now that the menu is confirmed to be valid, add it mp.addMenu(menu); // Open the menu mp.open(); } else console.log(`Error: Menu is invalid.\n${menuValid.join(", ")}`);
The ProgressBar simply displays a progress bar in the Command Line Interface (CLI).
It displays an automatically calculated percentage value and an optional message.
Constructs a new object of the class
ProgressBar
.The param
timesToUpdate
needs to be passed the number of times you are going to call the methodnext()
.
This parameter is also directly correlated to the length of the progress bar.
The optional parameterinitialMessage
can contain a string that is displayed at 0% progress. If left undefined, no message will appear.new ProgressBar(timesToUpdate: number, initialMessage?: string)
Increments the progress bar once.
How many times you are going to call this method needs to be known when creating a ProgressBar object as it is needed in the constructor.
This is a fundamental thing about progress bars and I can't change it.The optional parameter
message
can be used to display a message next to the progress bar.ProgressBar.next(message?: string): void
Registers a function to be called when the progress bar reaches 100%.
ProgressBar.onFinish(callback: function): void;
Returns the current progress as a floating-point number between
0.0
and1.0
ProgressBar.getProgress(): number;
Returns the amount of increments needed to reach 100% progress - aka the amount of times the method
next()
needs to be called.ProgressBar.getRemainingIncrements(): number;
Example Code - Click to view
const scl = require("svcorelib"); let pb = new scl.ProgressBar(15, "Doing some stuff (Iteration #0)"); // Register Promise callback to be executed when the progress bar reaches 100% pb.onFinish().then(() => { console.log("Finished.\n\n"); }); // Increment progress bar after a random timeout function iterate(iterations) { if(iterations < 15) { setTimeout(() => { iterations++; pb.next(`Doing some stuff (Iteration #${iterations})`); iterate(iterations); }, scl.randRange(200, 400)); } } iterate(0);
The SelectionMenu allows a user to scroll through a list of options and select one of them.
Click here to see an example of how this might look like
(disregard the
[
character in the first line)
Constructs a new object of the class
SelectionMenu
.
If you want to translate the default texts, use the objectlocale
.The optional param
title
specifies a title shown on a line above the options of the SelectionMenu.
With the optional parametersettings
you can configure the SelectionMenu to your liking. It is explained here.Throws a
NoStdinError
if the terminal in which the process runs doesn't have a stdin stream or isn't a compatible TTY terminal.new SelectionMenu(title?: string, settings?: SelectionMenuSettings)
Sets or overwrites the options of the SelectionMenu.
The parameter
options
needs to be an array of strings containing the text of the options.Returns a string containing an error message or
true
if it was successful.SelectionMenu.setOptions(options: string[]): string | boolean
Adds a single option to the SelectionMenu.
The parameter
option
needs to be a string.Returns a string containing an error message or
true
if it was successful.SelectionMenu.addOption(option: string): string | boolean
Registers a function to be called SelectionMenu.
The parameter
callback_fn
can be passed a function to be called when the SelectionMenu is submitted or canceled.
This function gets passed a single parameter of type SelectionMenuResult.Returns a promise that resolves with an object of type SelectionMenuResult or rejects with a string containing an error message.
SelectionMenu.onSubmit(callback_fn?: function(SelectionMenuResult){}): Promise<SelectionMenuResult>
Opens the SelectionMenu.
Make sure to add options withsetOptions()
oraddOption()
before calling this method.Returns a string containing an error message or
true
if it was successful.SelectionMenu.open(): string | boolean
Prematurely closes the SelectionMenu.
This will not cause the callback functions that have been registered withonSubmit()
to be executed.Returns a boolean of whether or not the SelectionMenu could be closed.
SelectionMenu.close(): boolean
This object is used in the construction of a SelectionMenu object.
{ cancelable: boolean, // Set to false to prevent users from canceling the SelectionMenu - defaults to true overflow: boolean // If set to true, if the user scrolls past the end or beginning, this makes the cursor of the menu overflow to the other side - defaults to true }
You can access this object directly on the SelectionMenu with the property
locale
(example is below).{ escKey: string; // Shorthand name of the escape key - defaults to "Esc" cancel: string; // Cancel text - defaults to "Cancel" scroll: string; // Scroll text - defaults to "Scroll" returnKey: string; // Shorthand name of the return key - defaults to "Return" select: string; // Select text - defaults to "Select" }
Example Localization - click to show
const scl = require("svcorelib"); let sm = new scl.SelectionMenu(); sm.addOption("Example Option"); sm.locale.cancel = "Exit"; sm.locale.returnKey = "↵"; sm.open();
Example Code - Click to view
const scl = require("svcorelib"); let sm = new scl.SelectionMenu("Example SelectionMenu:", { cancelable: true, overflow: true }); // Set first 5 options let setOptionsRes = sm.setOptions([ "Foo", "Bar", "Apple", "Pear", "Banana" ]); if(typeof setOptionsRes == "string") console.error(`Error while setting options: ${setOptionsRes}`); // Add another option let addOptionRes = sm.addOption("Baz"); if(typeof addOptionRes == "string") console.error(`Error while adding option: ${addOptionRes}`); // Add handler that gets called when the menu is submitted sm.onSubmit().then(res => { if(res.canceled) console.log(`User canceled the SelectionMenu`); else console.log(`User selected option "${res.option.description}" (index ${res.option.index})`); }).catch(err => { console.error(`Error while submitting SelectionMenu: ${err}`); }); // Alternatively, use the EventEmitter's .on() method sm.on("submit", (res) => { if(res.canceled) console.log(`User canceled the SelectionMenu`); else console.log(`User selected option "${res.option.description}" (index ${res.option.index})`); }); // Open the menu let openRes = sm.open(); if(typeof openRes === "string") console.error(`Error while opening SelectionMenu: ${openRes}`);
This class is a wrapper for the Promise API.
It keeps track of the state of the promise it wraps around.
Constructs a new object of the class
StatePromise
This class is a wrapper for the Promise API.
It keeps track of the state of the promise it wraps.Make sure to call
exec()
to actually execute the passed promise and to retrieve the returned value(s).The param
promise
is the promise to wrap around and to extract the state from.Throws a
TypeError
if thepromise
parameter is not an instance of thePromise
class.new StatePromise(promise: Promise)
This function actually executes the Promise.
Returns a new Promise instance (not the one from the constructor) that does however inherit the returned values from the constructor promise.
StatePromise.exec(): Promise
Returns the state of this Promise, as a string.
The possible states are:
State Description initialized
The StatePromise instance was created but the exec()
method wasn't called yetpending
The promise execution was started but it hasn't been resolved or rejected yet resolved
Execution was finished and the promise was resolved rejected
Execution was finished but the promise was rejected
SelectionMenu.getState(): "initialized" | "pending" | "resolved" | "rejected"
Example Code - Click to view
const { StatePromise } = require("svcorelib"); // Promise to wrap around const prom = new Promise((res, rej) => { // replace `res` with `rej` to test promise rejection setTimeout(() => res("test123"), 3500); }); const stp = new StatePromise(prom); console.log("START"); // Execute the StatePromise stp.exec().then((...returnedValues) => { console.log(`THEN: ${returnedValues}`); }).catch(err => { console.error(`CATCH: ${err}`); }); let iter = 0; const interval = setInterval(() => { console.log(`Iteration #${iter} - State: ${stp.getState()}`); iter++; if(iter == 5) clearInterval(interval); }, 1000);
Output:
START - State: initialized Iteration #0 - State: pending Iteration #1 - State: pending Iteration #2 - State: pending THEN: test123 Iteration #3 - State: resolved Iteration #4 - State: resolved
This class namespace, accessed with scl.Errors
, contains all of SCL's custom error classes.
They are used by SCL but feel free to also use these.
The classes have to be constructed with the new
keyword.
All of these classes extend from the base class SCLError
, which in turn extends from the Error
class.
The SCLError
base class adds a property date
, which is an instance of Date
and which represents the exact time the error instance was created.
This is the base class of all of SCL's Error classes.
Constructs a new object of the class
SCLError
The param
message
is optional. It contains a more detailed error message.new Errors.SCLError(message?: string)
Example Code - Click to view
const { Errors, colors } = require("svcorelib"); try { throw new Errors.SCLError("idk, something probably went wrong"); } catch(err) { // SCLError exposes the `date` property, which you can use for logging, debugging, etc.: console.error(`${colors.fg.red}Error thrown at ${err.date.toString()}: ${colors.rst}${err.toString()}`); }
This error gets thrown when a provided path is invalid or doesn't exist on the current device.
Constructs a new object of the class
InvalidPathError
.The param
message
is optional. It contains a more detailed error message.
SCL usually puts the invalid path in this parameter.new Errors.InvalidPathError(message?: string)
Example Code - Click to view
const { files, Errors } = require("svcorelib"); const fs = require("fs"); const { resolve } = require("path"); /** @throws InvalidPathError if the provided path doesn't exist */ async function throwIfNotExists(path) { path = resolve(path); if(!(await files.exists(path))) throw new Errors.InvalidPathError(`Path "${path}" doesn't exist.`); return; } async function run() { await throwIfNotExists("./package.json"); // no error is thrown await throwIfNotExists("./path/that/doesnt/exist"); // error is thrown here } run();
This error gets thrown when a provided path is valid but doesn't point to a folder / directory.
Constructs a new object of the class
NotAFolderError
.The param
message
is optional. It contains a more detailed error message.
SCL usually puts the invalid path in this parameter.new Errors.NotAFolderError(message?: string)
Example Code - Click to view
const scl = require("svcorelib"); const fs = require("fs"); const { resolve } = require("path"); /** @throws NotAFolderError if the provided path doesn't point to a folder */ function pathIsFolder(path) { path = resolve(path); if(!fs.statSync(path).isDirectory()) throw new scl.Errors.InvalidPathError(`Path "${path}" doesn't point to a folder.`); return; } pathIsFolder("./src"); // no error is thrown pathIsFolder("./SvCoreLib.js"); // error is thrown here
This error gets thrown when a provided glob pattern is invalid.
Constructs a new object of the class
PatternInvalidError
.The param
message
is optional. It contains a more detailed error message.
SCL usually puts the invalid pattern in this parameter.new Errors.PatternInvalidError(message?: string)
This error gets thrown when the terminal that the process runs in doesn't provide an stdin channel.
Constructs a new object of the class
NoStdinError
.The param
message
is optional. It contains a more detailed error message.new Errors.NoStdinError(message?: string)
This error gets thrown when an invalid MIME type was provided.
Constructs a new object of the class
InvalidMimeTypeError
.The param
message
is optional. It contains a more detailed error message.new Errors.InvalidMimeTypeError(message?: string)
This error gets thrown when a SQL database connection was not established yet or errored out.
Constructs a new object of the class
SqlConnectionNotEstablishedError
.The param
message
is optional. It contains a more detailed error message.
In SCLs case, this parameter contains the current connection state of the DB connection.new Errors.SqlConnectionNotEstablishedError(message?: string)
This section contains all of SCLs objects.
These are read-only, static and passive properties and will not invoke or change anything.
This object can be used to color text in the Command Line Interface (CLI).
Since typingscl.colors.xy.color_name
can be quite long, I recommend declaring one or multiple variables like shown in the example code below.scl.colorsSupported colors are:
Color SCL ❌ Reset to default scl.colors.rst
orscl.colors.fg.rst
orscl.colors.bg.rst
💡 Bright color scl.colors.bright
🚨 Blinking scl.colors.blink
⚫️ Black Text scl.colors.fg.black
⚫️ Black Background scl.colors.bg.black
🟥 Red Text scl.colors.fg.red
🟥 Red Background scl.colors.bg.red
🟩 Green Text scl.colors.fg.green
🟩 Green Background scl.colors.bg.green
🟨 Yellow Text scl.colors.fg.yellow
🟨 Yellow Background scl.colors.bg.yellow
🟦 Blue Text scl.colors.fg.blue
🟦 Blue Background scl.colors.bg.blue
🟪 Magenta Text scl.colors.fg.magenta
🟪 Magenta Background scl.colors.bg.magenta
🔷 Cyan Text scl.colors.fg.cyan
🔷 Cyan Background scl.colors.bg.cyan
⚪️ White Text scl.colors.fg.white
⚪️ White Background scl.colors.bg.white
Example Code - click to show
const scl = require("svcorelib"); const { fg, bg } = scl.colors; console.log(`${scl.colors.fat}Foreground Colors: ${fg.green}Green${fg.rst} ${fg.magenta}Magenta${fg.rst} ${fg.blue}Blue${fg.rst} ${fg.cyan}Cyan${fg.rst}`); console.log(`${scl.colors.fat}Background Colors: ${bg.green}Green${fg.rst} ${bg.magenta}Magenta${fg.rst} ${bg.blue}Blue${fg.rst} ${bg.cyan}Cyan${bg.rst}`);
This object offers a few read-only bits of information about SCL, like the version number or license.
scl.infoProperties:
Property Type Description scl.info.version
string
SCLs current version, as a semver-compatible string scl.info.intVersion
number[]
SCLs version, as an array of numbers, for better usability within code scl.info.name
string
The name of SCL (who knows, maybe it'll change eventually) scl.info.desc
string
A short description of what SCL is and does scl.info.author
string
The name of the author of SCL (currently Sv443
)scl.info.authorLong
string
The authors name, email address and homepage in this format: Name <Email> (URL)
scl.info.contributors
object[]
The contributors
property of SCLspackage.json
filescl.info.license
string
The license and URL to the license text of SCL in the format License (URL)
scl.info.documentation
string
A URL to SCLs documentation
Example Code - click to show
const scl = require("svcorelib"); if(scl.info.intVersion[0] < 1 && scl.info.intVersion[1] < 12) console.error(`This code needs ${scl.info.name} v1.12.x or higher to run!\nHow to install the latest version: ${scl.info.documentation}#installation`);
This is where you can find all legal information about SCL and the Sv443 Network.
SvCoreLib is licensed under the MIT license. You can view the full license text by clicking here.
Below is a short summary of the license (it is not legal advice though):
- use this library anywhere
- copy the source code of the library
- modify the source code of the library
- merge the source code with other code
- publish and distribute the code (even under a different license)
- monetize or sell the code or projects that contain the code
- remove the
LICENSE.txt
file from the finished product. It has to be contained in every distribution of your product and accessible by the end user - publish the code without modifying it and claim it as your own
- modify the code, publish it and then claim it as your own (and no-one else's)
- claim any warranty. This software is provided "as is"
- demand any liability from the author(s) and contributors
I will hereby not claim any legal responsibility or liability for SvCoreLib. Whether it is used maliciously or breaks something, I can't be held accountable.
I am doing my best to ensure security and stability but there's only so much a single developer can do.
Security patches are created as soon as possible but I don't have any binding responsibility to make these patches.
Please create a backup before using this library if you want to be extra secure and report any issue that may arise to the GitHub issue tracker and I will try my best to fix it as soon as possible.
Click here to view the privacy policy.
Click here to view the security policy.
Made with ❤️ by Sv443
Please consider supporting me