Socket
Socket
Sign inDemoInstall

@b613/utils

Package Overview
Dependencies
115
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0-beta24 to 1.0.0-beta25

lib/color/color.node.d.ts

82

lib/array.d.ts
/**
* Array split into groups of specific length
* Splits an array into multiple arrays of specified size.
* @template T
* @param {T[]} array - The array to split.
* @param {number} limit - The size limit for each sub-array.
* @returns {T[][]} An array containing arrays of elements from the original array.
*/
export function split<T>(array: T[], limit: number): T[][];
export declare function split<T>(array: T[], limit: number): T[][];
/**
* Swap the `fromIndex` and `toIndex` index elements of the given `array`
* Swaps items in an array at specified indices.
* @param {any[]} array - The array containing the items to swap.
* @param {number} from - The index of the first item to swap.
* @param {number} to - The index of the second item to swap.
* @returns {void}
*/
export function swapItems(array: any[], fromIndex: number, toIndex: number): void;
export declare function swapItems(array: any[], from: number, to: number): void;
/**
* Shuffle elements of the given `array`
* Shuffles the elements of an array in place.
* @template T
* @param {T[]} array - The array to shuffle.
* @returns {T[]} The shuffled array.
*/
export function shuffle<T>(array: T[]): T[];
export declare function shuffle<T>(array: T[]): T[];
/**
* Add `item` between array items
* @returns A new array
* Returns a new array by inserting a specified item between each element of the original array.
* @template T
* @param {Readonly<T>[]} array - The array to include the item in.
* @param {Readonly<T>} item - The item to include between each element.
* @returns {T[]} A new array with the specified item included between each element.
*/
export function include<T>(array: Readonly<T>[], item: Readonly<T>): T[];
export declare function include<T>(array: Readonly<T>[], item: Readonly<T>): T[];
/**
* Check whether `array1` and `array2` are equal, returning a Boolean result.
* The function uses the [Strict Equality Comparison Algorithm](https://www.ecma-international.org/ecma-262/5.1/#sec-11.9.6)
* to compare two operands.
* - If one of operands is not an array, return `false`.
* - If the operands have the same reference, return `true`.
* - If the two operands do not have the same length, return `false`.
* - If each item of the first operand is strictly equals to its equivalent in
* the second operand, return `true`
* Checks if two arrays are identical, i.e., have the same elements in the same order.
* @param {Array} array1 - The first array to compare.
* @param {Array} array2 - The second array to compare.
* @returns {boolean} Returns true if the arrays are identical, false otherwise.
*/
export function identical(array1: any[], array2: any[]): boolean;
export declare function identical(array1: any, array2: any): boolean;
/**
* Remove `element` from the given `array` and returns the index of the
* removed `element`
* Removes the first occurrence of a specified item from an array.
* @template T
* @param {T[]} array - The array to remove the item from.
* @param {T} itemToRemove - The item to remove.
* @returns {number} The index of the removed item, or -1 if the item is not found.
*/
export function remove<T>(array: T[], element: T): number;
export declare function remove<T = unknown>(array: T[], itemToRemove: T): number;
/**
* Returns the index of the first element in the array, and -1 otherwise.
* Finds the index of the first occurrence of a specified element in an array.
* @template T
* @param {T[]} items - The array to search for the element.
* @param {T} element - The element to find.
* @returns {number} The index of the first occurrence of the element, or -1 if not found.
*/
export function findIndex<T>(items: T[], element: T): number;
export declare function findIndex<T = unknown>(items: T[], element: T): number;
/**
* Finds the intersection of multiple arrays.
* @param {any[][]} arrays - Arrays to find the intersection from.
* @returns {any[]} The intersection of the arrays.
*/
export declare function intersection(arrays: any[][]): any[];
/**
* Removes duplicate elements from an array while preserving the original order.
* @template T
* @param {T[]} arr - The array to remove duplicates from.
* @returns {T[]} A new array with duplicate elements removed.
*/
export declare function removeDuplicates<T>(arr: T[]): T[];

