WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
const { Writable } = require('node:stream')
|
||||
|
||||
module.exports = (options) => {
|
||||
const myTransportStream = new Writable({
|
||||
autoDestroy: true,
|
||||
write (chunk, enc, cb) {
|
||||
// apply a transform and send to stdout
|
||||
console.log(chunk.toString().toUpperCase())
|
||||
cb()
|
||||
}
|
||||
})
|
||||
return myTransportStream
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import type {WriteStream} from 'node:tty';
|
||||
|
||||
export type Options = {
|
||||
/**
|
||||
Whether `process.argv` should be sniffed for `--color` and `--no-color` flags.
|
||||
|
||||
@default true
|
||||
*/
|
||||
readonly sniffFlags?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
Levels:
|
||||
- `0` - All colors disabled.
|
||||
- `1` - Basic 16 colors support.
|
||||
- `2` - ANSI 256 colors support.
|
||||
- `3` - Truecolor 16 million colors support.
|
||||
*/
|
||||
export type ColorSupportLevel = 0 | 1 | 2 | 3;
|
||||
|
||||
/**
|
||||
Detect whether the terminal supports color.
|
||||
*/
|
||||
export type ColorSupport = {
|
||||
/**
|
||||
The color level.
|
||||
*/
|
||||
level: ColorSupportLevel;
|
||||
|
||||
/**
|
||||
Whether basic 16 colors are supported.
|
||||
*/
|
||||
hasBasic: boolean;
|
||||
|
||||
/**
|
||||
Whether ANSI 256 colors are supported.
|
||||
*/
|
||||
has256: boolean;
|
||||
|
||||
/**
|
||||
Whether Truecolor 16 million colors are supported.
|
||||
*/
|
||||
has16m: boolean;
|
||||
};
|
||||
|
||||
export type ColorInfo = ColorSupport | false;
|
||||
|
||||
export function createSupportsColor(stream?: WriteStream, options?: Options): ColorInfo;
|
||||
|
||||
declare const supportsColor: {
|
||||
stdout: ColorInfo;
|
||||
stderr: ColorInfo;
|
||||
};
|
||||
|
||||
export default supportsColor;
|
||||
@@ -0,0 +1,21 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference lib="esnext.temporal" />
|
||||
|
||||
interface Date {
|
||||
toTemporalInstant(): Temporal.Instant;
|
||||
}
|
||||
@@ -0,0 +1,820 @@
|
||||
/**
|
||||
* @fileoverview Rule to specify spacing of object literal keys and values
|
||||
* @author Brandon Mills
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { getGraphemeCount } = require("../shared/string-utils");
|
||||
|
||||
/**
|
||||
* Checks whether a string contains a line terminator as defined in
|
||||
* https://262.ecma-international.org/5.1/#sec-7.3
|
||||
* @param {string} str String to test.
|
||||
* @returns {boolean} True if str contains a line terminator.
|
||||
*/
|
||||
function containsLineTerminator(str) {
|
||||
return astUtils.LINEBREAK_MATCHER.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last element of an array.
|
||||
* @param {Array} arr An array.
|
||||
* @returns {any} Last element of arr.
|
||||
*/
|
||||
function last(arr) {
|
||||
return arr.at(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is contained on a single line.
|
||||
* @param {ASTNode} node AST Node being evaluated.
|
||||
* @returns {boolean} True if the node is a single line.
|
||||
*/
|
||||
function isSingleLine(node) {
|
||||
return node.loc.end.line === node.loc.start.line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the properties on a single line.
|
||||
* @param {ASTNode[]} properties List of Property AST nodes.
|
||||
* @returns {boolean} True if all properties is on a single line.
|
||||
*/
|
||||
function isSingleLineProperties(properties) {
|
||||
const [firstProp] = properties,
|
||||
lastProp = last(properties);
|
||||
|
||||
return firstProp.loc.start.line === lastProp.loc.end.line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a single option property from the configuration with defaults for undefined values
|
||||
* @param {Object} toOptions Object to be initialized
|
||||
* @param {Object} fromOptions Object to be initialized from
|
||||
* @returns {Object} The object with correctly initialized options and values
|
||||
*/
|
||||
function initOptionProperty(toOptions, fromOptions) {
|
||||
toOptions.mode = fromOptions.mode || "strict";
|
||||
|
||||
// Set value of beforeColon
|
||||
if (typeof fromOptions.beforeColon !== "undefined") {
|
||||
toOptions.beforeColon = +fromOptions.beforeColon;
|
||||
} else {
|
||||
toOptions.beforeColon = 0;
|
||||
}
|
||||
|
||||
// Set value of afterColon
|
||||
if (typeof fromOptions.afterColon !== "undefined") {
|
||||
toOptions.afterColon = +fromOptions.afterColon;
|
||||
} else {
|
||||
toOptions.afterColon = 1;
|
||||
}
|
||||
|
||||
// Set align if exists
|
||||
if (typeof fromOptions.align !== "undefined") {
|
||||
if (typeof fromOptions.align === "object") {
|
||||
toOptions.align = fromOptions.align;
|
||||
} else {
|
||||
// "string"
|
||||
toOptions.align = {
|
||||
on: fromOptions.align,
|
||||
mode: toOptions.mode,
|
||||
beforeColon: toOptions.beforeColon,
|
||||
afterColon: toOptions.afterColon,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return toOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all the option values (singleLine, multiLine and align) from the configuration with defaults for undefined values
|
||||
* @param {Object} toOptions Object to be initialized
|
||||
* @param {Object} fromOptions Object to be initialized from
|
||||
* @returns {Object} The object with correctly initialized options and values
|
||||
*/
|
||||
function initOptions(toOptions, fromOptions) {
|
||||
if (typeof fromOptions.align === "object") {
|
||||
// Initialize the alignment configuration
|
||||
toOptions.align = initOptionProperty({}, fromOptions.align);
|
||||
toOptions.align.on = fromOptions.align.on || "colon";
|
||||
toOptions.align.mode = fromOptions.align.mode || "strict";
|
||||
|
||||
toOptions.multiLine = initOptionProperty(
|
||||
{},
|
||||
fromOptions.multiLine || fromOptions,
|
||||
);
|
||||
toOptions.singleLine = initOptionProperty(
|
||||
{},
|
||||
fromOptions.singleLine || fromOptions,
|
||||
);
|
||||
} else {
|
||||
// string or undefined
|
||||
toOptions.multiLine = initOptionProperty(
|
||||
{},
|
||||
fromOptions.multiLine || fromOptions,
|
||||
);
|
||||
toOptions.singleLine = initOptionProperty(
|
||||
{},
|
||||
fromOptions.singleLine || fromOptions,
|
||||
);
|
||||
|
||||
// If alignment options are defined in multiLine, pull them out into the general align configuration
|
||||
if (toOptions.multiLine.align) {
|
||||
toOptions.align = {
|
||||
on: toOptions.multiLine.align.on,
|
||||
mode:
|
||||
toOptions.multiLine.align.mode || toOptions.multiLine.mode,
|
||||
beforeColon: toOptions.multiLine.align.beforeColon,
|
||||
afterColon: toOptions.multiLine.align.afterColon,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return toOptions;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "key-spacing",
|
||||
url: "https://eslint.style/rules/key-spacing",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Enforce consistent spacing between keys and values in object literal properties",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/key-spacing",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: [
|
||||
{
|
||||
anyOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
align: {
|
||||
anyOf: [
|
||||
{
|
||||
enum: ["colon", "value"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
on: {
|
||||
enum: ["colon", "value"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
singleLine: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
multiLine: {
|
||||
type: "object",
|
||||
properties: {
|
||||
align: {
|
||||
anyOf: [
|
||||
{
|
||||
enum: ["colon", "value"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: [
|
||||
"strict",
|
||||
"minimum",
|
||||
],
|
||||
},
|
||||
on: {
|
||||
enum: [
|
||||
"colon",
|
||||
"value",
|
||||
],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
singleLine: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
multiLine: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
align: {
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
enum: ["strict", "minimum"],
|
||||
},
|
||||
on: {
|
||||
enum: ["colon", "value"],
|
||||
},
|
||||
beforeColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
afterColon: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
extraKey: "Extra space after {{computed}}key '{{key}}'.",
|
||||
extraValue:
|
||||
"Extra space before value for {{computed}}key '{{key}}'.",
|
||||
missingKey: "Missing space after {{computed}}key '{{key}}'.",
|
||||
missingValue:
|
||||
"Missing space before value for {{computed}}key '{{key}}'.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
/**
|
||||
* OPTIONS
|
||||
* "key-spacing": [2, {
|
||||
* beforeColon: false,
|
||||
* afterColon: true,
|
||||
* align: "colon" // Optional, or "value"
|
||||
* }
|
||||
*/
|
||||
const options = context.options[0] || {},
|
||||
ruleOptions = initOptions({}, options),
|
||||
multiLineOptions = ruleOptions.multiLine,
|
||||
singleLineOptions = ruleOptions.singleLine,
|
||||
alignmentOptions = ruleOptions.align || null;
|
||||
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Determines if the given property is key-value property.
|
||||
* @param {ASTNode} property Property node to check.
|
||||
* @returns {boolean} Whether the property is a key-value property.
|
||||
*/
|
||||
function isKeyValueProperty(property) {
|
||||
return !(
|
||||
property.method ||
|
||||
property.shorthand ||
|
||||
property.kind !== "init" ||
|
||||
property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadElement"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting from the given node (a property.key node here) looks forward
|
||||
* until it finds the colon punctuator and returns it.
|
||||
* @param {ASTNode} node The node to start looking from.
|
||||
* @returns {ASTNode} The colon punctuator.
|
||||
*/
|
||||
function getNextColon(node) {
|
||||
return sourceCode.getTokenAfter(node, astUtils.isColonToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting from the given node (a property.key node here) looks forward
|
||||
* until it finds the last token before a colon punctuator and returns it.
|
||||
* @param {ASTNode} node The node to start looking from.
|
||||
* @returns {ASTNode} The last token before a colon punctuator.
|
||||
*/
|
||||
function getLastTokenBeforeColon(node) {
|
||||
const colonToken = getNextColon(node);
|
||||
|
||||
return sourceCode.getTokenBefore(colonToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting from the given node (a property.key node here) looks forward
|
||||
* until it finds the first token after a colon punctuator and returns it.
|
||||
* @param {ASTNode} node The node to start looking from.
|
||||
* @returns {ASTNode} The first token after a colon punctuator.
|
||||
*/
|
||||
function getFirstTokenAfterColon(node) {
|
||||
const colonToken = getNextColon(node);
|
||||
|
||||
return sourceCode.getTokenAfter(colonToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a property is a member of the property group it follows.
|
||||
* @param {ASTNode} lastMember The last Property known to be in the group.
|
||||
* @param {ASTNode} candidate The next Property that might be in the group.
|
||||
* @returns {boolean} True if the candidate property is part of the group.
|
||||
*/
|
||||
function continuesPropertyGroup(lastMember, candidate) {
|
||||
const groupEndLine = lastMember.loc.start.line,
|
||||
candidateValueStartLine = (
|
||||
isKeyValueProperty(candidate)
|
||||
? getFirstTokenAfterColon(candidate.key)
|
||||
: candidate
|
||||
).loc.start.line;
|
||||
|
||||
if (candidateValueStartLine - groupEndLine <= 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the first comment is adjacent to the end of the group, the
|
||||
* last comment is adjacent to the candidate property, and that successive
|
||||
* comments are adjacent to each other.
|
||||
*/
|
||||
const leadingComments = sourceCode.getCommentsBefore(candidate);
|
||||
|
||||
if (
|
||||
leadingComments.length &&
|
||||
leadingComments[0].loc.start.line - groupEndLine <= 1 &&
|
||||
candidateValueStartLine - last(leadingComments).loc.end.line <=
|
||||
1
|
||||
) {
|
||||
for (let i = 1; i < leadingComments.length; i++) {
|
||||
if (
|
||||
leadingComments[i].loc.start.line -
|
||||
leadingComments[i - 1].loc.end.line >
|
||||
1
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object literal property's key as the identifier name or string value.
|
||||
* @param {ASTNode} property Property node whose key to retrieve.
|
||||
* @returns {string} The property's key.
|
||||
*/
|
||||
function getKey(property) {
|
||||
const key = property.key;
|
||||
|
||||
if (property.computed) {
|
||||
return sourceCode.getText().slice(key.range[0], key.range[1]);
|
||||
}
|
||||
return astUtils.getStaticPropertyName(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an appropriately-formatted error if spacing is incorrect on one
|
||||
* side of the colon.
|
||||
* @param {ASTNode} property Key-value pair in an object literal.
|
||||
* @param {string} side Side being verified - either "key" or "value".
|
||||
* @param {string} whitespace Actual whitespace string.
|
||||
* @param {number} expected Expected whitespace length.
|
||||
* @param {string} mode Value of the mode as "strict" or "minimum"
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(property, side, whitespace, expected, mode) {
|
||||
const diff = whitespace.length - expected;
|
||||
|
||||
if (
|
||||
((diff && mode === "strict") ||
|
||||
(diff < 0 && mode === "minimum") ||
|
||||
(diff > 0 && !expected && mode === "minimum")) &&
|
||||
!(expected && containsLineTerminator(whitespace))
|
||||
) {
|
||||
const nextColon = getNextColon(property.key),
|
||||
tokenBeforeColon = sourceCode.getTokenBefore(nextColon, {
|
||||
includeComments: true,
|
||||
}),
|
||||
tokenAfterColon = sourceCode.getTokenAfter(nextColon, {
|
||||
includeComments: true,
|
||||
}),
|
||||
isKeySide = side === "key",
|
||||
isExtra = diff > 0,
|
||||
diffAbs = Math.abs(diff),
|
||||
spaces = Array(diffAbs + 1).join(" ");
|
||||
|
||||
const locStart = isKeySide
|
||||
? tokenBeforeColon.loc.end
|
||||
: nextColon.loc.start;
|
||||
const locEnd = isKeySide
|
||||
? nextColon.loc.start
|
||||
: tokenAfterColon.loc.start;
|
||||
const missingLoc = isKeySide
|
||||
? tokenBeforeColon.loc
|
||||
: tokenAfterColon.loc;
|
||||
const loc = isExtra
|
||||
? { start: locStart, end: locEnd }
|
||||
: missingLoc;
|
||||
|
||||
let fix;
|
||||
|
||||
if (isExtra) {
|
||||
let range;
|
||||
|
||||
// Remove whitespace
|
||||
if (isKeySide) {
|
||||
range = [
|
||||
tokenBeforeColon.range[1],
|
||||
tokenBeforeColon.range[1] + diffAbs,
|
||||
];
|
||||
} else {
|
||||
range = [
|
||||
tokenAfterColon.range[0] - diffAbs,
|
||||
tokenAfterColon.range[0],
|
||||
];
|
||||
}
|
||||
fix = function (fixer) {
|
||||
return fixer.removeRange(range);
|
||||
};
|
||||
} else {
|
||||
// Add whitespace
|
||||
if (isKeySide) {
|
||||
fix = function (fixer) {
|
||||
return fixer.insertTextAfter(
|
||||
tokenBeforeColon,
|
||||
spaces,
|
||||
);
|
||||
};
|
||||
} else {
|
||||
fix = function (fixer) {
|
||||
return fixer.insertTextBefore(
|
||||
tokenAfterColon,
|
||||
spaces,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let messageId;
|
||||
|
||||
if (isExtra) {
|
||||
messageId = side === "key" ? "extraKey" : "extraValue";
|
||||
} else {
|
||||
messageId = side === "key" ? "missingKey" : "missingValue";
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: property[side],
|
||||
loc,
|
||||
messageId,
|
||||
data: {
|
||||
computed: property.computed ? "computed " : "",
|
||||
key: getKey(property),
|
||||
},
|
||||
fix,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of characters in a key, including quotes around string
|
||||
* keys and braces around computed property keys.
|
||||
* @param {ASTNode} property Property of on object literal.
|
||||
* @returns {number} Width of the key.
|
||||
*/
|
||||
function getKeyWidth(property) {
|
||||
const startToken = sourceCode.getFirstToken(property);
|
||||
const endToken = getLastTokenBeforeColon(property.key);
|
||||
|
||||
return getGraphemeCount(
|
||||
sourceCode
|
||||
.getText()
|
||||
.slice(startToken.range[0], endToken.range[1]),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the whitespace around the colon in an object literal property.
|
||||
* @param {ASTNode} property Property node from an object literal.
|
||||
* @returns {Object} Whitespace before and after the property's colon.
|
||||
*/
|
||||
function getPropertyWhitespace(property) {
|
||||
const whitespace = /(\s*):(\s*)/u.exec(
|
||||
sourceCode
|
||||
.getText()
|
||||
.slice(property.key.range[1], property.value.range[0]),
|
||||
);
|
||||
|
||||
if (whitespace) {
|
||||
return {
|
||||
beforeColon: whitespace[1],
|
||||
afterColon: whitespace[2],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates groups of properties.
|
||||
* @param {ASTNode} node ObjectExpression node being evaluated.
|
||||
* @returns {Array<ASTNode[]>} Groups of property AST node lists.
|
||||
*/
|
||||
function createGroups(node) {
|
||||
if (node.properties.length === 1) {
|
||||
return [node.properties];
|
||||
}
|
||||
|
||||
return node.properties.reduce(
|
||||
(groups, property) => {
|
||||
const currentGroup = last(groups),
|
||||
prev = last(currentGroup);
|
||||
|
||||
if (!prev || continuesPropertyGroup(prev, property)) {
|
||||
currentGroup.push(property);
|
||||
} else {
|
||||
groups.push([property]);
|
||||
}
|
||||
|
||||
return groups;
|
||||
},
|
||||
[[]],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies correct vertical alignment of a group of properties.
|
||||
* @param {ASTNode[]} properties List of Property AST nodes.
|
||||
* @returns {void}
|
||||
*/
|
||||
function verifyGroupAlignment(properties) {
|
||||
const length = properties.length,
|
||||
widths = properties.map(getKeyWidth), // Width of keys, including quotes
|
||||
align = alignmentOptions.on; // "value" or "colon"
|
||||
let targetWidth = Math.max(...widths),
|
||||
beforeColon,
|
||||
afterColon,
|
||||
mode;
|
||||
|
||||
if (alignmentOptions && length > 1) {
|
||||
// When aligning values within a group, use the alignment configuration.
|
||||
beforeColon = alignmentOptions.beforeColon;
|
||||
afterColon = alignmentOptions.afterColon;
|
||||
mode = alignmentOptions.mode;
|
||||
} else {
|
||||
beforeColon = multiLineOptions.beforeColon;
|
||||
afterColon = multiLineOptions.afterColon;
|
||||
mode = alignmentOptions.mode;
|
||||
}
|
||||
|
||||
// Conditionally include one space before or after colon
|
||||
targetWidth += align === "colon" ? beforeColon : afterColon;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const property = properties[i];
|
||||
const whitespace = getPropertyWhitespace(property);
|
||||
|
||||
if (whitespace) {
|
||||
// Object literal getters/setters lack a colon
|
||||
const width = widths[i];
|
||||
|
||||
if (align === "value") {
|
||||
report(
|
||||
property,
|
||||
"key",
|
||||
whitespace.beforeColon,
|
||||
beforeColon,
|
||||
mode,
|
||||
);
|
||||
report(
|
||||
property,
|
||||
"value",
|
||||
whitespace.afterColon,
|
||||
targetWidth - width,
|
||||
mode,
|
||||
);
|
||||
} else {
|
||||
// align = "colon"
|
||||
report(
|
||||
property,
|
||||
"key",
|
||||
whitespace.beforeColon,
|
||||
targetWidth - width,
|
||||
mode,
|
||||
);
|
||||
report(
|
||||
property,
|
||||
"value",
|
||||
whitespace.afterColon,
|
||||
afterColon,
|
||||
mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies spacing of property conforms to specified options.
|
||||
* @param {ASTNode} node Property node being evaluated.
|
||||
* @param {Object} lineOptions Configured singleLine or multiLine options
|
||||
* @returns {void}
|
||||
*/
|
||||
function verifySpacing(node, lineOptions) {
|
||||
const actual = getPropertyWhitespace(node);
|
||||
|
||||
if (actual) {
|
||||
// Object literal getters/setters lack colons
|
||||
report(
|
||||
node,
|
||||
"key",
|
||||
actual.beforeColon,
|
||||
lineOptions.beforeColon,
|
||||
lineOptions.mode,
|
||||
);
|
||||
report(
|
||||
node,
|
||||
"value",
|
||||
actual.afterColon,
|
||||
lineOptions.afterColon,
|
||||
lineOptions.mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies spacing of each property in a list.
|
||||
* @param {ASTNode[]} properties List of Property AST nodes.
|
||||
* @param {Object} lineOptions Configured singleLine or multiLine options
|
||||
* @returns {void}
|
||||
*/
|
||||
function verifyListSpacing(properties, lineOptions) {
|
||||
const length = properties.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
verifySpacing(properties[i], lineOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies vertical alignment, taking into account groups of properties.
|
||||
* @param {ASTNode} node ObjectExpression node being evaluated.
|
||||
* @returns {void}
|
||||
*/
|
||||
function verifyAlignment(node) {
|
||||
createGroups(node).forEach(group => {
|
||||
const properties = group.filter(isKeyValueProperty);
|
||||
|
||||
if (
|
||||
properties.length > 0 &&
|
||||
isSingleLineProperties(properties)
|
||||
) {
|
||||
verifyListSpacing(properties, multiLineOptions);
|
||||
} else {
|
||||
verifyGroupAlignment(properties);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public API
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
if (alignmentOptions) {
|
||||
// Verify vertical alignment
|
||||
|
||||
return {
|
||||
ObjectExpression(node) {
|
||||
if (isSingleLine(node)) {
|
||||
verifyListSpacing(
|
||||
node.properties.filter(isKeyValueProperty),
|
||||
singleLineOptions,
|
||||
);
|
||||
} else {
|
||||
verifyAlignment(node);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Obey beforeColon and afterColon in each property as configured
|
||||
return {
|
||||
Property(node) {
|
||||
verifySpacing(
|
||||
node,
|
||||
isSingleLine(node.parent)
|
||||
? singleLineOptions
|
||||
: multiLineOptions,
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export type MessageIds = 'unnecessaryTypeParameter';
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unnecessaryTypeParameter", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,42 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABILITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
declare namespace Intl {
|
||||
interface DateTimeFormatPartTypesRegistry {
|
||||
day: any;
|
||||
dayPeriod: any;
|
||||
era: any;
|
||||
hour: any;
|
||||
literal: any;
|
||||
minute: any;
|
||||
month: any;
|
||||
second: any;
|
||||
timeZoneName: any;
|
||||
weekday: any;
|
||||
year: any;
|
||||
}
|
||||
|
||||
type DateTimeFormatPartTypes = keyof DateTimeFormatPartTypesRegistry;
|
||||
|
||||
interface DateTimeFormatPart {
|
||||
type: DateTimeFormatPartTypes;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DateTimeFormat {
|
||||
formatToParts(date?: Date | number): DateTimeFormatPart[];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cryptoNode.d.ts","sourceRoot":"","sources":["../src/cryptoNode.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,MAAM,EAAE,GAKJ,CAAC"}
|
||||
@@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const Range = require('../classes/range')
|
||||
|
||||
// Mostly just for testing and legacy API reasons
|
||||
const toComparators = (range, options) =>
|
||||
new Range(range, options).set
|
||||
.map(comp => comp.map(c => c.value).join(' ').trim().split(' '))
|
||||
|
||||
module.exports = toComparators
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict'
|
||||
|
||||
// given a set of versions and a range, create a "simplified" range
|
||||
// that includes the same versions that the original range does
|
||||
// If the original range is shorter than the simplified one, return that.
|
||||
const satisfies = require('../functions/satisfies.js')
|
||||
const compare = require('../functions/compare.js')
|
||||
module.exports = (versions, range, options) => {
|
||||
const set = []
|
||||
let first = null
|
||||
let prev = null
|
||||
const v = versions.sort((a, b) => compare(a, b, options))
|
||||
for (const version of v) {
|
||||
const included = satisfies(version, range, options)
|
||||
if (included) {
|
||||
prev = version
|
||||
if (!first) {
|
||||
first = version
|
||||
}
|
||||
} else {
|
||||
if (prev) {
|
||||
set.push([first, prev])
|
||||
}
|
||||
prev = null
|
||||
first = null
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
set.push([first, null])
|
||||
}
|
||||
|
||||
const ranges = []
|
||||
for (const [min, max] of set) {
|
||||
if (min === max) {
|
||||
ranges.push(min)
|
||||
} else if (!max && min === v[0]) {
|
||||
ranges.push('*')
|
||||
} else if (!max) {
|
||||
ranges.push(`>=${min}`)
|
||||
} else if (min === v[0]) {
|
||||
ranges.push(`<=${max}`)
|
||||
} else {
|
||||
ranges.push(`${min} - ${max}`)
|
||||
}
|
||||
}
|
||||
const simplified = ranges.join(' || ')
|
||||
const original = typeof range.raw === 'string' ? range.raw : String(range)
|
||||
return simplified.length < original.length ? simplified : range
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"commentDirectiveType.d.ts","sourceRoot":"","sources":["../../src/enums/commentDirectiveType.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,oBAAoB,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import {
|
||||
BlockScope,
|
||||
CatchScope,
|
||||
ClassFieldInitializerScope,
|
||||
ClassStaticBlockScope,
|
||||
ClassScope,
|
||||
ForScope,
|
||||
FunctionExpressionNameScope,
|
||||
FunctionScope,
|
||||
GlobalScope,
|
||||
ModuleScope,
|
||||
SwitchScope,
|
||||
WithScope,
|
||||
} from "./scope.js";
|
||||
import { assert } from "./assert.js";
|
||||
|
||||
/** @import * as types from "eslint-scope" */
|
||||
/** @import ESTree from "estree" */
|
||||
/** @import { Scope } from "./scope.js" */
|
||||
/** @import Variable from "./variable.js" */
|
||||
|
||||
/**
|
||||
* @constructor ScopeManager
|
||||
* @implements {types.ScopeManager}
|
||||
*/
|
||||
class ScopeManager {
|
||||
constructor(options) {
|
||||
this.scopes = [];
|
||||
this.globalScope = null;
|
||||
this.__nodeToScope = new WeakMap();
|
||||
this.__currentScope = null;
|
||||
this.__options = options;
|
||||
this.__declaredVariables = new WeakMap();
|
||||
}
|
||||
|
||||
__isOptimistic() {
|
||||
return this.__options.optimistic;
|
||||
}
|
||||
|
||||
__ignoreEval() {
|
||||
return this.__options.ignoreEval;
|
||||
}
|
||||
|
||||
__isJSXEnabled() {
|
||||
return this.__options.jsx === true;
|
||||
}
|
||||
|
||||
isGlobalReturn() {
|
||||
return (
|
||||
this.__options.nodejsScope ||
|
||||
this.__options.sourceType === "commonjs"
|
||||
);
|
||||
}
|
||||
|
||||
isModule() {
|
||||
return this.__options.sourceType === "module";
|
||||
}
|
||||
|
||||
isImpliedStrict() {
|
||||
return !!this.__options.impliedStrict;
|
||||
}
|
||||
|
||||
isStrictModeSupported() {
|
||||
return this.__options.ecmaVersion >= 5;
|
||||
}
|
||||
|
||||
// Returns appropriate scope for this node.
|
||||
__get(node) {
|
||||
return this.__nodeToScope.get(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variables that are declared by the node.
|
||||
*
|
||||
* "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
|
||||
* If the node declares nothing, this method returns an empty array.
|
||||
* CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
|
||||
* @param {ESTree.Node} node a node to get.
|
||||
* @returns {Variable[]} variables that declared by the node.
|
||||
*/
|
||||
getDeclaredVariables(node) {
|
||||
return this.__declaredVariables.get(node) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* acquire scope from node.
|
||||
* @function ScopeManager#acquire
|
||||
* @param {ESTree.Node} node node for the acquired scope.
|
||||
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
|
||||
* @returns {Scope?} Scope from node
|
||||
*/
|
||||
acquire(node, inner) {
|
||||
/**
|
||||
* predicate
|
||||
* @param {Scope} testScope scope to test
|
||||
* @returns {boolean} predicate
|
||||
*/
|
||||
function predicate(testScope) {
|
||||
if (
|
||||
testScope.type === "function" &&
|
||||
testScope.functionExpressionScope
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const scopes = this.__get(node);
|
||||
|
||||
if (!scopes || scopes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Heuristic selection from all scopes.
|
||||
// If you would like to get all scopes, please use ScopeManager#acquireAll.
|
||||
if (scopes.length === 1) {
|
||||
return scopes[0];
|
||||
}
|
||||
|
||||
if (inner) {
|
||||
for (let i = scopes.length - 1; i >= 0; --i) {
|
||||
const scope = scopes[i];
|
||||
|
||||
if (predicate(scope)) {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, iz = scopes.length; i < iz; ++i) {
|
||||
const scope = scopes[i];
|
||||
|
||||
if (predicate(scope)) {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* acquire all scopes from node.
|
||||
* @function ScopeManager#acquireAll
|
||||
* @param {ESTree.Node} node node for the acquired scope.
|
||||
* @returns {Scope[]?} Scope array
|
||||
*/
|
||||
acquireAll(node) {
|
||||
return this.__get(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* release the node.
|
||||
* @function ScopeManager#release
|
||||
* @param {ESTree.Node} node releasing node.
|
||||
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
|
||||
* @returns {Scope?} upper scope for the node.
|
||||
*/
|
||||
release(node, inner) {
|
||||
const scopes = this.__get(node);
|
||||
|
||||
if (scopes && scopes.length) {
|
||||
const scope = scopes[0].upper;
|
||||
|
||||
if (!scope) {
|
||||
return null;
|
||||
}
|
||||
return this.acquire(scope.block, inner);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add global variables and resolve their references.
|
||||
* @function ScopeManager#addGlobals
|
||||
* @param {string[]} names Names of global variables to add.
|
||||
* @returns {void}
|
||||
*/
|
||||
addGlobals(names) {
|
||||
// @ts-ignore -- globalScope must be set before this method is called.
|
||||
this.globalScope.__addVariables(names);
|
||||
}
|
||||
|
||||
attach() {} // eslint-disable-line class-methods-use-this -- Desired as instance method
|
||||
|
||||
detach() {} // eslint-disable-line class-methods-use-this -- Desired as instance method
|
||||
|
||||
__nestScope(scope) {
|
||||
if (scope instanceof GlobalScope) {
|
||||
assert(this.__currentScope === null);
|
||||
this.globalScope = scope;
|
||||
}
|
||||
this.__currentScope = scope;
|
||||
return scope;
|
||||
}
|
||||
|
||||
__nestGlobalScope(node) {
|
||||
return this.__nestScope(new GlobalScope(this, node));
|
||||
}
|
||||
|
||||
__nestBlockScope(node) {
|
||||
return this.__nestScope(
|
||||
new BlockScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestFunctionScope(node, isMethodDefinition) {
|
||||
return this.__nestScope(
|
||||
new FunctionScope(
|
||||
this,
|
||||
this.__currentScope,
|
||||
node,
|
||||
isMethodDefinition,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
__nestForScope(node) {
|
||||
return this.__nestScope(new ForScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestCatchScope(node) {
|
||||
return this.__nestScope(
|
||||
new CatchScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestWithScope(node) {
|
||||
return this.__nestScope(new WithScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestClassScope(node) {
|
||||
return this.__nestScope(
|
||||
new ClassScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestClassFieldInitializerScope(node) {
|
||||
return this.__nestScope(
|
||||
new ClassFieldInitializerScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestClassStaticBlockScope(node) {
|
||||
return this.__nestScope(
|
||||
new ClassStaticBlockScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestSwitchScope(node) {
|
||||
return this.__nestScope(
|
||||
new SwitchScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestModuleScope(node) {
|
||||
return this.__nestScope(
|
||||
new ModuleScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__nestFunctionExpressionNameScope(node) {
|
||||
return this.__nestScope(
|
||||
new FunctionExpressionNameScope(this, this.__currentScope, node),
|
||||
);
|
||||
}
|
||||
|
||||
__isES6() {
|
||||
return this.__options.ecmaVersion >= 6;
|
||||
}
|
||||
}
|
||||
|
||||
export default ScopeManager;
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @import * as acorn from "acorn";
|
||||
* @import { Options, EspreeTokens } from "../espree.js";
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {acorn.tokTypes & {
|
||||
* jsxName: acorn.TokenType,
|
||||
* jsxText: acorn.TokenType,
|
||||
* jsxTagEnd: acorn.TokenType,
|
||||
* jsxTagStart: acorn.TokenType
|
||||
* }} TokTypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {new (
|
||||
* token: string,
|
||||
* isExpr: boolean,
|
||||
* preserveSpace: boolean,
|
||||
* override?: (parser: any) => void
|
||||
* ) => void} TokContext
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* tc_oTag: TokContext,
|
||||
* tc_cTag: TokContext,
|
||||
* tc_expr: TokContext
|
||||
* }} TokContexts
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* generator?: boolean
|
||||
* } & acorn.Node} EsprimaNode
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {"Block"|"Hashbang"|"Line"} CommentType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* tokenize: () => EspreeTokens,
|
||||
* parse: () => acorn.Program
|
||||
* }} EspreeParser
|
||||
*/
|
||||
|
||||
/* eslint-disable jsdoc/valid-types -- Waiting on jsdoc plugin update */
|
||||
/**
|
||||
* @typedef {acorn.Parser & {
|
||||
* jsx_readToken(): string;
|
||||
* jsx_readNewLine(normalizeCRLF: boolean): void;
|
||||
* jsx_readString(quote: number): void;
|
||||
* jsx_readEntity(): string;
|
||||
* jsx_readWord(): void;
|
||||
* jsx_parseIdentifier(): acorn.Node;
|
||||
* jsx_parseNamespacedName(): acorn.Node;
|
||||
* jsx_parseElementName(): acorn.Node | string;
|
||||
* jsx_parseAttributeValue(): acorn.Node;
|
||||
* jsx_parseEmptyExpression(): acorn.Node;
|
||||
* jsx_parseExpressionContainer(): acorn.Node;
|
||||
* jsx_parseAttribute(): acorn.Node;
|
||||
* jsx_parseOpeningElementAt(startPos: number, startLoc?: acorn.SourceLocation): acorn.Node;
|
||||
* jsx_parseClosingElementAt(startPos: number, startLoc?: acorn.SourceLocation): acorn.Node;
|
||||
* jsx_parseElementAt(startPos: number, startLoc?: acorn.SourceLocation): acorn.Node;
|
||||
* jsx_parseText(): acorn.Node;
|
||||
* jsx_parseElement(): acorn.Node;
|
||||
* }} AcornJsxParser
|
||||
*/
|
||||
|
||||
/**
|
||||
* We pick (statics) from acorn rather than plain extending to avoid complaint
|
||||
* about base constructors needing the same return type (i.e., we return
|
||||
* `AcornJsxParser` here)
|
||||
* @typedef {Pick<typeof acorn.Parser, keyof typeof acorn.Parser> & {
|
||||
* readonly acornJsx: {
|
||||
* tokTypes: TokTypes;
|
||||
* tokContexts: TokContexts
|
||||
* };
|
||||
* new (options: acorn.Options, input: string, startPos?: number): AcornJsxParser;
|
||||
* }} AcornJsxParserCtor
|
||||
*/
|
||||
/**
|
||||
* @typedef {{
|
||||
* new (opts: Options | null | undefined, code: string | object): EspreeParser
|
||||
* } & Pick<typeof acorn.Parser, keyof typeof acorn.Parser>} EspreeParserCtor
|
||||
*/
|
||||
/**
|
||||
* @typedef {{
|
||||
* new (opts: Options | null | undefined, code: string | object): EspreeParser
|
||||
* } & Pick<AcornJsxParserCtor, keyof AcornJsxParserCtor>} EspreeParserJsxCtor
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Pick<AcornJsxParserCtor, keyof AcornJsxParserCtor> & {
|
||||
* acorn: {
|
||||
* tokTypes: TokTypes,
|
||||
* getLineInfo: (input: string, pos: number) => {
|
||||
* line: number,
|
||||
* column: number
|
||||
* }
|
||||
* }
|
||||
* new (options: acorn.Options, input: string, startPos?: number): AcornJsxParser & {
|
||||
* next: () => void,
|
||||
* type: acorn.TokenType,
|
||||
* curLine: number,
|
||||
* start: number,
|
||||
* end: number,
|
||||
* finishNode (node: acorn.Node, type: string): acorn.Node,
|
||||
* finishNodeAt (node: acorn.Node, type: string, pos: number, loc: acorn.Position): acorn.Node,
|
||||
* parseTopLevel (node: acorn.Node): acorn.Node,
|
||||
* nextToken (): void
|
||||
* }
|
||||
* }} AcornJsxParserCtorEnhanced
|
||||
*/
|
||||
|
||||
/* eslint-enable jsdoc/valid-types -- Bug in older versions */
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { TSESTree } from '@typescript-eslint/utils';
|
||||
export declare function isNodeEqual(a: TSESTree.Node, b: TSESTree.Node): boolean;
|
||||
@@ -0,0 +1,3 @@
|
||||
export declare function addCandidateTSConfigRootDir(candidate: string): void;
|
||||
export declare function clearCandidateTSConfigRootDirs(): void;
|
||||
export declare function getInferredTSConfigRootDir(): string;
|
||||
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
# isexe
|
||||
|
||||
Minimal module to check if a file is executable, and a normal file.
|
||||
|
||||
Uses `fs.stat` and tests against the `PATHEXT` environment variable on
|
||||
Windows.
|
||||
|
||||
## USAGE
|
||||
|
||||
```javascript
|
||||
var isexe = require('isexe')
|
||||
isexe('some-file-name', function (err, isExe) {
|
||||
if (err) {
|
||||
console.error('probably file does not exist or something', err)
|
||||
} else if (isExe) {
|
||||
console.error('this thing can be run')
|
||||
} else {
|
||||
console.error('cannot be run')
|
||||
}
|
||||
})
|
||||
|
||||
// same thing but synchronous, throws errors
|
||||
var isExe = isexe.sync('some-file-name')
|
||||
|
||||
// treat errors as just "not executable"
|
||||
isexe('maybe-missing-file', { ignoreErrors: true }, callback)
|
||||
var isExe = isexe.sync('maybe-missing-file', { ignoreErrors: true })
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `isexe(path, [options], [callback])`
|
||||
|
||||
Check if the path is executable. If no callback provided, and a
|
||||
global `Promise` object is available, then a Promise will be returned.
|
||||
|
||||
Will raise whatever errors may be raised by `fs.stat`, unless
|
||||
`options.ignoreErrors` is set to true.
|
||||
|
||||
### `isexe.sync(path, [options])`
|
||||
|
||||
Same as `isexe` but returns the value and throws any errors raised.
|
||||
|
||||
### Options
|
||||
|
||||
* `ignoreErrors` Treat all errors as "no, this is not executable", but
|
||||
don't raise them.
|
||||
* `uid` Number to use as the user id
|
||||
* `gid` Number to use as the group id
|
||||
* `pathExt` List of path extensions to use instead of `PATHEXT`
|
||||
environment variable on Windows.
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"keys-while": {
|
||||
"name": "keys-while",
|
||||
"browser": "Chrome Mobile 39.0.0 (Android 5.1.1)",
|
||||
"suite": "iter",
|
||||
"hz": 41449.9799734825,
|
||||
"success": true,
|
||||
"fastest": true,
|
||||
"rme": 0.022947386031672564,
|
||||
"rhz": 1,
|
||||
"sampleSize": 159
|
||||
},
|
||||
"keys-for": {
|
||||
"name": "keys-for",
|
||||
"browser": "Chrome Mobile 39.0.0 (Android 5.1.1)",
|
||||
"suite": "iter",
|
||||
"hz": 38639.94651532041,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.019140969586850222,
|
||||
"rhz": 0.9322066389426532,
|
||||
"sampleSize": 160
|
||||
},
|
||||
"incr-for": {
|
||||
"name": "incr-for",
|
||||
"browser": "Chrome Mobile 39.0.0 (Android 5.1.1)",
|
||||
"suite": "iter",
|
||||
"hz": 15632.699209216895,
|
||||
"success": true,
|
||||
"fastest": false,
|
||||
"rme": 0.017769563380438193,
|
||||
"rhz": 0.37714612212642484,
|
||||
"sampleSize": 161
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
var _typeof = require("./typeof.js")["default"];
|
||||
var checkInRHS = require("./checkInRHS.js");
|
||||
var setFunctionName = require("./setFunctionName.js");
|
||||
var toPropertyKey = require("./toPropertyKey.js");
|
||||
function applyDecs2311(e, t, n, r, o, i) {
|
||||
var a,
|
||||
c,
|
||||
u,
|
||||
s,
|
||||
f,
|
||||
l,
|
||||
p,
|
||||
d = Symbol.metadata || Symbol["for"]("Symbol.metadata"),
|
||||
m = Object.defineProperty,
|
||||
h = Object.create,
|
||||
y = [h(null), h(null)],
|
||||
v = t.length;
|
||||
function g(t, n, r) {
|
||||
return function (o, i) {
|
||||
n && (i = o, o = e);
|
||||
for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []);
|
||||
return r ? i : o;
|
||||
};
|
||||
}
|
||||
function b(e, t, n, r) {
|
||||
if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined"));
|
||||
return e;
|
||||
}
|
||||
function applyDec(e, t, n, r, o, i, u, s, f, l, p) {
|
||||
function d(e) {
|
||||
if (!p(e)) throw new TypeError("Attempted to access private element on non-instance");
|
||||
}
|
||||
var h = [].concat(t[0]),
|
||||
v = t[3],
|
||||
w = !u,
|
||||
D = 1 === o,
|
||||
S = 3 === o,
|
||||
j = 4 === o,
|
||||
E = 2 === o;
|
||||
function I(t, n, r) {
|
||||
return function (o, i) {
|
||||
return n && (i = o, o = e), r && r(o), P[t].call(o, i);
|
||||
};
|
||||
}
|
||||
if (!w) {
|
||||
var P = {},
|
||||
k = [],
|
||||
F = S ? "get" : j || D ? "set" : "value";
|
||||
if (f ? (l || D ? P = {
|
||||
get: setFunctionName(function () {
|
||||
return v(this);
|
||||
}, r, "get"),
|
||||
set: function set(e) {
|
||||
t[4](this, e);
|
||||
}
|
||||
} : P[F] = v, l || setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) {
|
||||
if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet");
|
||||
y[+s][r] = o < 3 ? 1 : o;
|
||||
}
|
||||
}
|
||||
for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) {
|
||||
var T = b(h[O], "A decorator", "be", !0),
|
||||
z = n ? h[O - 1] : void 0,
|
||||
A = {},
|
||||
H = {
|
||||
kind: ["field", "accessor", "method", "getter", "setter", "class"][o],
|
||||
name: r,
|
||||
metadata: a,
|
||||
addInitializer: function (e, t) {
|
||||
if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished");
|
||||
b(t, "An initializer", "be", !0), i.push(t);
|
||||
}.bind(null, A)
|
||||
};
|
||||
if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H["static"] = s, H["private"] = f, c = H.access = {
|
||||
has: f ? p.bind() : function (e) {
|
||||
return r in e;
|
||||
}
|
||||
}, j || (c.get = f ? E ? function (e) {
|
||||
return d(e), P.value;
|
||||
} : I("get", 0, d) : function (e) {
|
||||
return e[r];
|
||||
}), E || S || (c.set = f ? I("set", 0, d) : function (e, t) {
|
||||
e[r] = t;
|
||||
}), N = T.call(z, D ? {
|
||||
get: P.get,
|
||||
set: P.set
|
||||
} : P[F], H), A.v = 1, D) {
|
||||
if ("object" == _typeof(N) && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined");
|
||||
} else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N);
|
||||
}
|
||||
return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N;
|
||||
}
|
||||
function w(e) {
|
||||
return m(e, d, {
|
||||
configurable: !0,
|
||||
enumerable: !0,
|
||||
value: a
|
||||
});
|
||||
}
|
||||
return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function l(e) {
|
||||
e && f.push(g(e));
|
||||
}, p = function p(t, r) {
|
||||
for (var i = 0; i < n.length; i++) {
|
||||
var a = n[i],
|
||||
c = a[1],
|
||||
l = 7 & c;
|
||||
if ((8 & c) == t && !l == r) {
|
||||
var p = a[2],
|
||||
d = !!a[3],
|
||||
m = 16 & c;
|
||||
applyDec(t ? e : e.prototype, a, m, d ? "#" + p : toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) {
|
||||
return checkInRHS(t) === e;
|
||||
} : o);
|
||||
}
|
||||
}
|
||||
}, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), {
|
||||
e: c,
|
||||
get c() {
|
||||
var n = [];
|
||||
return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)];
|
||||
}
|
||||
};
|
||||
}
|
||||
module.exports = applyDecs2311, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,4 @@
|
||||
function _AwaitValue(t) {
|
||||
this.wrapped = t;
|
||||
}
|
||||
module.exports = _AwaitValue, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
function _non_iterable_rest() {
|
||||
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
exports._ = _non_iterable_rest;
|
||||
@@ -0,0 +1,68 @@
|
||||
Usage: pino-pretty [options] [command]
|
||||
|
||||
Commands:
|
||||
help Display help
|
||||
version Display version
|
||||
|
||||
Options:
|
||||
-c, --colorize Force adding color sequences to the output
|
||||
-C, --config specify a path to a json file containing the pino-pretty options
|
||||
-f, --crlf Append CRLF instead of LF to formatted lines
|
||||
-X, --customColors Override default colors using names from https://www.npmjs.com/package/colorette (`-X err:red,info:blue`)
|
||||
-x, --customLevels Override default levels (`-x err:99,info:1`)
|
||||
-k, --errorLikeObjectKeys Define which keys contain error objects (`-k err,error`) (defaults to `err,error`)
|
||||
-e, --errorProps Comma separated list of properties on error objects to show (`*` for all properties) (defaults to ``)
|
||||
-h, --help Output usage information
|
||||
-H, --hideObject Hide objects from output (but not error object)
|
||||
-i, --ignore Ignore one or several keys: (`-i time,hostname`)
|
||||
-I, --include The opposite of `--ignore`, only include one or several keys: (`-I level,time`)
|
||||
-l, --levelFirst Display the log level as the first output field
|
||||
-L, --levelKey [value] Detect the log level under the specified key (defaults to "level")
|
||||
-b, --levelLabel [value] Output the log level using the specified label (defaults to "levelLabel")
|
||||
-o, --messageFormat Format output of message
|
||||
-m, --messageKey [value] Highlight the message under the specified key (defaults to "msg")
|
||||
-L, --minimumLevel Hide messages below the specified log level
|
||||
-S, --singleLine Print all non-error objects on a single line
|
||||
-a, --timestampKey [value] Display the timestamp from the specified key (defaults to "time")
|
||||
-t, --translateTime Display epoch timestamps as UTC ISO format or according to an optional format string (default ISO 8601)
|
||||
-U, --useOnlyCustomProps Only use custom levels and colors (if provided); don't fallback to default levels and colors (-U false)
|
||||
-v, --version Output the version number
|
||||
|
||||
Examples:
|
||||
- To prettify logs, simply pipe a log file through
|
||||
$ cat log | pino-pretty
|
||||
|
||||
- To highlight a string at a key other than 'msg'
|
||||
$ cat log | pino-pretty -m fooMessage
|
||||
|
||||
- To detect the log level at a key other than 'level'
|
||||
$ cat log | pino-pretty --levelKey fooLevel
|
||||
|
||||
- To output the log level label using a key other than 'levelLabel'
|
||||
$ cat log | pino-pretty --levelLabel LVL -o "{LVL}"
|
||||
|
||||
- To display timestamp from a key other than 'time'
|
||||
$ cat log | pino-pretty -a fooTimestamp
|
||||
|
||||
- To convert Epoch timestamps to ISO timestamps use the -t option
|
||||
$ cat log | pino-pretty -t
|
||||
|
||||
- To convert Epoch timestamps to local timezone format use the -t option with "SYS:" prefixed format string
|
||||
$ cat log | pino-pretty -t "SYS:yyyy-mm-dd HH:MM:ss"
|
||||
|
||||
- To flip level and time/date in standard output use the -l option
|
||||
$ cat log | pino-pretty -l
|
||||
|
||||
- Only prints messages with a minimum log level of info
|
||||
$ cat log | pino-pretty -L info
|
||||
|
||||
- Prettify logs but don't print pid and hostname
|
||||
$ cat log | pino-pretty -i pid,hostname
|
||||
|
||||
- Prettify logs but only print time and level
|
||||
$ cat log | pino-pretty -I time,level
|
||||
|
||||
- Loads options from a config file
|
||||
$ cat log | pino-pretty --config=/path/to/config.json
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Internal helpers for blake hash.
|
||||
* @module
|
||||
*/
|
||||
import { rotr } from './utils.ts';
|
||||
|
||||
/**
|
||||
* Internal blake variable.
|
||||
* For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1].
|
||||
*/
|
||||
// prettier-ignore
|
||||
export const BSIGMA: Uint8Array = /* @__PURE__ */ Uint8Array.from([
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
|
||||
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
|
||||
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
|
||||
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
|
||||
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
|
||||
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
|
||||
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
|
||||
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
|
||||
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
|
||||
// Blake1, unused in others
|
||||
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
|
||||
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
|
||||
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
|
||||
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
|
||||
]);
|
||||
|
||||
// prettier-ignore
|
||||
export type Num4 = { a: number; b: number; c: number; d: number; };
|
||||
|
||||
// Mixing function G splitted in two halfs
|
||||
export function G1s(a: number, b: number, c: number, d: number, x: number): Num4 {
|
||||
a = (a + b + x) | 0;
|
||||
d = rotr(d ^ a, 16);
|
||||
c = (c + d) | 0;
|
||||
b = rotr(b ^ c, 12);
|
||||
return { a, b, c, d };
|
||||
}
|
||||
|
||||
export function G2s(a: number, b: number, c: number, d: number, x: number): Num4 {
|
||||
a = (a + b + x) | 0;
|
||||
d = rotr(d ^ a, 8);
|
||||
c = (c + d) | 0;
|
||||
b = rotr(b ^ c, 7);
|
||||
return { a, b, c, d };
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
# flatted
|
||||
|
||||
[](https://www.npmjs.com/package/flatted) [](https://coveralls.io/github/WebReflection/flatted?branch=main) [](https://opensource.org/licenses/ISC) 
|
||||
|
||||

|
||||
|
||||
<sup>**Social Media Photo by [Matt Seymour](https://unsplash.com/@mattseymour) on [Unsplash](https://unsplash.com/)**</sup>
|
||||
|
||||
A super light (0.5K) and fast circular JSON parser, directly from the creator of [CircularJSON](https://github.com/WebReflection/circular-json/#circularjson).
|
||||
|
||||
Available also for **[PHP](./php/flatted.php)**.
|
||||
|
||||
Available also for **[Python](./python/flatted.py)**.
|
||||
|
||||
Available also for **[Go](./golang/README.md)**.
|
||||
|
||||
- - -
|
||||
|
||||
## ℹ️ JSON only values
|
||||
|
||||
If you need anything more complex than values JSON understands, there is a standard approach to recursion and more data-types than what JSON allows, and it's part of the [Structured Clone polyfill](https://github.com/ungap/structured-clone/#readme).
|
||||
|
||||
- - -
|
||||
|
||||
```js
|
||||
npm i flatted
|
||||
```
|
||||
|
||||
Usable via [CDN](https://unpkg.com/flatted) or as regular module.
|
||||
|
||||
```js
|
||||
// ESM
|
||||
import {parse, stringify, toJSON, fromJSON} from 'flatted';
|
||||
|
||||
// CJS
|
||||
const {parse, stringify, toJSON, fromJSON} = require('flatted');
|
||||
|
||||
const a = [{}];
|
||||
a[0].a = a;
|
||||
a.push(a);
|
||||
|
||||
stringify(a); // [["1","0"],{"a":"0"}]
|
||||
```
|
||||
|
||||
## toJSON and fromJSON
|
||||
|
||||
If you'd like to implicitly survive JSON serialization, these two helpers helps:
|
||||
|
||||
```js
|
||||
import {toJSON, fromJSON} from 'flatted';
|
||||
|
||||
class RecursiveMap extends Map {
|
||||
static fromJSON(any) {
|
||||
return new this(fromJSON(any));
|
||||
}
|
||||
toJSON() {
|
||||
return toJSON([...this.entries()]);
|
||||
}
|
||||
}
|
||||
|
||||
const recursive = new RecursiveMap;
|
||||
const same = {};
|
||||
same.same = same;
|
||||
recursive.set('same', same);
|
||||
|
||||
const asString = JSON.stringify(recursive);
|
||||
const asMap = RecursiveMap.fromJSON(JSON.parse(asString));
|
||||
asMap.get('same') === asMap.get('same').same;
|
||||
// true
|
||||
```
|
||||
|
||||
|
||||
## Flatted VS JSON
|
||||
|
||||
As it is for every other specialized format capable of serializing and deserializing circular data, you should never `JSON.parse(Flatted.stringify(data))`, and you should never `Flatted.parse(JSON.stringify(data))`.
|
||||
|
||||
The only way this could work is to `Flatted.parse(Flatted.stringify(data))`, as it is also for _CircularJSON_ or any other, otherwise there's no granted data integrity.
|
||||
|
||||
Also please note this project serializes and deserializes only data compatible with JSON, so that sockets, or anything else with internal classes different from those allowed by JSON standard, won't be serialized and unserialized as expected.
|
||||
|
||||
|
||||
### New in V1: Exact same JSON API
|
||||
|
||||
* Added a [reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Syntax) parameter to `.parse(string, reviver)` and revive your own objects.
|
||||
* Added a [replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Syntax) and a `space` parameter to `.stringify(object, replacer, space)` for feature parity with JSON signature.
|
||||
|
||||
|
||||
### Compatibility
|
||||
All ECMAScript engines compatible with `Map`, `Set`, `Object.keys`, and `Array.prototype.reduce` will work, even if polyfilled.
|
||||
|
||||
|
||||
### How does it work ?
|
||||
While stringifying, all Objects, including Arrays, and strings, are flattened out and replaced as unique index. `*`
|
||||
|
||||
Once parsed, all indexes will be replaced through the flattened collection.
|
||||
|
||||
<sup><sub>`*` represented as string to avoid conflicts with numbers</sub></sup>
|
||||
|
||||
```js
|
||||
// logic example
|
||||
var a = [{one: 1}, {two: '2'}];
|
||||
a[0].a = a;
|
||||
// a is the main object, will be at index '0'
|
||||
// {one: 1} is the second object, index '1'
|
||||
// {two: '2'} the third, in '2', and it has a string
|
||||
// which will be found at index '3'
|
||||
|
||||
Flatted.stringify(a);
|
||||
// [["1","2"],{"one":1,"a":"0"},{"two":"3"},"2"]
|
||||
// a[one,two] {one: 1, a} {two: '2'} '2'
|
||||
```
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @fileoverview Rule to enforce spacing around colons of switch statements.
|
||||
* @author Toru Nagashima
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "switch-colon-spacing",
|
||||
url: "https://eslint.style/rules/switch-colon-spacing",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "Enforce spacing around colons of switch statements",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/switch-colon-spacing",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
before: { type: "boolean", default: false },
|
||||
after: { type: "boolean", default: true },
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
fixable: "whitespace",
|
||||
messages: {
|
||||
expectedBefore: "Expected space(s) before this colon.",
|
||||
expectedAfter: "Expected space(s) after this colon.",
|
||||
unexpectedBefore: "Unexpected space(s) before this colon.",
|
||||
unexpectedAfter: "Unexpected space(s) after this colon.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const options = context.options[0] || {};
|
||||
const beforeSpacing = options.before === true; // false by default
|
||||
const afterSpacing = options.after !== false; // true by default
|
||||
|
||||
/**
|
||||
* Check whether the spacing between the given 2 tokens is valid or not.
|
||||
* @param {Token} left The left token to check.
|
||||
* @param {Token} right The right token to check.
|
||||
* @param {boolean} expected The expected spacing to check. `true` if there should be a space.
|
||||
* @returns {boolean} `true` if the spacing between the tokens is valid.
|
||||
*/
|
||||
function isValidSpacing(left, right, expected) {
|
||||
return (
|
||||
astUtils.isClosingBraceToken(right) ||
|
||||
!astUtils.isTokenOnSameLine(left, right) ||
|
||||
sourceCode.isSpaceBetween(left, right) === expected
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether comments exist between the given 2 tokens.
|
||||
* @param {Token} left The left token to check.
|
||||
* @param {Token} right The right token to check.
|
||||
* @returns {boolean} `true` if comments exist between the given 2 tokens.
|
||||
*/
|
||||
function commentsExistBetween(left, right) {
|
||||
return (
|
||||
sourceCode.getFirstTokenBetween(left, right, {
|
||||
includeComments: true,
|
||||
filter: astUtils.isCommentToken,
|
||||
}) !== null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the spacing between the given 2 tokens.
|
||||
* @param {RuleFixer} fixer The fixer to fix.
|
||||
* @param {Token} left The left token of fix range.
|
||||
* @param {Token} right The right token of fix range.
|
||||
* @param {boolean} spacing The spacing style. `true` if there should be a space.
|
||||
* @returns {Fix|null} The fix object.
|
||||
*/
|
||||
function fix(fixer, left, right, spacing) {
|
||||
if (commentsExistBetween(left, right)) {
|
||||
return null;
|
||||
}
|
||||
if (spacing) {
|
||||
return fixer.insertTextAfter(left, " ");
|
||||
}
|
||||
return fixer.removeRange([left.range[1], right.range[0]]);
|
||||
}
|
||||
|
||||
return {
|
||||
SwitchCase(node) {
|
||||
const colonToken = astUtils.getSwitchCaseColonToken(
|
||||
node,
|
||||
sourceCode,
|
||||
);
|
||||
const beforeToken = sourceCode.getTokenBefore(colonToken);
|
||||
const afterToken = sourceCode.getTokenAfter(colonToken);
|
||||
|
||||
if (!isValidSpacing(beforeToken, colonToken, beforeSpacing)) {
|
||||
context.report({
|
||||
node,
|
||||
loc: colonToken.loc,
|
||||
messageId: beforeSpacing
|
||||
? "expectedBefore"
|
||||
: "unexpectedBefore",
|
||||
fix: fixer =>
|
||||
fix(fixer, beforeToken, colonToken, beforeSpacing),
|
||||
});
|
||||
}
|
||||
if (!isValidSpacing(colonToken, afterToken, afterSpacing)) {
|
||||
context.report({
|
||||
node,
|
||||
loc: colonToken.loc,
|
||||
messageId: afterSpacing
|
||||
? "expectedAfter"
|
||||
: "unexpectedAfter",
|
||||
fix: fixer =>
|
||||
fix(fixer, colonToken, afterToken, afterSpacing),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @fileoverview typings for "eslint/config" module
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
import {
|
||||
type Config,
|
||||
type ConfigObject,
|
||||
defineConfig,
|
||||
globalIgnores,
|
||||
includeIgnoreFile,
|
||||
} from "@eslint/config-helpers";
|
||||
|
||||
export {
|
||||
type Config,
|
||||
type ConfigObject,
|
||||
defineConfig,
|
||||
globalIgnores,
|
||||
includeIgnoreFile,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,420 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
|
||||
// node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js
|
||||
var WebSocketBrowserImpl = class extends EventEmitter {
|
||||
socket;
|
||||
/** Instantiate a WebSocket class
|
||||
* @constructor
|
||||
* @param {String} address - url to a websocket server
|
||||
* @param {WebSocketBrowserOptions} options - websocket options
|
||||
* @return {WebSocketBrowserImpl} - returns a WebSocket instance
|
||||
*/
|
||||
constructor(address, options) {
|
||||
super();
|
||||
this.socket = new window.WebSocket(address, options.protocols);
|
||||
this.socket.onopen = () => this.emit("open");
|
||||
this.socket.onmessage = (event) => this.emit("message", event.data);
|
||||
this.socket.onerror = (error) => this.emit("error", error);
|
||||
this.socket.onclose = (event) => {
|
||||
this.emit("close", event.code, event.reason);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Sends data through a websocket connection
|
||||
* @method
|
||||
* @param {(String|Object)} data - data to be sent via websocket
|
||||
* @param {Object} optionsOrCallback - ws options
|
||||
* @param {Function} callback - a callback called once the data is sent
|
||||
* @return {Undefined}
|
||||
*/
|
||||
send(data, optionsOrCallback, callback) {
|
||||
const cb = callback || optionsOrCallback;
|
||||
try {
|
||||
this.socket.send(data);
|
||||
cb();
|
||||
} catch (error) {
|
||||
cb(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Closes an underlying socket
|
||||
* @method
|
||||
* @param {Number} code - status code explaining why the connection is being closed
|
||||
* @param {String} reason - a description why the connection is closing
|
||||
* @return {Undefined}
|
||||
* @throws {Error}
|
||||
*/
|
||||
close(code, reason) {
|
||||
this.socket.close(code, reason);
|
||||
}
|
||||
addEventListener(type, listener, options) {
|
||||
this.socket.addEventListener(type, listener, options);
|
||||
}
|
||||
};
|
||||
function WebSocket(address, options) {
|
||||
return new WebSocketBrowserImpl(address, options);
|
||||
}
|
||||
|
||||
// src/lib/utils.ts
|
||||
var DefaultDataPack = class {
|
||||
encode(value) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
decode(value) {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
};
|
||||
|
||||
// src/lib/client.ts
|
||||
var CommonClient = class extends EventEmitter {
|
||||
address;
|
||||
rpc_id;
|
||||
queue;
|
||||
options;
|
||||
autoconnect;
|
||||
ready;
|
||||
reconnect;
|
||||
reconnect_timer_id;
|
||||
reconnect_interval;
|
||||
max_reconnects;
|
||||
rest_options;
|
||||
current_reconnects;
|
||||
generate_request_id;
|
||||
socket;
|
||||
webSocketFactory;
|
||||
dataPack;
|
||||
/**
|
||||
* Instantiate a Client class.
|
||||
* @constructor
|
||||
* @param {webSocketFactory} webSocketFactory - factory method for WebSocket
|
||||
* @param {String} address - url to a websocket server
|
||||
* @param {Object} options - ws options object with reconnect parameters
|
||||
* @param {Function} generate_request_id - custom generation request Id
|
||||
* @param {DataPack} dataPack - data pack contains encoder and decoder
|
||||
* @return {CommonClient}
|
||||
*/
|
||||
constructor(webSocketFactory, address = "ws://localhost:8080", {
|
||||
autoconnect = true,
|
||||
reconnect = true,
|
||||
reconnect_interval = 1e3,
|
||||
max_reconnects = 5,
|
||||
...rest_options
|
||||
} = {}, generate_request_id, dataPack) {
|
||||
super();
|
||||
this.webSocketFactory = webSocketFactory;
|
||||
this.queue = {};
|
||||
this.rpc_id = 0;
|
||||
this.address = address;
|
||||
this.autoconnect = autoconnect;
|
||||
this.ready = false;
|
||||
this.reconnect = reconnect;
|
||||
this.reconnect_timer_id = void 0;
|
||||
this.reconnect_interval = reconnect_interval;
|
||||
this.max_reconnects = max_reconnects;
|
||||
this.rest_options = rest_options;
|
||||
this.current_reconnects = 0;
|
||||
this.generate_request_id = generate_request_id || (() => typeof this.rpc_id === "number" ? ++this.rpc_id : Number(this.rpc_id) + 1);
|
||||
if (!dataPack) this.dataPack = new DefaultDataPack();
|
||||
else this.dataPack = dataPack;
|
||||
if (this.autoconnect)
|
||||
this._connect(this.address, {
|
||||
autoconnect: this.autoconnect,
|
||||
reconnect: this.reconnect,
|
||||
reconnect_interval: this.reconnect_interval,
|
||||
max_reconnects: this.max_reconnects,
|
||||
...this.rest_options
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Connects to a defined server if not connected already.
|
||||
* @method
|
||||
* @return {Undefined}
|
||||
*/
|
||||
connect() {
|
||||
if (this.socket) return;
|
||||
this._connect(this.address, {
|
||||
autoconnect: this.autoconnect,
|
||||
reconnect: this.reconnect,
|
||||
reconnect_interval: this.reconnect_interval,
|
||||
max_reconnects: this.max_reconnects,
|
||||
...this.rest_options
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Calls a registered RPC method on server.
|
||||
* @method
|
||||
* @param {String} method - RPC method name
|
||||
* @param {Object|Array} params - optional method parameters
|
||||
* @param {Number} timeout - RPC reply timeout value
|
||||
* @param {Object} ws_opts - options passed to ws
|
||||
* @return {Promise}
|
||||
*/
|
||||
call(method, params, timeout, ws_opts) {
|
||||
if (!ws_opts && "object" === typeof timeout) {
|
||||
ws_opts = timeout;
|
||||
timeout = null;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.ready) return reject(new Error("socket not ready"));
|
||||
const rpc_id = this.generate_request_id(method, params);
|
||||
const message = {
|
||||
jsonrpc: "2.0",
|
||||
method,
|
||||
params: params || void 0,
|
||||
id: rpc_id
|
||||
};
|
||||
this.socket.send(this.dataPack.encode(message), ws_opts, (error) => {
|
||||
if (error) return reject(error);
|
||||
this.queue[rpc_id] = { promise: [resolve, reject] };
|
||||
if (timeout) {
|
||||
this.queue[rpc_id].timeout = setTimeout(() => {
|
||||
delete this.queue[rpc_id];
|
||||
reject(new Error("reply timeout"));
|
||||
}, timeout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Logins with the other side of the connection.
|
||||
* @method
|
||||
* @param {Object} params - Login credentials object
|
||||
* @return {Promise}
|
||||
*/
|
||||
async login(params) {
|
||||
const resp = await this.call("rpc.login", params);
|
||||
if (!resp) throw new Error("authentication failed");
|
||||
return resp;
|
||||
}
|
||||
/**
|
||||
* Fetches a list of client's methods registered on server.
|
||||
* @method
|
||||
* @return {Array}
|
||||
*/
|
||||
async listMethods() {
|
||||
return await this.call("__listMethods");
|
||||
}
|
||||
/**
|
||||
* Sends a JSON-RPC 2.0 notification to server.
|
||||
* @method
|
||||
* @param {String} method - RPC method name
|
||||
* @param {Object} params - optional method parameters
|
||||
* @return {Promise}
|
||||
*/
|
||||
notify(method, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.ready) return reject(new Error("socket not ready"));
|
||||
const message = {
|
||||
jsonrpc: "2.0",
|
||||
method,
|
||||
params
|
||||
};
|
||||
this.socket.send(this.dataPack.encode(message), (error) => {
|
||||
if (error) return reject(error);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Subscribes for a defined event.
|
||||
* @method
|
||||
* @param {String|Array} event - event name
|
||||
* @return {Undefined}
|
||||
* @throws {Error}
|
||||
*/
|
||||
async subscribe(event) {
|
||||
if (typeof event === "string") event = [event];
|
||||
const result = await this.call("rpc.on", event);
|
||||
if (typeof event === "string" && result[event] !== "ok")
|
||||
throw new Error(
|
||||
"Failed subscribing to an event '" + event + "' with: " + result[event]
|
||||
);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Unsubscribes from a defined event.
|
||||
* @method
|
||||
* @param {String|Array} event - event name
|
||||
* @return {Undefined}
|
||||
* @throws {Error}
|
||||
*/
|
||||
async unsubscribe(event) {
|
||||
if (typeof event === "string") event = [event];
|
||||
const result = await this.call("rpc.off", event);
|
||||
if (typeof event === "string" && result[event] !== "ok")
|
||||
throw new Error("Failed unsubscribing from an event with: " + result);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Closes a WebSocket connection gracefully.
|
||||
* @method
|
||||
* @param {Number} code - socket close code
|
||||
* @param {String} data - optional data to be sent before closing
|
||||
* @return {Undefined}
|
||||
*/
|
||||
close(code, data) {
|
||||
if (this.socket) this.socket.close(code || 1e3, data);
|
||||
}
|
||||
/**
|
||||
* Enable / disable automatic reconnection.
|
||||
* @method
|
||||
* @param {Boolean} reconnect - enable / disable reconnection
|
||||
* @return {Undefined}
|
||||
*/
|
||||
setAutoReconnect(reconnect) {
|
||||
this.reconnect = reconnect;
|
||||
}
|
||||
/**
|
||||
* Set the interval between reconnection attempts.
|
||||
* @method
|
||||
* @param {Number} interval - reconnection interval in milliseconds
|
||||
* @return {Undefined}
|
||||
*/
|
||||
setReconnectInterval(interval) {
|
||||
this.reconnect_interval = interval;
|
||||
}
|
||||
/**
|
||||
* Set the maximum number of reconnection attempts.
|
||||
* @method
|
||||
* @param {Number} max_reconnects - maximum reconnection attempts
|
||||
* @return {Undefined}
|
||||
*/
|
||||
setMaxReconnects(max_reconnects) {
|
||||
this.max_reconnects = max_reconnects;
|
||||
}
|
||||
/**
|
||||
* Get the current number of reconnection attempts made.
|
||||
* @method
|
||||
* @return {Number} current reconnection attempts
|
||||
*/
|
||||
getCurrentReconnects() {
|
||||
return this.current_reconnects;
|
||||
}
|
||||
/**
|
||||
* Get the maximum number of reconnection attempts.
|
||||
* @method
|
||||
* @return {Number} maximum reconnection attempts
|
||||
*/
|
||||
getMaxReconnects() {
|
||||
return this.max_reconnects;
|
||||
}
|
||||
/**
|
||||
* Check if the client is currently attempting to reconnect.
|
||||
* @method
|
||||
* @return {Boolean} true if reconnection is in progress
|
||||
*/
|
||||
isReconnecting() {
|
||||
return this.reconnect_timer_id !== void 0;
|
||||
}
|
||||
/**
|
||||
* Check if the client will attempt to reconnect on the next close event.
|
||||
* @method
|
||||
* @return {Boolean} true if reconnection will be attempted
|
||||
*/
|
||||
willReconnect() {
|
||||
return this.reconnect && (this.max_reconnects === 0 || this.current_reconnects < this.max_reconnects);
|
||||
}
|
||||
/**
|
||||
* Connection/Message handler.
|
||||
* @method
|
||||
* @private
|
||||
* @param {String} address - WebSocket API address
|
||||
* @param {Object} options - ws options object
|
||||
* @return {Undefined}
|
||||
*/
|
||||
_connect(address, options) {
|
||||
clearTimeout(this.reconnect_timer_id);
|
||||
this.socket = this.webSocketFactory(address, options);
|
||||
this.socket.addEventListener("open", () => {
|
||||
this.ready = true;
|
||||
this.emit("open");
|
||||
this.current_reconnects = 0;
|
||||
});
|
||||
this.socket.addEventListener("message", ({ data: message }) => {
|
||||
if (message instanceof ArrayBuffer)
|
||||
message = Buffer.from(message).toString();
|
||||
try {
|
||||
message = this.dataPack.decode(message);
|
||||
} catch (_error) {
|
||||
return;
|
||||
}
|
||||
if (message.notification && this.listeners(message.notification).length) {
|
||||
if (!Object.keys(message.params).length)
|
||||
return this.emit(message.notification);
|
||||
const args = [message.notification];
|
||||
if (message.params.constructor === Object) args.push(message.params);
|
||||
else
|
||||
for (let i = 0; i < message.params.length; i++)
|
||||
args.push(message.params[i]);
|
||||
return Promise.resolve().then(() => {
|
||||
this.emit.apply(this, args);
|
||||
});
|
||||
}
|
||||
if (!this.queue[message.id]) {
|
||||
if (message.method) {
|
||||
return Promise.resolve().then(() => {
|
||||
this.emit(message.method, message?.params);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ("error" in message === "result" in message)
|
||||
this.queue[message.id].promise[1](
|
||||
new Error(
|
||||
'Server response malformed. Response must include either "result" or "error", but not both.'
|
||||
)
|
||||
);
|
||||
if (this.queue[message.id].timeout)
|
||||
clearTimeout(this.queue[message.id].timeout);
|
||||
if (message.error) this.queue[message.id].promise[1](message.error);
|
||||
else this.queue[message.id].promise[0](message.result);
|
||||
delete this.queue[message.id];
|
||||
});
|
||||
this.socket.addEventListener("error", (error) => this.emit("error", error));
|
||||
this.socket.addEventListener("close", ({ code, reason }) => {
|
||||
if (this.ready)
|
||||
setTimeout(() => this.emit("close", code, reason), 0);
|
||||
this.ready = false;
|
||||
this.socket = void 0;
|
||||
if (code === 1e3) return;
|
||||
this.current_reconnects++;
|
||||
if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0))
|
||||
this.reconnect_timer_id = setTimeout(
|
||||
() => this._connect(address, options),
|
||||
this.reconnect_interval
|
||||
);
|
||||
else if (this.reconnect && this.max_reconnects > 0 && this.current_reconnects >= this.max_reconnects) {
|
||||
setTimeout(() => this.emit("max_reconnects_reached", code, reason), 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// src/index.browser.ts
|
||||
var Client = class extends CommonClient {
|
||||
constructor(address = "ws://localhost:8080", {
|
||||
autoconnect = true,
|
||||
reconnect = true,
|
||||
reconnect_interval = 1e3,
|
||||
max_reconnects = 5,
|
||||
...rest_options
|
||||
} = {}, generate_request_id) {
|
||||
super(
|
||||
WebSocket,
|
||||
address,
|
||||
{
|
||||
autoconnect,
|
||||
reconnect,
|
||||
reconnect_interval,
|
||||
max_reconnects,
|
||||
...rest_options
|
||||
},
|
||||
generate_request_id
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export { Client, CommonClient, DefaultDataPack, WebSocket };
|
||||
//# sourceMappingURL=index.browser.mjs.map
|
||||
//# sourceMappingURL=index.browser.mjs.map
|
||||
Reference in New Issue
Block a user