@@ -1,5 +0,9 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findIndex = exports.remove = exports.identical = exports.include = exports.shuffle = exports.swapItems = exports.split = void 0;
function split(array, limit) {
/**
* Splits an array into multiple arrays of specified size.
* @template T
* @param {T[]} array - The array to split.
* @param {number} limit - The size limit for each sub-array.
* @returns {T[][]} An array containing arrays of elements from the original array.
*/
export function split(array, limit) {
const input = [...array];

@@ -15,20 +19,33 @@ if (limit <= 0) {

}
exports.split = split;
function swapItems(array, from, to) {
/**
* Swaps items in an array at specified indices.
* @param {any[]} array - The array containing the items to swap.
* @param {number} from - The index of the first item to swap.
* @param {number} to - The index of the second item to swap.
* @returns {void}
*/
export function swapItems(array, from, to) {
[array[from], array[to]] = [array[to], array[from]];
}
exports.swapItems = swapItems;
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
/**
* Shuffles the elements of an array in place.
* @template T
* @param {T[]} array - The array to shuffle.
* @returns {T[]} The shuffled array.
*/
export function shuffle(array) {
for (let index = array.length - 1; index > 0; index--) {
const j = Math.floor(Math.random() * (index + 1));
[array[index], array[j]] = [array[j], array[index]];
}
return array;
}
exports.shuffle = shuffle;
/**
* Add `item` between array items
* @returns A new array
* Returns a new array by inserting a specified item between each element of the original array.
* @template T
* @param {Readonly<T>[]} array - The array to include the item in.
* @param {Readonly<T>} item - The item to include between each element.
* @returns {T[]} A new array with the specified item included between each element.
*/
function include(array, item) {
export function include(array, item) {
return array.reduce((children, entry, index) => {

@@ -42,4 +59,9 @@ children.push(entry);

}
exports.include = include;
function identical(array1, array2) {
/**
* Checks if two arrays are identical, i.e., have the same elements in the same order.
* @param {Array} array1 - The first array to compare.
* @param {Array} array2 - The second array to compare.
* @returns {boolean} Returns true if the arrays are identical, false otherwise.
*/
export function identical(array1, array2) {
if (!Array.isArray(array1) || !Array.isArray(array2)) {

@@ -56,4 +78,10 @@ return false;

}
exports.identical = identical;
function remove(array, itemToRemove) {
/**
* Removes the first occurrence of a specified item from an array.
* @template T
* @param {T[]} array - The array to remove the item from.
* @param {T} itemToRemove - The item to remove.
* @returns {number} The index of the removed item, or -1 if the item is not found.
*/
export function remove(array, itemToRemove) {
const index = array.findIndex((item) => item === itemToRemove);

@@ -65,10 +93,42 @@ if (index > -1) {

}
exports.remove = remove;
/**
* Returns the index of the first element in the array, and -1 otherwise.
* Finds the index of the first occurrence of a specified element in an array.
* @template T
* @param {T[]} items - The array to search for the element.
* @param {T} element - The element to find.
* @returns {number} The index of the first occurrence of the element, or -1 if not found.
*/
function findIndex(items, element) {
export function findIndex(items, element) {
return items.findIndex((currentItem) => currentItem === element);
}
exports.findIndex = findIndex;
/**
* Finds the intersection of multiple arrays.
* @param {any[][]} arrays - Arrays to find the intersection from.
* @returns {any[]} The intersection of the arrays.
*/
export function intersection(arrays) {
if (arrays.length === 0) {
return [];
}
if (arrays.length === 1) {
return arrays[0];
}
const restArrays = arrays.slice(1);
return arrays[0].filter((element) => restArrays.every((array) => array.includes(element)));
}
/**
* Removes duplicate elements from an array while preserving the original order.
* @template T
* @param {T[]} arr - The array to remove duplicates from.
* @returns {T[]} A new array with duplicate elements removed.
*/
export function removeDuplicates(arr) {
const uniqueArr = [];
for (const item of arr) {
if (uniqueArr.indexOf(item) === -1) {
uniqueArr.push(item);
}
}
return uniqueArr;
}
//# sourceMappingURL=array.js.map

@@ -1,12 +0,52 @@

import { Trace } from './Trace';
import { AxiosInstance, AxiosRequestConfig } from 'axios';
import { IAxiosCacheAdapterOptions } from 'axios-cache-adapter';
import { Color } from './color';
export type Options = Omit<AxiosRequestConfig, 'baseURL'> & {
logger?: Trace;
cache?: IAxiosCacheAdapterOptions;
color?: Color;
export type Method = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'TRACE';
export type RequestAuth = {
token?: string;
username?: string;
roles?: string;
};
export function createClient(baseURL: string, options?: Options): AxiosInstance;
export type RequestOptions<T extends Record<string, any> = object> = RequestInit & {
params?: T;
data?: any;
};
export type Options<AdditionalOptions extends Record<string, any> = never> = RequestInit & {
logger?(message: string, type: string): void;
beforeEach?: <T extends Record<string, any>>(method: Method, path: string, request: RequestOptions<T> & Partial<AdditionalOptions>) => void;
};
export interface RequestInit {
/** A string indicating how the request will interact with the browser's cache to set request's cache. */
cache?: RequestCache;
/** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */
credentials?: RequestCredentials;
/** A Headers object, an object literal, or an array of two-item arrays to set request's headers. */
headers?: HeadersInit;
/** A cryptographic hash of the resource to be fetched by request. Sets request's integrity. */
integrity?: string;
/** A boolean to set request's keepalive. */
keepalive?: boolean;
/** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */
mode?: RequestMode;
/** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */
redirect?: RequestRedirect;
/** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */
referrer?: string;
/** A referrer policy to set request's referrerPolicy. */
referrerPolicy?: ReferrerPolicy;
/** An AbortSignal to set request's signal. */
signal?: AbortSignal | null;
/** Can only be null. Used to disassociate request from any Window. */
window?: null;
}
/**
* Creates an HTTP client to make requests.
* @template AdditionalOptions
* @param {string} baseUrl - The base URL for requests.
* @param {Options<AdditionalOptions>} [options={}] - Additional options for the client.
* @returns {{
* options: Options<AdditionalOptions>,
* execute<T>(method: Method, path: string, request?: RequestOptions & Partial<AdditionalOptions>): Promise<T>
* }} The HTTP client.
*/
export declare function createClient<AdditionalOptions extends Record<string, any> = never>(baseUrl: string, options?: Options<AdditionalOptions>): {
options: Options<AdditionalOptions>;
execute<T>(method: Method, path: string, request?: RequestOptions & Partial<AdditionalOptions>): Promise<T>;
};

@@ -1,31 +0,53 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createClient = void 0;
const tslib_1 = require("tslib");
const axios_1 = tslib_1.__importDefault(require("axios"));
const axios_cache_adapter_1 = tslib_1.__importDefault(require("axios-cache-adapter"));
const fallbackColor = {
cyan: (str) => `${str}`,
red: (str) => `${str}`,
yellow: (str) => `${str}`,
green: (str) => `${str}`,
};
function createClient(baseURL, { headers = {}, logger, cache, color = fallbackColor, ...options } = {}) {
const adapter = cache ? axios_cache_adapter_1.default.setupCache(cache).adapter : undefined;
const instance = axios_1.default.create({ ...options, baseURL, headers, adapter });
instance.interceptors.response.use((response) => {
const method = response.request.method || 'GET';
const prefix = `${method.toUpperCase()} ${response.config.url}`;
if (response.status >= 400) {
logger === null || logger === void 0 ? void 0 : logger.info(`${prefix} ${color.red(response.status)}`, 'HTTP');
logger === null || logger === void 0 ? void 0 : logger.error(`Error ${response.status}: ${JSON.stringify(response.data, null, 2)}`);
}
else {
logger === null || logger === void 0 ? void 0 : logger.info(`${prefix} ${color.green(response.status)}`, 'HTTP');
}
return response;
});
return instance;
/* eslint-disable max-len */
import { createHttpException } from './http.js';
import { stringify } from './qs.js';
/**
* Creates an HTTP client to make requests.
* @template AdditionalOptions
* @param {string} baseUrl - The base URL for requests.
* @param {Options<AdditionalOptions>} [options={}] - Additional options for the client.
* @returns {{
* options: Options<AdditionalOptions>,
* execute<T>(method: Method, path: string, request?: RequestOptions & Partial<AdditionalOptions>): Promise<T>
* }} The HTTP client.
*/
export function createClient(baseUrl, options = {}) {
const mainHeaders = options.headers ?? {};
return {
options,
async execute(method, path, request = {}) {
if (options.beforeEach) {
options.beforeEach(method, path, request);
}
const { params, data, ...rest } = request;
let url = baseUrl + path;
const requestHeaders = rest.headers ?? {};
const requestOptions = { ...options, ...request, headers: { ...mainHeaders, ...requestHeaders } };
if (params) {
const q = stringify(params);
if (q) {
url += `?${q}`;
}
}
const response = await fetch(url, { ...requestOptions, method, body: data });
if (options.logger) {
options.logger(`${method} ${url} ${response.status}`, 'HTTP');
}
if (response.ok) {
const contentType = response.headers.get('content-type');
if (contentType?.includes('application/json')) {
return response.json();
}
if (contentType?.includes('application/octet-stream') || contentType?.includes('image/') || contentType?.includes('audio/') || contentType?.includes('video/')) {
return Buffer.from(await response.arrayBuffer());
}
if (contentType?.includes('text')) {
return await response.text();
}
return response;
}
throw createHttpException(response.status, response.statusText);
},
};
}
exports.createClient = createClient;
//# sourceMappingURL=client.js.map

@@ -0,6 +1,28 @@

/**
* Represents a circular list that iterates over its elements infinitely.
* @template T
*/
export declare class CircularList<T> {
index: number;
constructor(items: T[]);
next(excludes?: T[]): T;
/** The array of items in the circular list. */
private items;
/** The generator for iterating over items in a circular manner. */
private gen;
/** The current index of the generator. */
index: number;
/**
* Creates a circular list.
* @param {T[]} items - The array of items to include in the circular list.
*/
constructor(items: T[]);
/**
* Gets the next item in the circular list, excluding specified items.
* @param {T[]} [excludes=[]] - An array of items to exclude from the next item selection.
* @returns {T | undefined} The next item in the circular list, or undefined if all items are excluded.
*/
next(excludes?: T[]): T | undefined;
/**
* Creates a generator for iterating over items in a circular manner.
* @returns {Generator<T, T, unknown>} A generator for iterating over items in a circular manner.
*/
create(): any;
}

@@ -1,10 +0,25 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CircularList = void 0;
class CircularList {
/**
* Represents a circular list that iterates over its elements infinitely.
* @template T
*/
export class CircularList {
/** The array of items in the circular list. */
items;
/** The generator for iterating over items in a circular manner. */
gen;
/** The current index of the generator. */
index = 0;
/**
* Creates a circular list.
* @param {T[]} items - The array of items to include in the circular list.
*/
constructor(items) {
this.index = 0;
this.items = items;
this.gen = this.create();
}
/**
* Gets the next item in the circular list, excluding specified items.
* @param {T[]} [excludes=[]] - An array of items to exclude from the next item selection.
* @returns {T | undefined} The next item in the circular list, or undefined if all items are excluded.
*/
next(excludes = []) {

@@ -20,2 +35,6 @@ let item;

}
/**
* Creates a generator for iterating over items in a circular manner.
* @returns {Generator<T, T, unknown>} A generator for iterating over items in a circular manner.
*/
*create() {

@@ -30,3 +49,2 @@ while (true) {

}
exports.CircularList = CircularList;
//# sourceMappingURL=clist.js.map

@@ -1,6 +0,3 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const cli_color_1 = tslib_1.__importDefault(require("cli-color"));
exports.default = cli_color_1.default;
import color from 'cli-color';
export default color;
//# sourceMappingURL=color.node.js.map

@@ -1,400 +0,424 @@

export class HttpStatus {
statusCode: number;
body: any;
/**
* Create an HTTP error object
* @param status HTTP code
* @param body HTTP body
*/
constructor(status: number, body?: any);
clone(message: string): HttpError;
/**
* Creates an HTTP exception with the specified status code and message.
* @param {number} statusCode - The status code of the HTTP exception.
* @param {string} message - The message describing the HTTP exception.
* @param {*} [body] - The optional body of the HTTP exception.
* @returns {HttpError} The HTTP exception object.
*/
export declare function createHttpException(statusCode: number, message: string, body?: any): HttpError;
/**
* Represents an HTTP status with a status code and an optional body.
*/
export declare class HttpStatus {
/**
* The status code of the HTTP status.
* @type {number}
*/
statusCode: number;
/**
* The body of the HTTP status.
* @type {*}
*/
body: any;
/**
* Constructs an instance of HttpStatus.
* @param {number} status - The status code of the HTTP status.
* @param {*} [body=null] - The optional body of the HTTP status.
*/
constructor(status: number, body?: any);
/**
* Clones the HTTP status with a new message and body.
* @param {string} message - The new message for the cloned HTTP status.
* @param {*} [body=null] - The new body for the cloned HTTP status.
* @returns {HttpError} A new HttpError object cloned from this HTTP status with the provided message and body.
*/
clone(message: string, body: any): HttpError;
}
export class HttpError extends Error {
statusCode: number;
body: any;
/**
* Create an HTTP error object
* @param status HTTP code
* @param body HTTP body
*/
constructor(status: number, body?: any);
clone(message: string): HttpError;
/**
* Represents an HTTP error with a status code, message, and an optional body.
*/
export declare class HttpError extends Error {
/**
* The status code of the HTTP error.
* @type {number}
*/
statusCode: number;
/**
* The body of the HTTP error.
* @type {*}
*/
body: any;
/**
* Constructs an instance of HttpError.
* @param {number} status - The status code of the HTTP error.
* @param {string} message - The message describing the HTTP error.
* @param {*} [body=null] - The optional body of the HTTP error.
*/
constructor(status: number, message: string, body?: any);
/**
* Clones the HTTP error with a new message and body.
* @param {string} message - The new message for the cloned HTTP error.
* @param {*} [body=null] - The new body for the cloned HTTP error.
* @returns {HttpError} A new HttpError object cloned from this HTTP error with the provided message and body.
*/
clone(message: string, body?: any): HttpError;
}
export type Status = {
// 2xx success
/**
* Standard response for successful HTTP requests. The actual response will
* depend on the request method used. In a GET request, the response will
* contain an entity corresponding to the requested resource. In a POST
* request, the response will contain an entity describing or containing the
* result of the action.
*/
OK: HttpStatus;
/**
* The request has been fulfilled, resulting in the creation of a new
* resource.
*/
Created: HttpStatus;
/**
* The request has been accepted for processing, but the processing has not
* been completed. The request might or might not be eventually acted upon,
* and may be disallowed when processing occurs.
*/
Accepted: HttpStatus;
/**
* The server is a transforming proxy (e.g. a Web accelerator) that received
* a 200 OK from its origin, but is returning a modified version of the
* origin's response.
*/
NonAuthoritativeInformation: HttpStatus;
/**
* The server successfully processed the request, and is not returning any
* content.
*/
NoContent: HttpStatus;
/**
* The server successfully processed the request, asks that the requester
* reset its document view, and is not returning any content.
*/
ResetContent: HttpStatus;
/**
* The server is delivering only part of the resource (byte serving) due to
* a range header sent by the client. The range header is used by HTTP
* clients to enable resuming of interrupted downloads, or split a download
* into multiple simultaneous streams.
*/
PartialContent: HttpStatus;
/**
* The message body that follows is by default an XML message and can contain
* a number of separate response codes, depending on how many sub-requests
* were made.
*/
MultiStatus: HttpStatus;
/**
* The members of a DAV binding have already been enumerated in a preceding
* part of the (multistatus) response, and are not being included again
*/
AlreadyReported: HttpStatus;
/**
* The server has fulfilled a request for the resource, and the response is
* a representation of the result of one or more instance-manipulations
* applied to the current instance.
*/
IMUsed: HttpStatus;
// 3xx redirection
/**
* Indicates multiple options for the resource from which the client may
* choose (via agent-driven content negotiation). For example, this code
* could be used to present multiple video format options, to list files with
* different filename extensions, or to suggest word-sense disambiguation.
*/
MultipleChoices: HttpStatus;
/**
* This and all future requests should be directed to the given URI.
*/
MovedPermanently: HttpStatus;
/**
* Tells the client to look at (browse to) another URL. The HTTP/1.0
* specification (RFC 1945) required the client to perform a temporary
* redirect with the same method (the original describing phrase was "Moved
* Temporarily"), but popular browsers implemented 302 redirects by changing
* the method to GET. Therefore, HTTP/1.1 added status codes 303 and 307 to
* distinguish between the two behaviours.
*/
Found: HttpStatus;
/**
* The response to the request can be found under another URI using the GET
* method. When received in response to a POST (or PUT/DELETE), the client
* should presume that the server has received the data and should issue a
* new GET request to the given URI.
*/
SeeOther: HttpStatus;
/**
* Indicates that the resource has not been modified since the version specified
* by the request headers If-Modified-Since or If-None-Match. In such case,
* there is no need to retransmit the resource since the client still has a
* previously-downloaded copy.
*/
NotModified: HttpStatus;
/**
* The requested resource is available only through a proxy, the address for
* which is provided in the response. For security reasons, many HTTP clients
* (such as Mozilla Firefox and Internet Explorer) do not obey this status
* code.
*/
UseProxy: HttpStatus;
/**
* No longer used. Originally meant "Subsequent requests should use the
* specified proxy."
*/
SwitchProxy: HttpStatus;
/**
* In this case, the request should be repeated with another URI;
* however, future requests should still use the original URI.
* In contrast to how 302 was historically implemented, the request method is
* not allowed to be changed when reissuing the original request. For example,
* a POST request should be repeated using another POST request.
*/
TemporaryRedirect: HttpStatus;
/**
* This and all future requests should be directed to the given URI.
* 308 parallel the behaviour of 301, but does not allow the HTTP method to
* change. So, for example, submitting a form to a permanently redirected
* resource may continue smoothly.
*/
PermanentRedirect: HttpStatus;
// 4xx client errors
/**
* The server cannot or will not process the request due to an apparent
* client error (e.g., malformed request syntax, size too large, invalid
* request message framing, or deceptive request routing).
*/
BadRequest: HttpError;
/**
* Similar to 403 Forbidden, but specifically for use when authentication
* is required and has failed or has not yet been provided. The response
* must include a WWW-Authenticate header field containing a challenge
* applicable to the requested resource. See Basic access authentication and
* Digest access authentication. 401 semantically means "unauthorised", the
* user does not have valid authentication credentials for the target
* resource.
*/
Unauthorized: HttpError;
/**
* Reserved for future use. The original intention was that this code might
* be used as part of some form of digital cash or micropayment scheme, as
* proposed, for example, by GNU Taler, but that has not yet happened, and
* this code is not widely used. Google Developers API uses this status if
* a particular developer has exceeded the daily limit on requests. Sipgate
* uses this code if an account does not have sufficient funds to start a
* call. Shopify uses this code when the store has not paid their fees and
* is temporarily disabled. Stripe uses this code for failed payments where
* parameters were correct, for example blocked fraudulent payments.
*/
PaymentRequired: HttpError;
/**
* The request contained valid data and was understood by the server, but the
* server is refusing action. This may be due to the user not having the
* necessary permissions for a resource or needing an account of some sort,
* or attempting a prohibited action (e.g. creating a duplicate record where
* only one is allowed). This code is also typically used if the request
* provided authentication by answering the WWW-Authenticate header field
* challenge, but the server did not accept that authentication. The request
* should not be repeated.
*/
Forbidden: HttpError;
/**
* The requested resource could not be found but may be available in the
* future. Subsequent requests by the client are permissible.
*/
NotFound: HttpError;
/**
* A request method is not supported for the requested resource; for
* example, a GET request on a form that requires data to be presented via
* POST, or a PUT request on a read-only resource.
*/
MethodNotAllowed: HttpError;
/**
* The requested resource is capable of generating only content not
* acceptable according to the Accept headers sent in the request.
*/
NotAcceptable: HttpError;
/**
* The client must first authenticate itself with the proxy.
*/
ProxyAuthenticationRequired: HttpError;
/**
* The server timed out waiting for the request. According to HTTP
* specifications: "The client did not produce a request within the time that
* the server was prepared to wait. The client MAY repeat the request without
* modifications at any later time."
*/
RequestTimeout: HttpError;
/**
* Indicates that the request could not be processed because of conflict in
* the current state of the resource, such as an edit conflict between
* multiple simultaneous updates.
*/
Conflict: HttpError;
/**
* Indicates that the resource requested is no longer available and will not
* be available again. This should be used when a resource has been
* intentionally removed and the resource should be purged. Upon receiving a
* 410 status code, the client should not request the resource in the future.
* Clients such as search engines should remove the resource from their
* indices. Most use cases do not require clients and search engines to purge
* the resource, and a "404 Not Found" may be used instead.
*/
Gone: HttpError;
/**
* The request did not specify the length of its content, which is required
* by the requested resource.
*/
LengthRequired: HttpError;
/**
* The server does not meet one of the preconditions that the requester put
* on the request header fields.
*/
PreconditionFailed: HttpError;
/**
* The request is larger than the server is willing or able to process.
*/
PayloadTooLarge: HttpError;
/**
* The URI provided was too long for the server to process. Often the result
* of too much data being encoded as a query-string of a GET request, in
* which case it should be converted to a POST request.
*/
URITooLong: HttpError;
/**
* The request entity has a media type which the server or resource does not
* support. For example, the client uploads an image as image/svg+xml, but
* the server requires that images use a different format.
*/
UnsupportedMediaType: HttpError;
/**
* The client has asked for a portion of the file (byte serving), but the
* server cannot supply that portion. For example, if the client asked for
* a part of the file that lies beyond the end of the file.
*/
RangeNotSatisfiable: HttpError;
/**
* The server cannot meet the requirements of the Expect request-header
* field.
*/
ExpectationFailed: HttpError;
/**
* This code was defined in 1998 as one of the traditional IETF April Fools'
* jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, and is not
* expected to be implemented by actual HTTP servers. The RFC specifies this
* code should be returned by teapots requested to brew coffee. This HTTP
* status is used as an Easter egg in some websites, such as Google.com's
* I'm a teapot easter egg.
*/
ImATeapot: HttpError;
/**
* The request was directed at a server that is not able to produce a
* response (for example because of connection reuse).
*/
MisdirectedRequest: HttpError;
/**
* The request was well-formed but was unable to be followed due to semantic
* errors.
*/
UnprocessableEntity: HttpError;
/**
* The resource that is being accessed is locked.
*/
Locked: HttpError;
/**
* The request failed because it depended on another request and that request
* failed (e.g., a PROPPATCH).
*/
FailedDependency: HttpError;
/**
* Indicates that the server is unwilling to risk processing a request that
* might be replayed.
*/
TooEarly: HttpError;
/**
* The client should switch to a different protocol such as TLS/1.3, given in
* the Upgrade header field.
*/
UpgradeRequired: HttpError;
/**
* The origin server requires the request to be conditional. Intended to
* prevent the 'lost update' problem, where a client GETs a resource's state,
* modifies it, and PUTs it back to the server, when meanwhile a third party
* has modified the state on the server, leading to a conflict.
*/
PreconditionRequired: HttpError;
/**
* The user has sent too many requests in a given amount of time. Intended
* for use with rate-limiting schemes.
*/
TooManyRequests: HttpError;
/**
* The server is unwilling to process the request because either an
* individual header field, or all the header fields collectively, are too
* large.
*/
RequestHeaderFieldsTooLarge: HttpError;
/**
* A server operator has received a legal demand to deny access to a
* resource or to a set of resources that includes the requested resource.
* The code 451 was chosen as a reference to the novel Fahrenheit 451
*/
UnavailableForLegalReasons: HttpError;
// 5xx server errors
/**
* A generic error message, given when an unexpected condition was
* encountered and no more specific message is suitable.
*/
InternalServerError: HttpError;
/**
* The server either does not recognize the request method, or it lacks the
* ability to fulfil the request. Usually this implies future availability
* (e.g., a new feature of a web-service API).
*/
NotImplemented: HttpError;
/**
* The server was acting as a gateway or proxy and received an invalid
* response from the upstream server.
*/
BadGateway: HttpError;
/**
* The server cannot handle the request (because it is overloaded or down
* for maintenance). Generally, this is a temporary state.
*/
ServiceUnavailable: HttpError;
/**
* The server was acting as a gateway or proxy and did not receive a timely
* response from the upstream server.
*/
GatewayTimeout: HttpError;
/**
* The server does not support the HTTP protocol version used in the request.
*/
HTTPVersionNotSupported: HttpError;
/**
* Transparent content negotiation for the request results in a circular
* reference.
*/
VariantAlsoNegotiates: HttpError;
/**
* The server is unable to store the representation needed to complete the
* request.
*/
InsufficientStorage: HttpError;
/**
* The server detected an infinite loop while processing the request
* (sent instead of 208 Already Reported).
*/
LoopDetected: HttpError;
/**
* Further extensions to the request are required for the server to fulfil it
*/
NotExtended: HttpError;
/**
* The client needs to authenticate to gain network access. Intended for use
* by intercepting proxies used to control access to the network (e.g.,
* "captive portals" used to require agreement to Terms of Service before
* granting full Internet access via a Wi-Fi hotspot).
*/
NetworkAuthenticationRequired: HttpError;
export declare const HTTP: {
/**
* Standard response for successful HTTP requests. The actual response will
* depend on the request method used. In a GET request, the response will
* contain an entity corresponding to the requested resource. In a POST
* request, the response will contain an entity describing or containing the
* result of the action.
*/
OK: HttpStatus;
/**
* The request has been fulfilled, resulting in the creation of a new
* resource.
*/
Created: HttpStatus;
/**
* The request has been accepted for processing, but the processing has not
* been completed. The request might or might not be eventually acted upon,
* and may be disallowed when processing occurs.
*/
Accepted: HttpStatus;
/**
* The server is a transforming proxy (e.g. a Web accelerator) that received
* a 200 OK from its origin, but is returning a modified version of the
* origin's response.
*/
NonAuthoritativeInformation: HttpStatus;
/**
* The server successfully processed the request, and is not returning any
* content.
*/
NoContent: HttpStatus;
/**
* The server successfully processed the request, asks that the requester
* reset its document view, and is not returning any content.
*/
ResetContent: HttpStatus;
/**
* The server is delivering only part of the resource (byte serving) due to
* a range header sent by the client. The range header is used by HTTP
* clients to enable resuming of interrupted downloads, or split a download
* into multiple simultaneous streams.
*/
PartialContent: HttpStatus;
/**
* The message body that follows is by default an XML message and can contain
* a number of separate response codes, depending on how many sub-requests
* were made.
*/
MultiStatus: HttpStatus;
/**
* The members of a DAV binding have already been enumerated in a preceding
* part of the (multistatus) response, and are not being included again
*/
AlreadyReported: HttpStatus;
/**
* The server has fulfilled a request for the resource, and the response is
* a representation of the result of one or more instance-manipulations
* applied to the current instance.
*/
IMUsed: HttpStatus;
/**
* Indicates multiple options for the resource from which the client may
* choose (via agent-driven content negotiation). For example, this code
* could be used to present multiple video format options, to list files with
* different filename extensions, or to suggest word-sense disambiguation.
*/
MultipleChoices: HttpStatus;
/**
* This and all future requests should be directed to the given URI.
*/
MovedPermanently: HttpStatus;
/**
* Tells the client to look at (browse to) another URL. The HTTP/1.0
* specification (RFC 1945) required the client to perform a temporary
* redirect with the same method (the original describing phrase was "Moved
* Temporarily"), but popular browsers implemented 302 redirects by changing
* the method to GET. Therefore, HTTP/1.1 added status codes 303 and 307 to
* distinguish between the two behaviours.
*/
Found: HttpStatus;
/**
* The response to the request can be found under another URI using the GET
* method. When received in response to a POST (or PUT/DELETE), the client
* should presume that the server has received the data and should issue a
* new GET request to the given URI.
*/
SeeOther: HttpStatus;
/**
* Indicates that the resource has not been modified since the version specified
* by the request headers If-Modified-Since or If-None-Match. In such case,
* there is no need to retransmit the resource since the client still has a
* previously-downloaded copy.
*/
NotModified: HttpStatus;
/**
* The requested resource is available only through a proxy, the address for
* which is provided in the response. For security reasons, many HTTP clients
* (such as Mozilla Firefox and Internet Explorer) do not obey this status
* code.
*/
UseProxy: HttpStatus;
/**
* No longer used. Originally meant "Subsequent requests should use the
* specified proxy."
*/
SwitchProxy: HttpStatus;
/**
* In this case, the request should be repeated with another URI;
* however, future requests should still use the original URI.
* In contrast to how 302 was historically implemented, the request method is
* not allowed to be changed when reissuing the original request. For example,
* a POST request should be repeated using another POST request.
*/
TemporaryRedirect: HttpStatus;
/**
* This and all future requests should be directed to the given URI.
* 308 parallel the behaviour of 301, but does not allow the HTTP method to
* change. So, for example, submitting a form to a permanently redirected
* resource may continue smoothly.
*/
PermanentRedirect: HttpStatus;
/**
* The server cannot or will not process the request due to an apparent
* client error (e.g., malformed request syntax, size too large, invalid
* request message framing, or deceptive request routing).
*/
BadRequest: HttpError;
/**
* Similar to 403 Forbidden, but specifically for use when authentication
* is required and has failed or has not yet been provided. The response
* must include a WWW-Authenticate header field containing a challenge
* applicable to the requested resource. See Basic access authentication and
* Digest access authentication. 401 semantically means "unauthorised", the
* user does not have valid authentication credentials for the target
* resource.
*/
Unauthorized: HttpError;
/**
* Reserved for future use. The original intention was that this code might
* be used as part of some form of digital cash or micropayment scheme, as
* proposed, for example, by GNU Taler, but that has not yet happened, and
* this code is not widely used. Google Developers API uses this status if
* a particular developer has exceeded the daily limit on requests. Sipgate
* uses this code if an account does not have sufficient funds to start a
* call. Shopify uses this code when the store has not paid their fees and
* is temporarily disabled. Stripe uses this code for failed payments where
* parameters were correct, for example blocked fraudulent payments.
*/
PaymentRequired: HttpError;
/**
* The request contained valid data and was understood by the server, but the
* server is refusing action. This may be due to the user not having the
* necessary permissions for a resource or needing an account of some sort,
* or attempting a prohibited action (e.g. creating a duplicate record where
* only one is allowed). This code is also typically used if the request
* provided authentication by answering the WWW-Authenticate header field
* challenge, but the server did not accept that authentication. The request
* should not be repeated.
*/
Forbidden: HttpError;
/**
* The requested resource could not be found but may be available in the
* future. Subsequent requests by the client are permissible.
*/
NotFound: HttpError;
/**
* A request method is not supported for the requested resource; for
* example, a GET request on a form that requires data to be presented via
* POST, or a PUT request on a read-only resource.
*/
MethodNotAllowed: HttpError;
/**
* The requested resource is capable of generating only content not
* acceptable according to the Accept headers sent in the request.
*/
NotAcceptable: HttpError;
/**
* The client must first authenticate itself with the proxy.
*/
ProxyAuthenticationRequired: HttpError;
/**
* The server timed out waiting for the request. According to HTTP
* specifications: "The client did not produce a request within the time that
* the server was prepared to wait. The client MAY repeat the request without
* modifications at any later time."
*/
RequestTimeout: HttpError;
/**
* Indicates that the request could not be processed because of conflict in
* the current state of the resource, such as an edit conflict between
* multiple simultaneous updates.
*/
Conflict: HttpError;
/**
* Indicates that the resource requested is no longer available and will not
* be available again. This should be used when a resource has been
* intentionally removed and the resource should be purged. Upon receiving a
* 410 status code, the client should not request the resource in the future.
* Clients such as search engines should remove the resource from their
* indices. Most use cases do not require clients and search engines to purge
* the resource, and a "404 Not Found" may be used instead.
*/
Gone: HttpError;
/**
* The request did not specify the length of its content, which is required
* by the requested resource.
*/
LengthRequired: HttpError;
/**
* The server does not meet one of the preconditions that the requester put
* on the request header fields.
*/
PreconditionFailed: HttpError;
/**
* The request is larger than the server is willing or able to process.
*/
PayloadTooLarge: HttpError;
/**
* The URI provided was too long for the server to process. Often the result
* of too much data being encoded as a query-string of a GET request, in
* which case it should be converted to a POST request.
*/
URITooLong: HttpError;
/**
* The request entity has a media type which the server or resource does not
* support. For example, the client uploads an image as image/svg+xml, but
* the server requires that images use a different format.
*/
UnsupportedMediaType: HttpError;
/**
* The client has asked for a portion of the file (byte serving), but the
* server cannot supply that portion. For example, if the client asked for
* a part of the file that lies beyond the end of the file.
*/
RangeNotSatisfiable: HttpError;
/**
* The server cannot meet the requirements of the Expect request-header
* field.
*/
ExpectationFailed: HttpError;
/**
* This code was defined in 1998 as one of the traditional IETF April Fools'
* jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, and is not
* expected to be implemented by actual HTTP servers. The RFC specifies this
* code should be returned by teapots requested to brew coffee. This HTTP
* status is used as an Easter egg in some websites, such as Google.com's
* I'm a teapot easter egg.
*/
ImATeapot: HttpError;
/**
* The request was directed at a server that is not able to produce a
* response (for example because of connection reuse).
*/
MisdirectedRequest: HttpError;
/**
* The request was well-formed but was unable to be followed due to semantic
* errors.
*/
UnprocessableEntity: HttpError;
/**
* The resource that is being accessed is locked.
*/
Locked: HttpError;
/**
* The request failed because it depended on another request and that request
* failed (e.g., a PROPPATCH).
*/
FailedDependency: HttpError;
/**
* Indicates that the server is unwilling to risk processing a request that
* might be replayed.
*/
TooEarly: HttpError;
/**
* The client should switch to a different protocol such as TLS/1.3, given in
* the Upgrade header field.
*/
UpgradeRequired: HttpError;
/**
* The origin server requires the request to be conditional. Intended to
* prevent the 'lost update' problem, where a client GETs a resource's state,
* modifies it, and PUTs it back to the server, when meanwhile a third party
* has modified the state on the server, leading to a conflict.
*/
PreconditionRequired: HttpError;
/**
* The user has sent too many requests in a given amount of time. Intended
* for use with rate-limiting schemes.
*/
TooManyRequests: HttpError;
/**
* The server is unwilling to process the request because either an
* individual header field, or all the header fields collectively, are too
* large.
*/
RequestHeaderFieldsTooLarge: HttpError;
/**
* A server operator has received a legal demand to deny access to a
* resource or to a set of resources that includes the requested resource.
* The code 451 was chosen as a reference to the novel Fahrenheit 451
*/
UnavailableForLegalReasons: HttpError;
/**
* A generic error message, given when an unexpected condition was
* encountered and no more specific message is suitable.
*/
InternalServerError: HttpError;
/**
* The server either does not recognize the request method, or it lacks the
* ability to fulfil the request. Usually this implies future availability
* (e.g., a new feature of a web-service API).
*/
NotImplemented: HttpError;
/**
* The server was acting as a gateway or proxy and received an invalid
* response from the upstream server.
*/
BadGateway: HttpError;
/**
* The server cannot handle the request (because it is overloaded or down
* for maintenance). Generally, this is a temporary state.
*/
ServiceUnavailable: HttpError;
/**
* The server was acting as a gateway or proxy and did not receive a timely
* response from the upstream server.
*/
GatewayTimeout: HttpError;
/**
* The server does not support the HTTP protocol version used in the request.
*/
HTTPVersionNotSupported: HttpError;
/**
* Transparent content negotiation for the request results in a circular
* reference.
*/
VariantAlsoNegotiates: HttpError;
/**
* The server is unable to store the representation needed to complete the
* request.
*/
InsufficientStorage: HttpError;
/**
* The server detected an infinite loop while processing the request
* (sent instead of 208 Already Reported).
*/
LoopDetected: HttpError;
/**
* Further extensions to the request are required for the server to fulfil it
*/
NotExtended: HttpError;
/**
* The client needs to authenticate to gain network access. Intended for use
* by intercepting proxies used to control access to the network (e.g.,
* "captive portals" used to require agreement to Terms of Service before
* granting full Internet access via a Wi-Fi hotspot).
*/
NetworkAuthenticationRequired: HttpError;
};
export const HTTP: Status;

@@ -1,5 +0,32 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTTP = exports.HttpError = exports.HttpStatus = void 0;
class HttpStatus {
/**
* Creates an HTTP exception with the specified status code and message.
* @param {number} statusCode - The status code of the HTTP exception.
* @param {string} message - The message describing the HTTP exception.
* @param {*} [body] - The optional body of the HTTP exception.
* @returns {HttpError} The HTTP exception object.
*/
export function createHttpException(statusCode, message, body) {
const error = new HttpError(statusCode, body);
error.message = message;
return error;
}
/**
* Represents an HTTP status with a status code and an optional body.
*/
export class HttpStatus {
/**
* The status code of the HTTP status.
* @type {number}
*/
statusCode;
/**
* The body of the HTTP status.
* @type {*}
*/
body;
/**
* Constructs an instance of HttpStatus.
* @param {number} status - The status code of the HTTP status.
* @param {*} [body=null] - The optional body of the HTTP status.
*/
constructor(status, body = null) {

@@ -9,19 +36,48 @@ this.statusCode = status;

}
clone(message) {
return new HttpError(this.statusCode, message);
/**
* Clones the HTTP status with a new message and body.
* @param {string} message - The new message for the cloned HTTP status.
* @param {*} [body=null] - The new body for the cloned HTTP status.
* @returns {HttpError} A new HttpError object cloned from this HTTP status with the provided message and body.
*/
clone(message, body) {
return new HttpError(this.statusCode, message, body);
}
}
exports.HttpStatus = HttpStatus;
class HttpError extends Error {
constructor(status, body = null) {
super();
/**
* Represents an HTTP error with a status code, message, and an optional body.
*/
export class HttpError extends Error {
/**
* The status code of the HTTP error.
* @type {number}
*/
statusCode;
/**
* The body of the HTTP error.
* @type {*}
*/
body;
/**
* Constructs an instance of HttpError.
* @param {number} status - The status code of the HTTP error.
* @param {string} message - The message describing the HTTP error.
* @param {*} [body=null] - The optional body of the HTTP error.
*/
constructor(status, message, body = null) {
super(message);
this.statusCode = status;
this.body = body;
}
clone(message) {
return new HttpError(this.statusCode, message);
/**
* Clones the HTTP error with a new message and body.
* @param {string} message - The new message for the cloned HTTP error.
* @param {*} [body=null] - The new body for the cloned HTTP error.
* @returns {HttpError} A new HttpError object cloned from this HTTP error with the provided message and body.
*/
clone(message, body = null) {
return new HttpError(this.statusCode, message, body);
}
}
exports.HttpError = HttpError;
exports.HTTP = {
export const HTTP = {
// 2xx success

@@ -28,0 +84,0 @@ /**

@@ -1,2 +0,1 @@

import { __awaiter } from "tslib";
const EventOptions = {

@@ -8,3 +7,3 @@ once: true,

const matches = base64.match(REGEX);
if (matches === null || matches === void 0 ? void 0 : matches.length) {
if (matches?.length) {
return {

@@ -18,7 +17,5 @@ mime: matches[1],

}
export function parseBase64(image) {
return __awaiter(this, void 0, void 0, function* () {
const result = parseCanvas(image, image.width, image.height);
return result.toDataURL();
});
export async function parseBase64(image) {
const result = parseCanvas(image, image.width, image.height);
return result.toDataURL();
}

@@ -33,6 +30,4 @@ export function pull({ url }) {

}
export function resize(image, width, height) {
return __awaiter(this, void 0, void 0, function* () {
return parseCanvas(image, width, height);
});
export async function resize(image, width, height) {
return parseCanvas(image, width, height);
}

@@ -39,0 +34,0 @@ function parseCanvas(image, width, height) {

@@ -1,13 +0,10 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resize = exports.pull = exports.parseBase64 = exports.parseMimeType = void 0;
const tslib_1 = require("tslib");
const os_1 = tslib_1.__importDefault(require("os"));
const promises_1 = tslib_1.__importDefault(require("fs/promises"));
const jimp_1 = tslib_1.__importDefault(require("jimp"));
const image_downloader_1 = tslib_1.__importDefault(require("image-downloader"));
import os from 'node:os';
import fs from 'node:fs/promises';
import download from 'image-downloader';
import sharp from 'sharp';
const REGEX = /^data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+);base64,(.+)/;
function parseMimeType(base64) {
export function parseMimeType(base64) {
// Extract the content type from the Base64 URL
const matches = base64.match(REGEX);
if (matches === null || matches === void 0 ? void 0 : matches.length) {
if (matches?.length) {
return {

@@ -21,21 +18,41 @@ mime: matches[1],

}
exports.parseMimeType = parseMimeType;
async function parseBase64(filename) {
const image = await promises_1.default.readFile(filename);
export async function parseBase64(filename) {
const image = await fs.readFile(filename);
return 'data:image/jpeg;base64,' + Buffer.from(image).toString('base64');
}
exports.parseBase64 = parseBase64;
function pull({ dest = os_1.default.tmpdir(), extractFilename = true, ...options }) {
return image_downloader_1.default.image({ dest, extractFilename, ...options });
export function pull({ dest = os.tmpdir(), extractFilename = true, ...options }) {
return download.image({ dest, extractFilename, ...options });
}
exports.pull = pull;
async function resize(filename, width, height = jimp_1.default.AUTO) {
const image = await jimp_1.default.read(filename);
const newFilename = `${filename}.resized`;
await image.resize(width, height, jimp_1.default.RESIZE_BEZIER).writeAsync(newFilename);
export async function convert(input, format) {
const pipeline = sharp(input.data);
return {
filename: newFilename,
data: await pipeline.toFormat(format).toBuffer(),
contentType: `image/${format}`,
};
}
exports.resize = resize;
export async function resize(input, options) {
const pipeline = sharp(input.data);
const { width, height } = await pipeline.metadata();
if (!options.width || width > options.width || !options.height || height > options.height) {
// Resize the image only if its dimensions exceed the specified options
return {
...input,
data: await pipeline.resize(options).toBuffer(),
};
}
return input;
}
export function parseInput(input) {
if (typeof input === 'string') {
const result = parseMimeType(input);
if (!result) {
throw new Error('Unsupported content type');
}
return {
data: Buffer.from(result.data, 'base64'),
contentType: result.mime,
};
}
return input;
}
//# sourceMappingURL=image.node.js.map
{
"name": "image",
"main": "./image.node.js",
"type": "module",
"exports": "./image.node.js",
"browser": "./image.browser.js"
}

@@ -1,1 +0,7 @@

export function random(min: number, max: number): number;
/**
* Generates a random integer between the specified minimum and maximum values (inclusive).
* @param {number} min - The minimum value (inclusive).
* @param {number} max - The maximum value (inclusive).
* @returns {number} A random integer within the specified range.
*/
export declare function random(min: number, max: number): number;

@@ -1,8 +0,10 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.random = void 0;
function random(min, max) {
/**
* Generates a random integer between the specified minimum and maximum values (inclusive).
* @param {number} min - The minimum value (inclusive).
* @param {number} max - The maximum value (inclusive).
* @returns {number} A random integer within the specified range.
*/
export function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
exports.random = random;
//# sourceMappingURL=number.js.map

@@ -0,55 +1,103 @@

/**
* Represents a string value to be escaped during stringification.
*/
export declare class ToStringEscape {
readonly value: string;
constructor(value: string);
/**
* The value to be escaped during stringification.
*/
readonly value: string;
/**
* Constructs an instance of ToStringEscape.
* @param {string} value - The value to be escaped during stringification.
*/
constructor(value: string);
}
/**
*
* @param object
* @param strict Default `true`
* Checks if a value is an object.
* @param {Record<string, any>} object - The value to check.
* @param {boolean} [strict=true] - Whether to strictly check for non-array objects.
* @returns {boolean} True if the value is an object, false otherwise.
*/
export function isObject(object: object, strict?: boolean): boolean;
export function isEmpty(object: object): boolean;
export function isEqual(object1: object, object2: object): boolean;
export declare function isObject(object: Record<string, any>, strict?: boolean): boolean;
/**
* Delete all object's properties
* Checks if an object is empty (has no properties).
* @param {Record<string, any>} object - The object to check.
* @returns {boolean} True if the object is empty, false otherwise.
*/
export function clear(object: object): void;
export function copy<T extends object>(object: T): T;
export declare function isEmpty(object: Record<string, any>): boolean;
/**
* Deep assign implementation (merge)
*
* @param dest The target object — what to apply the sources' properties to
* @param src The source object(s) — objects containing the properties you want to apply
* @param [strategy='append'] The merge strategy of array properties. By default `'append'`
* Checks if two objects are deeply equal.
* @param {Record<string, any>} object1 - The first object.
* @param {Record<string, any>} object2 - The second object.
* @returns {boolean} True if the objects are deeply equal, false otherwise.
*/
export function merge<T extends object, U extends object>(
dest: T,
src: U,
strategy?: 'append' | 'replace'
): T & U;
export function get<T>(object: object, path: string): T | undefined;
export function set(object: object, path: string, value: unknown): boolean;
export function del(object: object, path: string): boolean;
export declare function isEqual(object1: Record<string, any>, object2: Record<string, any>): boolean;
/**
* Converts a JavaScript object or value to a JSON string with support of function value
*
* @param object The value to convert to a JSON string
* @param space The space argument may be used to control spacing in the final string.
* - If it is a number, successive levels in the stringification will each
* be indented by this many space characters (up to 10).
* - If it is a string, successive levels will be indented by this string
* (or the first ten characters of it).
* @returns A JSON string representing the given value with stringified functions, or undefined.
* Deletes all properties of an object.
* @param {Record<string, any>} object - The object to clear.
*/
export function toString(object: object, space?: string | number): string;
export declare function clear(object: Record<string, any>): void;
/**
* Creates a deep copy of an object.
* @template T
* @param {T} object - The object to copy.
* @returns {T} A deep copy of the object.
*/
export declare function copy<T extends Record<string, any> = Record<string, any>>(object: T): T;
/**
* Groups elements of an array by a specified key.
* @template T
* @param {T[]} list - The array to group.
* @param {keyof T | ((item: T) => string | false)} key - The key to group by.
* @returns {{ [key: string]: T[] }} An object where keys are unique values determined by the grouping key,
* and values are arrays of elements from the original array.
*/
export declare function groupBy<T>(list: T[], key: keyof T | ((item: T) => string | false)): {
[key: string]: T[];
};
/**
* Merges two objects deeply.
* @template T
* @template S
* @template Z
* @param {T} dest - The destination object to merge into.
* @param {S} src - The source object to merge from.
* @param {'append' | 'replace' | 'merge'} [strategy='append'] - The merging strategy.
* @returns {Z} The merged object.
*/
export declare function merge<T extends Record<string, any>, S extends Record<string, any> = T, Z extends Record<string, any> = T & S>(dest: T, src: S, strategy?: 'append' | 'replace' | 'merge'): Z;
/**
* Gets a value from an object at the specified path.
* @template T
* @param {Record<string, any>} object - The object to retrieve the value from.
* @param {string} path - The path to the value.
* @returns {T | undefined} The value at the specified path, or undefined if not found.
*/
export declare function get<T = unknown>(object: Record<string, any>, path: string): T | undefined;
/**
* Sets a value in an object at the specified path.
* @param {Record<string, any>} object - The object to set the value in.
* @param {string} path - The path to set the value at.
* @param {unknown} value - The value to set.
* @returns {boolean} True if the value was successfully set, false otherwise.
*/
export declare function set(object: Record<string, any>, path: string, value: unknown): boolean;
/**
* Deletes a value from an object at the specified path.
* @param {Record<string, any>} object - The object to delete the value from.
* @param {string} path - The path to delete the value from.
* @returns {boolean} True if the value was successfully deleted, false otherwise.
*/
export declare function del(object: Record<string, any>, path: string): boolean;
/**
* Converts a JavaScript object or value to a JSON string with support for
* custom stringification of functions and specified string values.
* @param {object} object - The value to convert to a JSON string.
* @param {string | number} [space] - The space argument may be used to control spacing in the final string.
* - If it is a number, successive levels in the stringification will each
* be indented by this many space characters (up to 10).
* - If it is a string, successive levels will be indented by this string
* (or the first ten characters of it).
* @returns {string} A JSON string representing the given value with stringified functions and specified string values.
*/
export declare function toString(object: object, space?: string | number): string;

@@ -1,6 +0,14 @@

"use strict";
/* eslint-disable radar/cognitive-complexity */
Object.defineProperty(exports, "__esModule", { value: true });
exports.toString = exports.del = exports.set = exports.get = exports.merge = exports.copy = exports.clear = exports.isEqual = exports.isEmpty = exports.isObject = exports.ToStringEscape = void 0;
class ToStringEscape {
/**
* Represents a string value to be escaped during stringification.
*/
export class ToStringEscape {
/**
* The value to be escaped during stringification.
*/
value;
/**
* Constructs an instance of ToStringEscape.
* @param {string} value - The value to be escaped during stringification.
*/
constructor(value) {

@@ -10,10 +18,19 @@ this.value = value;

}
exports.ToStringEscape = ToStringEscape;
function isObject(object, strict = true) {
/**
* Checks if a value is an object.
* @param {Record<string, any>} object - The value to check.
* @param {boolean} [strict=true] - Whether to strictly check for non-array objects.
* @returns {boolean} True if the value is an object, false otherwise.
*/
export function isObject(object, strict = true) {
return typeof object === 'object' && object !== null && (!strict || !Array.isArray(object));
}
exports.isObject = isObject;
function isEmpty(object) {
/**
* Checks if an object is empty (has no properties).
* @param {Record<string, any>} object - The object to check.
* @returns {boolean} True if the object is empty, false otherwise.
*/
export function isEmpty(object) {
// eslint-disable-next-line no-unreachable-loop
for (const key in object) {
for (const _key in object) {
return false;

@@ -23,4 +40,9 @@ }

}
exports.isEmpty = isEmpty;
function isEqual(object1, object2) {
/**
* Checks if two objects are deeply equal.
* @param {Record<string, any>} object1 - The first object.
* @param {Record<string, any>} object2 - The second object.
* @returns {boolean} True if the objects are deeply equal, false otherwise.
*/
export function isEqual(object1, object2) {
if (object1 === object2) {

@@ -47,7 +69,7 @@ return true;

}
exports.isEqual = isEqual;
/**
* Delete all object's properties
* Deletes all properties of an object.
* @param {Record<string, any>} object - The object to clear.
*/
function clear(object) {
export function clear(object) {
for (const key in object) {

@@ -57,4 +79,9 @@ delete object[key];

}
exports.clear = clear;
function copy(object) {
/**
* Creates a deep copy of an object.
* @template T
* @param {T} object - The object to copy.
* @returns {T} A deep copy of the object.
*/
export function copy(object) {
if (typeof object !== 'object' || object === null) {

@@ -83,7 +110,34 @@ return object;

}
exports.copy = copy;
/**
* Deep assign implementation (merge)
* Groups elements of an array by a specified key.
* @template T
* @param {T[]} list - The array to group.
* @param {keyof T | ((item: T) => string | false)} key - The key to group by.
* @returns {{ [key: string]: T[] }} An object where keys are unique values determined by the grouping key,
* and values are arrays of elements from the original array.
*/
function merge(dest, src, strategy = 'append') {
export function groupBy(list, key) {
const grouped = {};
list.forEach((item) => {
const keyValue = typeof key === 'function' ? key(item) : `${item[key]}`;
if (keyValue) {
if (!grouped[keyValue]) {
grouped[keyValue] = [];
}
grouped[keyValue].push(item);
}
});
return grouped;
}
/**
* Merges two objects deeply.
* @template T
* @template S
* @template Z
* @param {T} dest - The destination object to merge into.
* @param {S} src - The source object to merge from.
* @param {'append' | 'replace' | 'merge'} [strategy='append'] - The merging strategy.
* @returns {Z} The merged object.
*/
export function merge(dest, src, strategy = 'append') {
if (isObject(dest) && isObject(src)) {

@@ -97,6 +151,19 @@ for (const key in src) {

else if (dest[key] instanceof Array) {
if (strategy === 'replace') {
dest[key].splice(0);
if (strategy === 'merge') {
let index = 0;
for (; index < dest[key].length; index++) {
if (index < src[key].length) {
dest[key][index] = merge(dest[key][index], src[key][index], strategy);
}
}
if (index < src[key].length) {
dest[key].push(...src[key].slice(index));
}
}
dest[key].push(...copy(src[key]));
else {
if (strategy === 'replace') {
dest[key].splice(0);
}
dest[key].push(...copy(src[key]));
}
}

@@ -113,11 +180,23 @@ else {

}
exports.merge = merge;
function get(object, path) {
/**
* Gets a value from an object at the specified path.
* @template T
* @param {Record<string, any>} object - The object to retrieve the value from.
* @param {string} path - The path to the value.
* @returns {T | undefined} The value at the specified path, or undefined if not found.
*/
export function get(object, path) {
const paths = parsePath(path);
return paths.length
? foundPaths(object, paths, null, (result, o, key, val) => (result ? o[key] : undefined))
? foundPaths(object, paths, null, (result, o, key, _val) => (result ? o[key] : undefined))
: object;
}
exports.get = get;
function set(object, path, value) {
/**
* Sets a value in an object at the specified path.
* @param {Record<string, any>} object - The object to set the value in.
* @param {string} path - The path to set the value at.
* @param {unknown} value - The value to set.
* @returns {boolean} True if the value was successfully set, false otherwise.
*/
export function set(object, path, value) {
return applyPaths(object, path, value, (result, o, key, val) => {

@@ -130,5 +209,10 @@ if (result) {

}
exports.set = set;
function del(object, path) {
return applyPaths(object, path, null, (result, o, key, val) => {
/**
* Deletes a value from an object at the specified path.
* @param {Record<string, any>} object - The object to delete the value from.
* @param {string} path - The path to delete the value from.
* @returns {boolean} True if the value was successfully deleted, false otherwise.
*/
export function del(object, path) {
return applyPaths(object, path, null, (result, o, key, _val) => {
if (result) {

@@ -140,15 +224,14 @@ delete o[key];

}
exports.del = del;
/**
* Converts a JavaScript object or value to a JSON string with support of function value
*
* @param object The value to convert to a JSON string
* @param space The space argument may be used to control spacing in the final string.
* - If it is a number, successive levels in the stringification will each
* be indented by this many space characters (up to 10).
* - If it is a string, successive levels will be indented by this string
* (or the first ten characters of it).
* @returns A JSON string representing the given value with stringified functions, or undefined.
* Converts a JavaScript object or value to a JSON string with support for
* custom stringification of functions and specified string values.
* @param {object} object - The value to convert to a JSON string.
* @param {string | number} [space] - The space argument may be used to control spacing in the final string.
* - If it is a number, successive levels in the stringification will each
* be indented by this many space characters (up to 10).
* - If it is a string, successive levels will be indented by this string
* (or the first ten characters of it).
* @returns {string} A JSON string representing the given value with stringified functions and specified string values.
*/
function toString(object, space) {
export function toString(object, space) {
let index = 0;

@@ -177,3 +260,2 @@ const cache = {};

}
exports.toString = toString;
function parsePath(path) {

@@ -180,0 +262,0 @@ return path.split(/\./).filter((item) => item);

@@ -1,15 +0,22 @@

import { Trace } from './trace';
export type Options = {
timeout?: number;
interval?: number;
retries?: number;
logger?: Trace;
import type { Trace } from './trace/trace.node.js';
/**
* Options for ping function.
* @typedef {Object} PingOptions
* @property {number} [timeout=30000] - The timeout value in milliseconds.
* @property {number} [interval=10000] - The interval between retries in milliseconds.
* @property {number} [retries=3] - The number of retries.
* @property {Trace} [logger] - The logger object for logging.
*/
export type PingOptions = {
timeout?: number;
interval?: number;
retries?: number;
logger?: Trace;
};
/**
* Check if a host from the given URL can be reached
* @param url
* @param options Default `{ timeout: 30000, interval: 10000, retries: 3 }`
* Checks the availability of a service by pinging it.
* @param {string} urlString - The URL of the service.
* @param {PingOptions} [options={}] - The options for pinging.
* @returns {Promise<boolean>} A promise that resolves to true if the service is available, otherwise false.
*/
export function ping(url: string, options?: Options): Promise<boolean>;
export declare function ping(urlString: string, { timeout, interval, retries, logger }?: PingOptions): Promise<boolean>;

@@ -1,6 +0,9 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ping = void 0;
const net_1 = require("net");
function ping(urlString, { timeout = 30000, interval = 10000, retries = 3, logger } = {}) {
import { createConnection } from 'node:net';
/**
* Checks the availability of a service by pinging it.
* @param {string} urlString - The URL of the service.
* @param {PingOptions} [options={}] - The options for pinging.
* @returns {Promise<boolean>} A promise that resolves to true if the service is available, otherwise false.
*/
export function ping(urlString, { timeout = 30000, interval = 10000, retries = 3, logger } = {}) {
let count = 1;

@@ -25,12 +28,12 @@ let retrying = true;

const check = () => {
logger === null || logger === void 0 ? void 0 : logger.info(`Checking availability of service ${url.host} (${count})`);
const socket = (0, net_1.createConnection)({ host: url.hostname, port, timeout });
logger?.info(`Checking availability of service ${url.host} (${count})`);
const socket = createConnection({ host: url.hostname, port, timeout });
socket.on('connect', () => {
retrying = false;
resolve(true);
logger === null || logger === void 0 ? void 0 : logger.info(`Service ${url.host} is now available`);
logger?.info(`Service ${url.host} is now available`);
});
socket.on('timeout', () => {
socket.end();
logger === null || logger === void 0 ? void 0 : logger.warn(`Service ${url.host} is not yet available (timeout)`);
logger?.warn(`Service ${url.host} is not yet available (timeout)`);
retry();

@@ -40,3 +43,3 @@ });

socket.end();
logger === null || logger === void 0 ? void 0 : logger.warn(`Service ${url.host} is not yet available (${err.message})`);
logger?.warn(`Service ${url.host} is not yet available (${err.message})`);
retry(err);

@@ -50,3 +53,2 @@ });

}
exports.ping = ping;
//# sourceMappingURL=ping.js.map
/**
* Sequential promise execution
* Executes asynchronous functions sequentially over each item in the array and returns an array of results.
* @param {X[]} items - The array of items.
* @param {(item: X, index: number) => Promise<T>} fn - The asynchronous function to execute over each item.
* @returns {Promise<T[]>} A promise that resolves to an array of results.
* @template T, X
*/
export function chain<T, X>(items: X[], fn: (item: X, index: number) => Promise<T>): Promise<T[]>;
export declare function chain<T, X>(items: X[], fn: (item: X, index: number) => Promise<T>): Promise<T[]>;
/**
* Parallel promise execution
* Executes asynchronous functions in parallel over each item in the array and returns an array of results.
* @param {X[]} items - The array of items.
* @param {(item: X, index: number) => Promise<T>} fn - The asynchronous function to execute over each item.
* @returns {Promise<T[]>} A promise that resolves to an array of results.
* @template T, X
*/
export function all<T, X>(items: X[], fn: (item: X, index: number) => Promise<T>): Promise<T[]>;
export declare function all<T, X>(items: X[], fn: (item: X, index: number) => Promise<T>): Promise<T[]>;

@@ -1,8 +0,9 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.all = exports.chain = void 0;
/**
* Sequential promise execution
* Executes asynchronous functions sequentially over each item in the array and returns an array of results.
* @param {X[]} items - The array of items.
* @param {(item: X, index: number) => Promise<T>} fn - The asynchronous function to execute over each item.
* @returns {Promise<T[]>} A promise that resolves to an array of results.
* @template T, X
*/
async function chain(items, fn) {
export async function chain(items, fn) {
const results = [];

@@ -17,10 +18,12 @@ await items.reduce((task, item, index) => {

}
exports.chain = chain;
/**
* Parallel promise execution
* Executes asynchronous functions in parallel over each item in the array and returns an array of results.
* @param {X[]} items - The array of items.
* @param {(item: X, index: number) => Promise<T>} fn - The asynchronous function to execute over each item.
* @returns {Promise<T[]>} A promise that resolves to an array of results.
* @template T, X
*/
async function all(items, fn) {
export async function all(items, fn) {
return Promise.all(items.map((item, index) => fn(item, index)));
}
exports.all = all;
//# sourceMappingURL=promise.js.map
/**
* Get a query object from a given object
* @param object Object representing search params
* @returns string representation of query
* Converts an object into a URL-encoded query string.
* @param {Record<string, any>} object - The object to be converted into a query string.
* @returns {string} The URL-encoded query string.
*/
export function stringify(object: Record<string, any>): string;
export declare function stringify(object: Record<string, any>): string;
/**
* Parses query parameters into the appropriate types.
* @param {Record<string, any>} queryParams - The query parameters to parse.
* @returns {T} The parsed query parameters.
* @template T
*/
export declare function parseQueryParams<T>(queryParams: Record<string, any>): T;

@@ -1,4 +0,26 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringify = void 0;
/**
* Converts an object into a URL-encoded query string.
* @param {Record<string, any>} object - The object to be converted into a query string.
* @returns {string} The URL-encoded query string.
*/
export function stringify(object) {
const items = [];
pushKeyPairs(items, '', object);
return items.filter((e) => e !== '').join('&');
}
/**
* Parses query parameters into the appropriate types.
* @param {Record<string, any>} queryParams - The query parameters to parse.
* @returns {T} The parsed query parameters.
* @template T
*/
export function parseQueryParams(queryParams) {
const parsedParams = {};
for (const key in queryParams) {
if (Object.prototype.hasOwnProperty.call(queryParams, key)) {
parsedParams[key] = convertToAppropriateType(queryParams[key]);
}
}
return parsedParams;
}
function pushKeyPairs(items, keyPrefix, object) {

@@ -17,2 +39,28 @@ for (const key in object) {

}
// Recursively convert string values to appropriate types
function convertToAppropriateType(value) {
if (typeof value === 'object' && value !== null) {
// If value is an object, recursively convert its properties
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = convertToAppropriateType(value[key]);
}
}
return result;
}
if (typeof value === 'string') {
// Convert string values to appropriate types
if (value === 'true') {
return true;
}
if (value === 'false') {
return false;
}
const numValue = Number(value);
return Number.isNaN(numValue) ? value : numValue;
}
// Return other types as is
return value;
}
function getKeyValue(key, value) {

@@ -32,13 +80,2 @@ if (!isNullValue(value)) {

}
/**
* Get a query object from a given object
* @param object Object representing search params
* @returns string representation of query
*/
function stringify(object) {
const items = [];
pushKeyPairs(items, '', object);
return items.filter((e) => e !== '').join('&');
}
exports.stringify = stringify;
//# sourceMappingURL=qs.js.map
/**
* Escape a pattern for a Regex
* @param pattern String to escape
* @returns boolean The excaped string
* @see https://stackoverflow.com/a/6969486
* Escapes special characters in a string, making it suitable for use as a literal in a regular expression pattern.
* @param {string} pattern - The input pattern string.
* @returns {string} The escaped pattern string.
*/
export function escapePattern(pattern: string): string;
export declare function escapePattern(pattern: string): string;

@@ -1,14 +0,9 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.escapePattern = void 0;
/**
* Escape a pattern for a Regex
* @param pattern String to escape
* @returns boolean The excaped string
* @see https://stackoverflow.com/a/6969486
* Escapes special characters in a string, making it suitable for use as a literal in a regular expression pattern.
* @param {string} pattern - The input pattern string.
* @returns {string} The escaped pattern string.
*/
function escapePattern(pattern) {
export function escapePattern(pattern) {
return pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
exports.escapePattern = escapePattern;
//# sourceMappingURL=regex.js.map
/**
* Generate an empty value for the given schema.
* @param schema The input schema
* @param useDefault Default `false`
* Filters for objects.
*/
export function generateEmptyValue<T = unknown>(schema: Record<string, any>, useDefault?: boolean): T;
export declare const Filters: {
/**
* Checks if the item is an object.
* @param {unknown} item - The item to check.
* @returns {boolean} True if the item is an object, false otherwise.
*/
object: (item: unknown) => boolean;
};
/**
* Generates an empty value based on a schema.
* @param {Record<string, any>} schema - The schema to generate the empty value from.
* @param {boolean} [useDefault=false] - Whether to use the default value defined in the schema.
* @returns {T} The generated empty value.
*/
export declare function generateEmptyValue<T = unknown>(schema: Record<string, any>, useDefault?: boolean): T;

@@ -1,11 +0,21 @@

"use strict";
/* eslint-disable radar/cognitive-complexity */
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateEmptyValue = void 0;
const object_js_1 = require("./object.js");
const Filters = {
import { isObject, merge } from './object.js';
/**
* Filters for objects.
*/
export const Filters = {
/**
* Checks if the item is an object.
* @param {unknown} item - The item to check.
* @returns {boolean} True if the item is an object, false otherwise.
*/
object: (item) => typeof item === 'object' && item !== null,
};
function generateEmptyValue(schema, useDefault = false) {
var _a;
/**
* Generates an empty value based on a schema.
* @param {Record<string, any>} schema - The schema to generate the empty value from.
* @param {boolean} [useDefault=false] - Whether to use the default value defined in the schema.
* @returns {T} The generated empty value.
*/
export function generateEmptyValue(schema, useDefault = false) {
if (useDefault) {

@@ -25,3 +35,3 @@ if (typeof schema.default !== 'undefined') {

.filter(Filters.object)
.reduce((data, item) => (0, object_js_1.merge)(data, item), {});
.reduce((data, item) => merge(data, item), {});
}

@@ -43,3 +53,3 @@ return dataItems[0];

const propSchema = schema.properties[prop];
if ((0, object_js_1.isObject)(propSchema) && (((_a = schema.required) === null || _a === void 0 ? void 0 : _a.includes(prop)) || 'default' in propSchema || 'const' in propSchema)) {
if (isObject(propSchema) && (schema.required?.includes(prop) || 'default' in propSchema || 'const' in propSchema)) {
object[prop] = generateEmptyValue(propSchema, useDefault);

@@ -56,3 +66,2 @@ }

}
exports.generateEmptyValue = generateEmptyValue;
//# sourceMappingURL=schema.js.map

@@ -1,189 +0,82 @@

import express, { Express, Request, Response, RequestHandler, Application, Router } from 'express';
import { Trace } from './trace';
export type createApp = typeof express;
/// <reference types="node" />
/// <reference types="node" />
import type { Server as NodeServer } from 'node:http';
import type { SecureContextOptions } from 'node:tls';
import type { Express, Request, Response, RequestHandler, Application, Router } from 'express';
import type { Trace } from './trace/trace.node.js';
export type { Express, Request, Response, RequestHandler, Application, Router };
/**
* Represents an internal error with additional properties.
*/
export type InternalError = Error & {
[key: string]: any;
[key: string]: any;
};
/**
* Represents options for server initialization.
*/
export type Options = {
name: string;
version: string;
port: number;
certificat?: SecureContextOptions;
serviceDependencies?: string[];
devMode?: boolean;
name: string;
version: string;
port: number;
certificat?: SecureContextOptions;
serviceDependencies?: string[];
devMode?: boolean;
logger?: Trace;
};
/**
* Creates an Express application instance.
*/
export declare const createApp: any;
/**
* Represents a server.
*/
export declare class Server {
readonly options: Options;
readonly app: Express;
readonly trace: Trace;
static readonly parser: {
options: Options;
server: NodeServer;
app: Express;
/**
* Parse incoming requests with JSON payloads and is based on body-parser
* A collection of request body parsers.
*/
json: express.json,
static readonly parser: {
/**
* Parse incoming requests with JSON payloads and is based on body-parser
*/
json: any;
/**
* Parse incoming requests with Buffer payloads and is based on body-parser
*/
raw: any;
/**
* Parse incoming requests with text payloads and is based on body-parser
*/
text: any;
/**
* Parse incoming requests with urlencoded payloads and is based on body-parser
*/
urlencoded: any;
};
/**
* Parse incoming requests with Buffer payloads and is based on body-parser
* Creates an Express router instance.
* @returns {Router} The Express router.
*/
raw: express.raw,
static createRouter(): Router;
/**
* Parse incoming requests with text payloads and is based on body-parser
* Handles errors and sends appropriate responses.
* @param {InternalError} err - The error to handle.
* @param {Response} res - The Express response object.
* @param {Trace} [logger] - Optional logger instance.
*/
text: express.text,
static handleError(err: InternalError, res: Response, logger?: Trace): void;
/**
* Parse incoming requests with urlencoded payloads and is based on body-parser
* Constructs a new Server instance.
* @param {Options} options - The options for server initialization.
*/
urlencoded: express.urlencoded,
};
static createRouter(): Router;
static handleError(err: InternalError, res: Response, logger?: ITrace): void;
constructor(options: Options);
start(): Promise<void>;
constructor(options: Options);
protected _start(): Promise<void>;
protected _prepare(): Promise<void>;
/**
* Starts the server.
* @returns {Promise<void>} A promise that resolves when the server has started.
*/
start(): Promise<void>;
}
export interface SecureContextOptions {
/**
* Optionally override the trusted CA certificates. Default is to trust
* the well-known CAs curated by Mozilla. Mozilla's CAs are completely
* replaced when CAs are explicitly specified using this option.
*/
ca?: string | Buffer | Array<string | Buffer>;
/**
* Cert chains in PEM format. One cert chain should be provided per
* private key. Each cert chain should consist of the PEM formatted
* certificate for a provided private key, followed by the PEM
* formatted intermediate certificates (if any), in order, and not
* including the root CA (the root CA must be pre-known to the peer,
* see ca). When providing multiple cert chains, they do not have to
* be in the same order as their private keys in key. If the
* intermediate certificates are not provided, the peer will not be
* able to validate the certificate, and the handshake will fail.
*/
cert?: string | Buffer | Array<string | Buffer>;
/**
* Colon-separated list of supported signature algorithms. The list
* can contain digest algorithms (SHA256, MD5 etc.), public key
* algorithms (RSA-PSS, ECDSA etc.), combination of both (e.g
* 'RSA+SHA384') or TLS v1.3 scheme names (e.g. rsa_pss_pss_sha512).
*/
sigalgs?: string;
/**
* Cipher suite specification, replacing the default. For more
* information, see modifying the default cipher suite. Permitted
* ciphers can be obtained via tls.getCiphers(). Cipher names must be
* uppercased in order for OpenSSL to accept them.
*/
ciphers?: string;
/**
* Name of an OpenSSL engine which can provide the client certificate.
*/
clientCertEngine?: string;
/**
* PEM formatted CRLs (Certificate Revocation Lists).
*/
crl?: string | Buffer | Array<string | Buffer>;
/**
* Diffie Hellman parameters, required for Perfect Forward Secrecy. Use
* openssl dhparam to create the parameters. The key length must be
* greater than or equal to 1024 bits or else an error will be thrown.
* Although 1024 bits is permissible, use 2048 bits or larger for
* stronger security. If omitted or invalid, the parameters are
* silently discarded and DHE ciphers will not be available.
*/
dhparam?: string | Buffer;
/**
* A string describing a named curve or a colon separated list of curve
* NIDs or names, for example P-521:P-384:P-256, to use for ECDH key
* agreement. Set to auto to select the curve automatically. Use
* crypto.getCurves() to obtain a list of available curve names. On
* recent releases, openssl ecparam -list_curves will also display the
* name and description of each available elliptic curve. Default:
* tls.DEFAULT_ECDH_CURVE.
*/
ecdhCurve?: string;
/**
* Attempt to use the server's cipher suite preferences instead of the
* client's. When true, causes SSL_OP_CIPHER_SERVER_PREFERENCE to be
* set in secureOptions
*/
honorCipherOrder?: boolean;
/**
* Private keys in PEM format. PEM allows the option of private keys
* being encrypted. Encrypted keys will be decrypted with
* options.passphrase. Multiple keys using different algorithms can be
* provided either as an array of unencrypted key strings or buffers,
* or an array of objects in the form {pem: <string|buffer>[,
* passphrase: <string>]}. The object form can only occur in an array.
* object.passphrase is optional. Encrypted keys will be decrypted with
* object.passphrase if provided, or options.passphrase if it is not.
*/
key?: string | Buffer | Array<Buffer>;
/**
* Name of an OpenSSL engine to get private key from. Should be used
* together with privateKeyIdentifier.
*/
privateKeyEngine?: string;
/**
* Identifier of a private key managed by an OpenSSL engine. Should be
* used together with privateKeyEngine. Should not be set together with
* key, because both options define a private key in different ways.
*/
privateKeyIdentifier?: string;
/**
* Shared passphrase used for a single private key and/or a PFX.
*/
passphrase?: string;
/**
* PFX or PKCS12 encoded private key and certificate chain. pfx is an
* alternative to providing key and cert individually. PFX is usually
* encrypted, if it is, passphrase will be used to decrypt it. Multiple
* PFX can be provided either as an array of unencrypted PFX buffers,
* or an array of objects in the form {buf: <string|buffer>[,
* passphrase: <string>]}. The object form can only occur in an array.
* object.passphrase is optional. Encrypted PFX will be decrypted with
* object.passphrase if provided, or options.passphrase if it is not.
*/
pfx?: string | Buffer | Array<string | Buffer>;
/**
* Optionally affect the OpenSSL protocol behavior, which is not
* usually necessary. This should be used carefully if at all! Value is
* a numeric bitmask of the SSL_OP_* options from OpenSSL Options
*/
secureOptions?: number; // Value is a numeric bitmask of the `SSL_OP_*` options
/**
* Legacy mechanism to select the TLS protocol version to use, it does
* not support independent control of the minimum and maximum version,
* and does not support limiting the protocol to TLSv1.3. Use
* minVersion and maxVersion instead. The possible values are listed as
* SSL_METHODS, use the function names as strings. For example, use
* 'TLSv1_1_method' to force TLS version 1.1, or 'TLS_method' to allow
* any TLS protocol version up to TLSv1.3. It is not recommended to use
* TLS versions less than 1.2, but it may be required for
* interoperability. Default: none, see minVersion.
*/
secureProtocol?: string;
/**
* Opaque identifier used by servers to ensure session state is not
* shared between applications. Unused by clients.
*/
sessionIdContext?: string;
/**
* 48-bytes of cryptographically strong pseudo-random data.
* See Session Resumption for more information.
*/
ticketKeys?: Buffer;
/**
* The number of seconds after which a TLS session created by the
* server will no longer be resumable. See Session Resumption for more
* information. Default: 300.
*/
sessionTimeout?: number;
}

@@ -1,18 +0,47 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = exports.createApp = void 0;
const tslib_1 = require("tslib");
const http_1 = tslib_1.__importDefault(require("http"));
const https_1 = tslib_1.__importDefault(require("https"));
const express_1 = tslib_1.__importDefault(require("express"));
const morgan_1 = tslib_1.__importDefault(require("morgan"));
const body_parser_1 = tslib_1.__importDefault(require("body-parser"));
const ping_js_1 = require("./ping.js");
const trace_node_js_1 = require("./trace/trace.node.js");
const http_js_1 = require("./http.js");
const promise_js_1 = require("./promise.js");
exports.createApp = express_1.default;
class Server {
import { createServer as createHttpServer } from 'node:http';
import { createServer as createHttpsServer } from 'node:https';
import express from 'express';
import logger from 'morgan';
import bodyParser from 'body-parser';
import { ping } from './ping.js';
import { HttpError } from './http.js';
import { all } from './promise.js';
/**
* Creates an Express application instance.
*/
export const createApp = express;
/**
* Represents a server.
*/
export class Server {
options;
server;
app;
/**
* A collection of request body parsers.
*/
static parser = {
/**
* Parse incoming requests with JSON payloads and is based on body-parser
*/
json: bodyParser.json,
/**
* Parse incoming requests with Buffer payloads and is based on body-parser
*/
raw: bodyParser.raw,
/**
* Parse incoming requests with text payloads and is based on body-parser
*/
text: bodyParser.text,
/**
* Parse incoming requests with urlencoded payloads and is based on body-parser
*/
urlencoded: bodyParser.urlencoded,
};
/**
* Creates an Express router instance.
* @returns {Router} The Express router.
*/
static createRouter() {
return express_1.default.Router({
return express.Router({
strict: true,

@@ -22,12 +51,18 @@ caseSensitive: false,

}
/**
* Handles errors and sends appropriate responses.
* @param {InternalError} err - The error to handle.
* @param {Response} res - The Express response object.
* @param {Trace} [logger] - Optional logger instance.
*/
static handleError(err, res, logger) {
if (err instanceof http_js_1.HttpError) {
if (err instanceof HttpError) {
res.status(err.statusCode);
if (err.body) {
res.json({ error: err.message, body: err.body });
logger === null || logger === void 0 ? void 0 : logger.error(`${err.statusCode} - ${err.message} - Body: ${JSON.stringify(err.body)}`);
logger?.error(`${err.statusCode} - ${err.message} - Body: ${JSON.stringify(err.body)}`);
}
else {
res.json({ error: err.message });
logger === null || logger === void 0 ? void 0 : logger.error(`${err.statusCode} - ${err.message}`);
logger?.error(`${err.statusCode} - ${err.message}`);
}

@@ -38,3 +73,3 @@ }

res.json({ error: err.message });
logger === null || logger === void 0 ? void 0 : logger.error(`${err.statusCode} - ${err.message}`);
logger?.error(`${err.statusCode} - ${err.message}`);
}

@@ -44,3 +79,3 @@ else if (err.status) {

res.json({ error: err.message });
logger === null || logger === void 0 ? void 0 : logger.error(`${err.status} - ${err.message}`);
logger?.error(`${err.status} - ${err.message}`);
}

@@ -50,21 +85,26 @@ else {

res.json({ error: err.message });
logger === null || logger === void 0 ? void 0 : logger.error(`500 - ${err.message} - ${err.stack}`);
logger?.error(`500 - ${err.message} - ${err.stack}`);
}
}
/**
* Constructs a new Server instance.
* @param {Options} options - The options for server initialization.
*/
constructor(options) {
this.options = options;
this.trace = new trace_node_js_1.Trace(options.name);
this.app = (0, exports.createApp)();
this.app = createApp();
this.app.disable('x-powered-by');
const loggerFormat = options.devMode
? `:date[iso] ${options.name} HTTP - :method :url :status :response-time ms - :res[content-length]`
: `:date[iso] ${options.name} HTTP - :remote-addr - :remote-user ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"`;
this.app.use((0, morgan_1.default)(loggerFormat));
if (options.logger) {
const loggerFormat = options.devMode
? `:date[iso] ${options.name} HTTP - :method :url :status :response-time ms - :res[content-length]`
: `:date[iso] ${options.name} HTTP - :remote-addr - :remote-user ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"`;
this.app.use(logger(loggerFormat));
}
}
async _start() {
this.trace.info(`Setting ${this.options.name} server...`);
this.options.logger?.info(`Setting ${this.options.name} server...`);
this.app.disable('x-powered-by');
this.app.route('/status')
.head((req, res) => res.sendStatus(200))
.get((req, res) => res.json({
.head((_req, res) => res.sendStatus(200))
.get((_req, res) => res.json({
name: this.options.name,

@@ -77,7 +117,8 @@ version: this.options.version,

await this._prepare();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.app.use((err, req, res, next) => Server.handleError(err, res, this.trace));
this.app.use((err, _req, res, _next) => {
Server.handleError(err, res, this.options.logger);
});
this.server = this.options.certificat
? https_1.default.createServer(this.options.certificat, this.app)
: http_1.default.createServer(this.app);
? createHttpsServer(this.options.certificat, this.app)
: createHttpServer(this.app);
this.server.on('error', (error) => {

@@ -90,6 +131,6 @@ if (error.syscall !== 'listen') {

case 'EACCES':
this.trace.error(`${this.options.port} requires elevated privileges`);
this.options.logger?.error(`${this.options.port} requires elevated privileges`);
process.exit(-3);
case 'EADDRINUSE':
this.trace.error(`${this.options.port} is already in use`);
this.options.logger?.error(`${this.options.port} is already in use`);
process.exit(-4);

@@ -100,4 +141,4 @@ default:

});
this.server.on('listening', () => this.trace.info(`Listening on ${this.options.port}`));
this.trace.info(`Starting ${this.options.name} server...`);
this.server.on('listening', () => this.options.logger?.info(`Listening on ${this.options.port}`));
this.options.logger?.info(`Starting ${this.options.name} server...`);
this.server.listen(this.options.port, '0.0.0.0');

@@ -107,15 +148,19 @@ process.on('SIGINT', () => this.server.close(() => process.exit(0)));

async _prepare() { }
/**
* Starts the server.
* @returns {Promise<void>} A promise that resolves when the server has started.
*/
async start() {
if (this.options.serviceDependencies instanceof Array) {
try {
await (0, promise_js_1.all)(this.options.serviceDependencies, (dependency) => (0, ping_js_1.ping)(dependency, {
await all(this.options.serviceDependencies, (dependency) => ping(dependency, {
timeout: 5000,
interval: this.options.devMode ? 3000 : 5000,
retries: this.options.devMode ? Number.MAX_SAFE_INTEGER : 10,
logger: this.trace,
logger: this.options.logger,
}));
}
catch (err) {
this.trace.error(err.message);
this.trace.error('Starting aborted');
this.options.logger?.error(err.message);
this.options.logger?.error('Starting aborted');
process.exit(-5);

@@ -127,9 +172,2 @@ }

}
exports.Server = Server;
Server.parser = {
json: body_parser_1.default.json,
raw: body_parser_1.default.raw,
text: body_parser_1.default.text,
urlencoded: body_parser_1.default.urlencoded,
};
//# sourceMappingURL=server.js.map

@@ -0,9 +1,32 @@

/**
* Trims each line in a string and joins them using the specified separator.
* @param {string} str - The input string containing lines to trim.
* @param {string} [separator=''] - The separator to use when joining trimmed lines.
* @returns {string} The trimmed and joined string.
*/
export declare function trimlines(str: string, separator?: string): string;
export type ParseCaseOptions = {
escapedChars?: string[];
separator: string;
escapedChars?: string[];
separator: string;
};
export function trimlines(str: string, separator?: string): string;
export function parseCase(str: string, options: ParseCaseOptions): string;
export function toKebabCase(str: string, escapedChars?: string[]): string;
export function unCamelCase(str: string, escapedChars?: string[]): string;
/**
* Parses a string into a specified case format.
* @param {string} str - The input string to parse.
* @param {ParseCaseOptions} options - The options for parsing.
* @returns {string} The parsed string.
*/
export declare function parseCase(str: string, { escapedChars, separator }: ParseCaseOptions): string;
/**
* Converts a string to kebab case.
* @param {string} str - The input string to convert.
* @param {string[]} [escapedChars=[]] - The characters to escape from conversion.
* @returns {string} The string converted to kebab case.
*/
export declare function toKebabCase(str: string, escapedChars?: string[]): string;
/**
* Converts a camel case string to a space-separated string.
* @param {string} str - The camel case string to convert.
* @param {string[]} [escapedChars=[]] - The characters to escape from conversion.
* @returns {string} The camel case string converted to space-separated string.
*/
export declare function unCamelCase(str: string, escapedChars?: string[]): string;

@@ -1,4 +0,1 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unCamelCase = exports.toKebabCase = exports.parseCase = exports.trimlines = void 0;
const RE_TRIMLINES = /(.+)(\n|\r\n)?/g;

@@ -13,4 +10,9 @@ const CHAR_CODE_0 = '0'.charCodeAt(0);

const CHAR_CODE_Z = 'Z'.charCodeAt(0);
const KEBAB_SEPARATOR = '-';
function trimlines(str, separator = '') {
/**
* Trims each line in a string and joins them using the specified separator.
* @param {string} str - The input string containing lines to trim.
* @param {string} [separator=''] - The separator to use when joining trimmed lines.
* @returns {string} The trimmed and joined string.
*/
export function trimlines(str, separator = '') {
let index = 0;

@@ -28,3 +30,2 @@ const output = [];

}
exports.trimlines = trimlines;
function isLowerCode(code) {

@@ -38,4 +39,10 @@ // eslint-disable-next-line camelcase

}
/**
* Parses a string into a specified case format.
* @param {string} str - The input string to parse.
* @param {ParseCaseOptions} options - The options for parsing.
* @returns {string} The parsed string.
*/
// eslint-disable-next-line radar/cognitive-complexity
function parseCase(str, { escapedChars = [], separator }) {
export function parseCase(str, { escapedChars = [], separator }) {
let output = '';

@@ -71,11 +78,20 @@ for (let index = 0; index < str.length; index++) {

}
exports.parseCase = parseCase;
function toKebabCase(str, escapedChars = []) {
/**
* Converts a string to kebab case.
* @param {string} str - The input string to convert.
* @param {string[]} [escapedChars=[]] - The characters to escape from conversion.
* @returns {string} The string converted to kebab case.
*/
export function toKebabCase(str, escapedChars = []) {
return parseCase(str, { escapedChars, separator: '-' });
}
exports.toKebabCase = toKebabCase;
function unCamelCase(str, escapedChars = []) {
/**
* Converts a camel case string to a space-separated string.
* @param {string} str - The camel case string to convert.
* @param {string[]} [escapedChars=[]] - The characters to escape from conversion.
* @returns {string} The camel case string converted to space-separated string.
*/
export function unCamelCase(str, escapedChars = []) {
return parseCase(str, { escapedChars, separator: ' ' });
}
exports.unCamelCase = unCamelCase;
//# sourceMappingURL=string.js.map
{
"name": "trace",
"main": "./trace.node.js",
"type": "module",
"exports": "./trace.node.js",
"browser": "./trace.browser.js"
}
/* eslint-disable no-console */
export class Trace {
prefix;
constructor(prefix) {

@@ -14,3 +15,3 @@ this.prefix = prefix;

warn(msg, prefix = 'WARN') {
console.info(this.parse(prefix, msg));
console.warn(this.parse(prefix, msg));
}

@@ -20,3 +21,6 @@ error(msg, prefix = 'ERROR') {

}
debug(msg, prefix = 'DEBUG') {
console.log(this.parse(prefix, msg));
}
}
//# sourceMappingURL=trace.browser.js.map

@@ -1,7 +0,4 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Trace = void 0;
const tslib_1 = require("tslib");
const color_node_1 = tslib_1.__importDefault(require("../color/color.node"));
class Trace {
import color from '../color/color.node.js';
export class Trace {
prefix;
constructor(prefix) {

@@ -18,9 +15,11 @@ this.prefix = prefix;

warn(msg, prefix = 'WARN') {
process.stderr.write(this.parse(color_node_1.default.yellow(prefix), msg));
process.stderr.write(this.parse(color.yellow(prefix), msg));
}
error(msg, prefix = 'ERROR') {
process.stderr.write(this.parse(color_node_1.default.red(prefix), msg));
process.stderr.write(this.parse(color.red(prefix), msg));
}
debug(msg, prefix = 'DEBUG') {
process.stderr.write(this.parse(color.cyan(prefix), msg));
}
}
exports.Trace = Trace;
//# sourceMappingURL=trace.node.js.map
{
"name": "@b613/utils",
"version": "1.0.0-beta24",
"version": "1.0.0-beta25",
"description": "Set of utility methods for common operations",
"license": "MIT",
"type": "commonjs",
"type": "module",
"types": "./typings.d.ts",
"exports": {
"./package.json": "./package.json",
"./lib/array": {
"import": "./lib/array.js",
"types": "./lib/array.d.ts"
},
"./lib/client": {
"import": "./lib/client.js",
"types": "./lib/client.d.ts"
},
"./lib/clist": {
"import": "./lib/clist.js",
"types": "./lib/clist.d.ts"
},
"./lib/http": {
"import": "./lib/http.js",
"types": "./lib/http.d.ts"
},
"./lib/image": {
"import": "./lib/image/image.browser.js",
"node": "./lib/image/image.node.js",
"types": "./lib/image/image.node.d.ts"
},
"./lib/json": {
"import": "./lib/json.js",
"types": "./lib/json.d.ts"
},
"./lib/number": {
"import": "./lib/number.js",
"types": "./lib/number.d.ts"
},
"./lib/object": {
"import": "./lib/object.js",
"types": "./lib/object.d.ts"
},
"./lib/ping": {
"import": "./lib/ping.js",
"types": "./lib/ping.d.ts"
},
"./lib/promise": {
"import": "./lib/promise.js",
"types": "./lib/promise.d.ts"
},
"./lib/qs": {
"import": "./lib/qs.js",
"types": "./lib/qs.d.ts"
},
"./lib/regex": {
"import": "./lib/regex.js",
"types": "./lib/regex.d.ts"
},
"./lib/schema": {
"import": "./lib/schema.js",
"types": "./lib/schema.d.ts"
},
"./lib/server": {
"import": "./lib/server.js",
"types": "./lib/server.d.ts"
},
"./lib/string": {
"import": "./lib/string.js",
"types": "./lib/string.d.ts"
},
"./lib/color": {
"import": "./lib/color/color.browser.js",
"node": "./lib/color/color.node.js",
"types": "./lib/color/color.node.d.ts"
},
"./lib/trace": {
"import": "./lib/trace/trace.browser.js",
"node": "./lib/trace/trace.node.js",
"types": "./lib/trace/trace.node.d.ts"
}
},
"files": [
"lib",
"typings.d.ts"
],
"scripts": {
"lint": "eslint .",
"test": "NODE_OPTIONS=--experimental-vm-modules node_modules/.bin/jest --coverage",
"watch": "NODE_OPTIONS=--experimental-vm-modules node_modules/.bin/jest --no-coverage --watchAll",
"build": "tsc && tsc -p tsconfig.browser.json && cp src/*.d.ts lib/"
"test": "vitest --coverage",
"watch": "vitest",
"build": "rm -rf lib && tsc && node exports.js"
},

@@ -39,4 +118,2 @@ "repository": {

"peerDependencies": {
"axios": "^1.3.3",
"axios-cache-adapter": "^2.7.3",
"body-parser": "^1.20.1",

@@ -46,4 +123,4 @@ "cli-color": "^2.0.3",

"image-downloader": "^4.3.0",
"jimp": "^0.16.1",
"morgan": "^1.10.0"
"morgan": "^1.10.0",
"sharp": "^0.33.2"
},

@@ -53,3 +130,2 @@ "devDependencies": {

"@types/express": "^4.17.13",
"@types/jest": "^29.4.0",
"@types/morgan": "^1.9.3",

@@ -59,4 +135,4 @@ "@types/node": "^18.0.0",

"@typescript-eslint/parser": "^5.21.0",
"axios": "^1.3.3",
"axios-cache-adapter": "^2.7.3",
"@vitest/coverage-v8": "^1.4.0",
"@vitest/ui": "^1.4.0",
"body-parser": "^1.20.1",

@@ -67,16 +143,14 @@ "cli-color": "^2.0.3",

"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-radar": "^0.2.1",
"express": "^4.18.1",
"image-downloader": "^4.3.0",
"jest": "^29.4.3",
"jimp": "^0.16.1",
"morgan": "^1.10.0",
"nock": "^13.2.4",
"ts-jest": "^29.0.5",
"typescript": "^4.6.4"
"sharp": "^0.33.2",
"typescript": "^5.2.2",
"vitest": "^1.4.0"
},
"engines": {
"node": ">=16.6"
"node": ">=18.18.2"
}
}
}

@@ -21,5 +21,4 @@ # Common Utils

| ------------------------- | -------------------------------------------------- |
| `@b613/utils/lib/client` | `npm install axios axios-cache-adapter` |
| `@b613/utils/lib/color` | `npm install cli-color` (only for Node.js usage) |
| `@b613/utils/lib/image` | `npm install image-downloader jimp` |
| `@b613/utils/lib/image` | `npm install image-downloader sharp` |
| `@b613/utils/lib/server` | `npm install body-parser express morgan` |

@@ -51,3 +50,3 @@ | `@b613/utils/lib/trace` | `npm install cli-color` (only for Node.js usage) |

1. [Install Nix Package Manager](https://nixos.org/manual/nix/stable/installation/installing-binary.html)
1. [Install The Determinate Nix Installer](https://github.com/DeterminateSystems/nix-installer)

@@ -58,4 +57,6 @@ 2. [Install `direnv` with your OS package manager](https://direnv.net/docs/installation.html#from-system-packages)

4. At the top-level of your project run:
4. **Load environment**
At the top-level of your project run:
```sh

@@ -65,5 +66,17 @@ direnv allow

The next time your launch your terminal and enter the top-level of your
project, `direnv` will check for changes.
5. **Install dependencies**
```sh
make install
```
6. **Start dev environment**
```sh
make env
```
This will starts a preconfigured Tmux session.
Please see the [.tmuxinator.yml](.tmuxinator.yml) file.
## License

@@ -70,0 +83,0 @@

/* eslint-disable max-len */
export type Nullable<T> = T | null;
type Nullable<T> = T | null;
export type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];
type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];
// Create a type that generates a union of prefixed keys
type PrefixedKeys<T, Prefix extends string> = {
[K in keyof T as `${Prefix}${Extract<K, string | number>}`]: K;
};
// type ReturnTypeAsync<T> = ReturnType<T extends (...args: any[]) => Promise<infer U> ? () => U : T>;
type ReturnTypeAsync<T extends (...args: any) => any> = ReturnType<T extends (...args: any[]) => Promise<infer U> ? () => U : T>;
/**

@@ -12,3 +20,3 @@ * ObjectKeyPaths declaration

? never
: T extends [infer F]
: T extends [infer F extends string | number | bigint | boolean | null | undefined]
? `${Prefix}${F}`

@@ -29,5 +37,5 @@ : T extends [infer F, ...infer R]

export type LeafPath<T> = LeafPathTree<T>[keyof LeafPathTree<T>];
type LeafPath<T> = LeafPathTree<T>[keyof LeafPathTree<T>];
export type ObjectKeyPaths<T, Prefix extends string = ''> = Join<LeafPath<T>, '.', Prefix>;
type ObjectKeyPaths<T, Prefix extends string = ''> = Join<LeafPath<T>, '.', Prefix>;

@@ -41,3 +49,3 @@ type ObjectKeysTree<T> = {

*/
export type ObjectKeys<T> = ObjectKeysTree<T>[keyof ObjectKeysTree<T>];
type ObjectKeys<T> = ObjectKeysTree<T>[keyof ObjectKeysTree<T>];

@@ -51,5 +59,5 @@ type ObjectKeysArrayTree<T> = {

*/
export type ObjectKeysArray<T> = ObjectKeysArrayTree<T>[keyof ObjectKeysArrayTree<T>];
type ObjectKeysArray<T> = ObjectKeysArrayTree<T>[keyof ObjectKeysArrayTree<T>];
export type JoinArray<T extends unknown[], Separator extends string, Prefix extends string, Suffix extends unknown | unknown[]> = T extends []
type JoinArray<T extends unknown[], Separator extends string, Prefix extends string, Suffix extends unknown | unknown[]> = T extends []
? never

@@ -81,2 +89,2 @@ : T extends [infer F]

export type KebabKeys<T> = { [K in keyof T as K extends string ? Kebab<K> : K]: T[K] };
type KebabKeys<T> = { [K in keyof T as K extends string ? Kebab<K> : K]: T[K] };

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc