WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
|
||||
const {none, final, isFinal, getFinalValue, many, isMany, getManyValues} = require('../defs');
|
||||
|
||||
const next = async function*(value, fns, index) {
|
||||
for (let i = index; i <= fns.length; ++i) {
|
||||
if (value && typeof value.then == 'function') {
|
||||
// thenable
|
||||
value = await value;
|
||||
}
|
||||
if (value === none) break;
|
||||
if (isFinal(value)) {
|
||||
const val = getFinalValue(value);
|
||||
if (val !== none) yield val;
|
||||
break;
|
||||
}
|
||||
if (isMany(value)) {
|
||||
const values = getManyValues(value);
|
||||
if (i == fns.length) {
|
||||
yield* values;
|
||||
} else {
|
||||
for (let j = 0; j < values.length; ++j) {
|
||||
yield* next(values[j], fns, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (value && typeof value.next == 'function') {
|
||||
// generator
|
||||
for (;;) {
|
||||
let data = value.next();
|
||||
if (data && typeof data.then == 'function') {
|
||||
data = await data;
|
||||
}
|
||||
if (data.done) break;
|
||||
if (i == fns.length) {
|
||||
yield data.value;
|
||||
} else {
|
||||
yield* next(data.value, fns, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == fns.length) {
|
||||
yield value;
|
||||
break;
|
||||
}
|
||||
value = fns[i](value);
|
||||
}
|
||||
};
|
||||
|
||||
const nop = async function*() {};
|
||||
|
||||
const asGen = (...fns) => {
|
||||
fns = fns.filter(fn => fn);
|
||||
if (!fns.length) return nop;
|
||||
if (Symbol.asyncIterator && fns[0][Symbol.asyncIterator]) {
|
||||
fns[0] = fns[0][Symbol.asyncIterator];
|
||||
} else if (Symbol.iterator && fns[0][Symbol.iterator]) {
|
||||
fns[0] = fns[0][Symbol.iterator];
|
||||
}
|
||||
return async function*(value) {
|
||||
yield* next(value, fns, 0);
|
||||
};
|
||||
};
|
||||
|
||||
asGen.next = next;
|
||||
|
||||
asGen.none = none;
|
||||
asGen.final = final;
|
||||
asGen.isFinal = isFinal;
|
||||
asGen.getFinalValue = getFinalValue;
|
||||
asGen.many = many;
|
||||
asGen.isMany = isMany;
|
||||
asGen.getManyValues = getManyValues;
|
||||
|
||||
module.exports = asGen;
|
||||
@@ -0,0 +1,157 @@
|
||||
# process-warning
|
||||
|
||||
[](https://github.com/fastify/process-warning/actions/workflows/ci.yml)
|
||||
[](https://www.npmjs.com/package/process-warning)
|
||||
[](https://github.com/neostandard/neostandard)
|
||||
|
||||
A small utility for generating consistent [warning objects](https://nodejs.org/api/process.html#event-warning) across your codebase.
|
||||
It also exposes a utility for emitting those warnings, guaranteeing that they are issued only once (unless configured otherwise).
|
||||
|
||||
_This module is used by the [Fastify](https://fastify.dev) framework and it was called `fastify-warning` prior to version 1.0.0._
|
||||
|
||||
### Install
|
||||
|
||||
```
|
||||
npm i process-warning
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
The module exports two builder functions for creating warnings.
|
||||
|
||||
```js
|
||||
const {
|
||||
createWarning,
|
||||
createDeprecation
|
||||
} = require('process-warning')
|
||||
|
||||
const warning = createWarning({
|
||||
name: 'ExampleWarning',
|
||||
code: 'EXP_WRN_001',
|
||||
message: 'Hello %s',
|
||||
unlimited: true
|
||||
})
|
||||
const emitted = warning('world')
|
||||
```
|
||||
|
||||
#### Methods
|
||||
|
||||
##### `createWarning({ name, code, message[, unlimited] })`
|
||||
|
||||
- `name` (`string`, required) - The error name, you can access it later with
|
||||
`error.name`. For consistency, we recommend prefixing module error names
|
||||
with `{YourModule}Warning`
|
||||
- `code` (`string`, required) - The warning code, you can access it later with
|
||||
`error.code`. For consistency, we recommend prefixing plugin error codes with
|
||||
`{ThreeLetterModuleName}_`, e.g. `FST_`. NOTE: codes should be all uppercase.
|
||||
- `message` (`string`, required) - The warning message. You can also use
|
||||
interpolated strings for formatting the message.
|
||||
- `options` (`object`, optional) - Optional options with the following
|
||||
properties:
|
||||
+ `unlimited` (`boolean`, optional) - Should the warning be emitted more than
|
||||
once? Defaults to `false`.
|
||||
|
||||
|
||||
##### `createDeprecation({code, message[, options]})`
|
||||
|
||||
This is a wrapper for `createWarning`. It is equivalent to invoking
|
||||
`createWarning` with the `name` parameter set to "DeprecationWarning".
|
||||
|
||||
Deprecation warnings have extended support for the Node.js CLI options:
|
||||
`--throw-deprecation`, `--no-deprecation`, and `--trace-deprecation`.
|
||||
|
||||
##### `warning([, a [, b [, c]]])`
|
||||
|
||||
The returned `warning` function can used for emitting warnings.
|
||||
A warning is guaranteed to be emitted at least once.
|
||||
|
||||
- `[, a [, b [, c]]]` (`any`, optional) - Parameters for string interpolation.
|
||||
|
||||
```js
|
||||
const { createWarning } = require('process-warning')
|
||||
const FST_ERROR_CODE = createWarning({ name: 'MyAppWarning', code: 'FST_ERROR_CODE', message: 'message' })
|
||||
FST_ERROR_CODE()
|
||||
```
|
||||
|
||||
How to use an interpolated string:
|
||||
```js
|
||||
const { createWarning } = require('process-warning')
|
||||
const FST_ERROR_CODE = createWarning({ name: 'MyAppWarning', code: 'FST_ERROR_CODE', message: 'Hello %s'})
|
||||
FST_ERROR_CODE('world')
|
||||
```
|
||||
|
||||
The `warning` object has methods and properties for managing the warning's state. Useful for testing.
|
||||
```js
|
||||
const { createWarning } = require('process-warning')
|
||||
const FST_ERROR_CODE = createWarning({ name: 'MyAppWarning', code: 'FST_ERROR_CODE', message: 'Hello %s'})
|
||||
console.log(FST_ERROR_CODE.emitted) // false
|
||||
FST_ERROR_CODE('world')
|
||||
console.log(FST_ERROR_CODE.emitted) // true
|
||||
|
||||
const FST_ERROR_CODE_2 = createWarning('MyAppWarning', 'FST_ERROR_CODE_2', 'Hello %s')
|
||||
FST_ERROR_CODE_2.emitted = true
|
||||
FST_ERROR_CODE_2('world') // will not be emitted because it is not unlimited
|
||||
```
|
||||
|
||||
How to use an unlimited warning:
|
||||
```js
|
||||
const { createWarning } = require('process-warning')
|
||||
const FST_ERROR_CODE = createWarning({ name: 'MyAppWarning', code: 'FST_ERROR_CODE', message: 'Hello %s', unlimited: true })
|
||||
FST_ERROR_CODE('world') // will be emitted
|
||||
FST_ERROR_CODE('world') // will be emitted again
|
||||
```
|
||||
|
||||
#### `spyWarning(warning)`
|
||||
|
||||
Spy the created warning function for testing purpose.
|
||||
|
||||
```js
|
||||
const { test } = require('node:test')
|
||||
const { createWarning, spyWarning } = require('process-warning')
|
||||
const FST_ERROR_CODE = createWarning({ name: 'MyAppWarning', code: 'FST_ERROR_CODE', message: 'Hello %s' })
|
||||
|
||||
test('spy warning', t => {
|
||||
const spyData = spyWarning(FST_ERROR_CODE)
|
||||
|
||||
// call after spy
|
||||
const emitted = FST_ERROR_CODE('world')
|
||||
t.assert.strictEqual(emitted, true)
|
||||
|
||||
// restore the warning function
|
||||
// it must be called when you do not need to spy anymore
|
||||
// otherwise, the calls data will accumulates.
|
||||
t.after(() => spyData.restore())
|
||||
|
||||
t.assert.strictEqual(FST_ERROR_CODE.emitted, true)
|
||||
// calls return the arguments and result.
|
||||
// result indicate whether warning is emitted through process.emitWarning
|
||||
console.log(spyData.calls) // [{ arguments: ['world'], result: true }]
|
||||
t.assert.deepStrictEqual(spyData.calls[0].arguments, ['world'])
|
||||
t.assert.strictEqual(spyData.calls[0].result, true)
|
||||
// number of times called the function
|
||||
console.log(spyData.callCount()) // 1
|
||||
t.assert.strictEqual(spyData.callCount(), 1)
|
||||
|
||||
// reset the spy stat and warning state
|
||||
spyData.reset()
|
||||
t.assert.strictEqual(FST_ERROR_CODE.emitted, false)
|
||||
t.assert.deepStrictEqual(spyData.calls, [])
|
||||
t.assert.strictEqual(spyData.callCount(), 0)
|
||||
})
|
||||
```
|
||||
|
||||
#### Suppressing warnings
|
||||
|
||||
It is possible to suppress warnings by utilizing one of node's built-in warning suppression mechanisms.
|
||||
|
||||
Warnings can be suppressed:
|
||||
|
||||
- by setting the `NODE_NO_WARNINGS` environment variable to `1`
|
||||
- by passing the `--no-warnings` flag to the node process
|
||||
- by setting '--no-warnings' in the `NODE_OPTIONS` environment variable
|
||||
|
||||
For more information see [node's documentation](https://nodejs.org/api/cli.html).
|
||||
|
||||
## License
|
||||
|
||||
Licensed under [MIT](./LICENSE).
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* A read-only variant of `Uint8Array`.
|
||||
*
|
||||
* This type prevents modifications to the array by omitting mutable methods such as `copyWithin`,
|
||||
* `fill`, `reverse`, `set`, and `sort`, while still allowing indexed access to elements.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const bytes: ReadonlyUint8Array = new Uint8Array([1, 2, 3]);
|
||||
* console.log(bytes[0]); // 1
|
||||
* bytes[0] = 42; // Type error: Cannot assign to '0' because it is a read-only property.
|
||||
* ```
|
||||
*/
|
||||
export interface ReadonlyUint8Array extends Omit<Uint8Array, TypedArrayMutableProperties> {
|
||||
readonly [n: number]: number;
|
||||
}
|
||||
type TypedArrayMutableProperties = 'copyWithin' | 'fill' | 'reverse' | 'set' | 'sort';
|
||||
export {};
|
||||
//# sourceMappingURL=readonly-uint8array.d.ts.map
|
||||
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @fileoverview Rule to require grouped accessor pairs in object literals and classes
|
||||
* @author Milos Djermanovic
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Property name if it can be computed statically, otherwise the list of the tokens of the key node.
|
||||
* @typedef {string|Token[]} Key
|
||||
*/
|
||||
|
||||
/**
|
||||
* Accessor nodes with the same key.
|
||||
* @typedef {Object} AccessorData
|
||||
* @property {Key} key Accessor's key
|
||||
* @property {ASTNode[]} getters List of getter nodes.
|
||||
* @property {ASTNode[]} setters List of setter nodes.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether or not the given lists represent the equal tokens in the same order.
|
||||
* Tokens are compared by their properties, not by instance.
|
||||
* @param {Token[]} left First list of tokens.
|
||||
* @param {Token[]} right Second list of tokens.
|
||||
* @returns {boolean} `true` if the lists have same tokens.
|
||||
*/
|
||||
function areEqualTokenLists(left, right) {
|
||||
if (left.length !== right.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < left.length; i++) {
|
||||
const leftToken = left[i],
|
||||
rightToken = right[i];
|
||||
|
||||
if (
|
||||
leftToken.type !== rightToken.type ||
|
||||
leftToken.value !== rightToken.value
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the given keys are equal.
|
||||
* @param {Key} left First key.
|
||||
* @param {Key} right Second key.
|
||||
* @returns {boolean} `true` if the keys are equal.
|
||||
*/
|
||||
function areEqualKeys(left, right) {
|
||||
if (typeof left === "string" && typeof right === "string") {
|
||||
// Statically computed names.
|
||||
return left === right;
|
||||
}
|
||||
if (Array.isArray(left) && Array.isArray(right)) {
|
||||
// Token lists.
|
||||
return areEqualTokenLists(left, right);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a given node is of an accessor kind ('get' or 'set').
|
||||
* @param {ASTNode} node A node to check.
|
||||
* @returns {boolean} `true` if the node is of an accessor kind.
|
||||
*/
|
||||
function isAccessorKind(node) {
|
||||
return node.kind === "get" || node.kind === "set";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [
|
||||
"anyOrder",
|
||||
{
|
||||
enforceForTSTypes: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Require grouped accessor pairs in object literals and classes",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/grouped-accessor-pairs",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{ enum: ["anyOrder", "getBeforeSet", "setBeforeGet"] },
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForTSTypes: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
notGrouped:
|
||||
"Accessor pair {{ formerName }} and {{ latterName }} should be grouped.",
|
||||
invalidOrder:
|
||||
"Expected {{ latterName }} to be before {{ formerName }}.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const [order, { enforceForTSTypes }] = context.options;
|
||||
const { sourceCode } = context;
|
||||
|
||||
/**
|
||||
* Reports the given accessor pair.
|
||||
* @param {string} messageId messageId to report.
|
||||
* @param {ASTNode} formerNode getter/setter node that is defined before `latterNode`.
|
||||
* @param {ASTNode} latterNode getter/setter node that is defined after `formerNode`.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function report(messageId, formerNode, latterNode) {
|
||||
context.report({
|
||||
node: latterNode,
|
||||
messageId,
|
||||
loc: astUtils.getFunctionHeadLoc(
|
||||
latterNode.type !== "TSMethodSignature"
|
||||
? latterNode.value
|
||||
: latterNode,
|
||||
sourceCode,
|
||||
),
|
||||
data: {
|
||||
formerName: astUtils.getFunctionNameWithKind(
|
||||
formerNode.type !== "TSMethodSignature"
|
||||
? formerNode.value
|
||||
: formerNode,
|
||||
),
|
||||
latterName: astUtils.getFunctionNameWithKind(
|
||||
latterNode.type !== "TSMethodSignature"
|
||||
? latterNode.value
|
||||
: latterNode,
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks accessor pairs in the given list of nodes.
|
||||
* @param {ASTNode[]} nodes The list to check.
|
||||
* @param {Function} shouldCheck – Predicate that returns `true` if the node should be checked.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function checkList(nodes, shouldCheck) {
|
||||
const accessors = [];
|
||||
let found = false;
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
|
||||
if (shouldCheck(node) && isAccessorKind(node)) {
|
||||
// Creates a new `AccessorData` object for the given getter or setter node.
|
||||
const name = astUtils.getStaticPropertyName(node);
|
||||
const key =
|
||||
name !== null ? name : sourceCode.getTokens(node.key);
|
||||
|
||||
// Merges the given `AccessorData` object into the given accessors list.
|
||||
for (let j = 0; j < accessors.length; j++) {
|
||||
const accessor = accessors[j];
|
||||
|
||||
if (areEqualKeys(accessor.key, key)) {
|
||||
accessor.getters.push(
|
||||
...(node.kind === "get" ? [node] : []),
|
||||
);
|
||||
accessor.setters.push(
|
||||
...(node.kind === "set" ? [node] : []),
|
||||
);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
accessors.push({
|
||||
key,
|
||||
getters: node.kind === "get" ? [node] : [],
|
||||
setters: node.kind === "set" ? [node] : [],
|
||||
});
|
||||
}
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const { getters, setters } of accessors) {
|
||||
// Don't report accessor properties that have duplicate getters or setters.
|
||||
if (getters.length === 1 && setters.length === 1) {
|
||||
const [getter] = getters,
|
||||
[setter] = setters,
|
||||
getterIndex = nodes.indexOf(getter),
|
||||
setterIndex = nodes.indexOf(setter),
|
||||
formerNode =
|
||||
getterIndex < setterIndex ? getter : setter,
|
||||
latterNode =
|
||||
getterIndex < setterIndex ? setter : getter;
|
||||
|
||||
if (Math.abs(getterIndex - setterIndex) > 1) {
|
||||
report("notGrouped", formerNode, latterNode);
|
||||
} else if (
|
||||
(order === "getBeforeSet" &&
|
||||
getterIndex > setterIndex) ||
|
||||
(order === "setBeforeGet" && getterIndex < setterIndex)
|
||||
) {
|
||||
report("invalidOrder", formerNode, latterNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
ObjectExpression(node) {
|
||||
checkList(node.properties, n => n.type === "Property");
|
||||
},
|
||||
ClassBody(node) {
|
||||
checkList(
|
||||
node.body,
|
||||
n => n.type === "MethodDefinition" && !n.static,
|
||||
);
|
||||
checkList(
|
||||
node.body,
|
||||
n => n.type === "MethodDefinition" && n.static,
|
||||
);
|
||||
},
|
||||
"TSTypeLiteral, TSInterfaceBody"(node) {
|
||||
if (enforceForTSTypes) {
|
||||
checkList(
|
||||
node.type === "TSTypeLiteral"
|
||||
? node.members
|
||||
: node.body,
|
||||
n => n.type === "TSMethodSignature",
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* @fileoverview Disallows multiple blank lines.
|
||||
* implementation adapted from the no-trailing-spaces rule.
|
||||
* @author Greg Cochard
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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: "no-multiple-empty-lines",
|
||||
url: "https://eslint.style/rules/no-multiple-empty-lines",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "Disallow multiple empty lines",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-multiple-empty-lines",
|
||||
},
|
||||
|
||||
fixable: "whitespace",
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
max: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
maxEOF: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
maxBOF: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
required: ["max"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
blankBeginningOfFile:
|
||||
"Too many blank lines at the beginning of file. Max of {{max}} allowed.",
|
||||
blankEndOfFile:
|
||||
"Too many blank lines at the end of file. Max of {{max}} allowed.",
|
||||
consecutiveBlank:
|
||||
"More than {{max}} blank {{pluralizedLines}} not allowed.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
// Use options.max or 2 as default
|
||||
let max = 2,
|
||||
maxEOF = max,
|
||||
maxBOF = max;
|
||||
|
||||
if (context.options.length) {
|
||||
max = context.options[0].max;
|
||||
maxEOF =
|
||||
typeof context.options[0].maxEOF !== "undefined"
|
||||
? context.options[0].maxEOF
|
||||
: max;
|
||||
maxBOF =
|
||||
typeof context.options[0].maxBOF !== "undefined"
|
||||
? context.options[0].maxBOF
|
||||
: max;
|
||||
}
|
||||
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
// Swallow the final newline, as some editors add it automatically and we don't want it to cause an issue
|
||||
const allLines =
|
||||
sourceCode.lines.at(-1) === ""
|
||||
? sourceCode.lines.slice(0, -1)
|
||||
: sourceCode.lines;
|
||||
const templateLiteralLines = new Set();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
TemplateLiteral(node) {
|
||||
node.quasis.forEach(literalPart => {
|
||||
// Empty lines have a semantic meaning if they're inside template literals. Don't count these as empty lines.
|
||||
for (
|
||||
let ignoredLine = literalPart.loc.start.line;
|
||||
ignoredLine < literalPart.loc.end.line;
|
||||
ignoredLine++
|
||||
) {
|
||||
templateLiteralLines.add(ignoredLine);
|
||||
}
|
||||
});
|
||||
},
|
||||
"Program:exit"(node) {
|
||||
return (
|
||||
allLines
|
||||
|
||||
// Given a list of lines, first get a list of line numbers that are non-empty.
|
||||
.reduce((nonEmptyLineNumbers, line, index) => {
|
||||
if (
|
||||
line.trim() ||
|
||||
templateLiteralLines.has(index + 1)
|
||||
) {
|
||||
nonEmptyLineNumbers.push(index + 1);
|
||||
}
|
||||
return nonEmptyLineNumbers;
|
||||
}, [])
|
||||
|
||||
// Add a value at the end to allow trailing empty lines to be checked.
|
||||
.concat(allLines.length + 1)
|
||||
|
||||
// Given two line numbers of non-empty lines, report the lines between if the difference is too large.
|
||||
.reduce((lastLineNumber, lineNumber) => {
|
||||
let messageId, maxAllowed;
|
||||
|
||||
if (lastLineNumber === 0) {
|
||||
messageId = "blankBeginningOfFile";
|
||||
maxAllowed = maxBOF;
|
||||
} else if (lineNumber === allLines.length + 1) {
|
||||
messageId = "blankEndOfFile";
|
||||
maxAllowed = maxEOF;
|
||||
} else {
|
||||
messageId = "consecutiveBlank";
|
||||
maxAllowed = max;
|
||||
}
|
||||
|
||||
if (lineNumber - lastLineNumber - 1 > maxAllowed) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: {
|
||||
line:
|
||||
lastLineNumber + maxAllowed + 1,
|
||||
column: 0,
|
||||
},
|
||||
end: { line: lineNumber, column: 0 },
|
||||
},
|
||||
messageId,
|
||||
data: {
|
||||
max: maxAllowed,
|
||||
pluralizedLines:
|
||||
maxAllowed === 1 ? "line" : "lines",
|
||||
},
|
||||
fix(fixer) {
|
||||
const rangeStart =
|
||||
sourceCode.getIndexFromLoc({
|
||||
line: lastLineNumber + 1,
|
||||
column: 0,
|
||||
});
|
||||
|
||||
/*
|
||||
* The end of the removal range is usually the start index of the next line.
|
||||
* However, at the end of the file there is no next line, so the end of the
|
||||
* range is just the length of the text.
|
||||
*/
|
||||
const lineNumberAfterRemovedLines =
|
||||
lineNumber - maxAllowed;
|
||||
const rangeEnd =
|
||||
lineNumberAfterRemovedLines <=
|
||||
allLines.length
|
||||
? sourceCode.getIndexFromLoc({
|
||||
line: lineNumberAfterRemovedLines,
|
||||
column: 0,
|
||||
})
|
||||
: sourceCode.text.length;
|
||||
|
||||
return fixer.removeRange([
|
||||
rangeStart,
|
||||
rangeEnd,
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return lineNumber;
|
||||
}, 0)
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
|
||||
*
|
||||
* Belongs to Koblitz curves: it has efficiently-computable GLV endomorphism ψ,
|
||||
* check out {@link EndomorphismOpts}. Seems to be rigid (not backdoored).
|
||||
* @module
|
||||
*/
|
||||
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
import { sha256 } from '@noble/hashes/sha2.js';
|
||||
import { randomBytes } from '@noble/hashes/utils.js';
|
||||
import { createCurve } from "./_shortw_utils.js";
|
||||
import { createHasher, isogenyMap, } from "./abstract/hash-to-curve.js";
|
||||
import { Field, mapHashToField, mod, pow2 } from "./abstract/modular.js";
|
||||
import { _normFnElement, mapToCurveSimpleSWU, } from "./abstract/weierstrass.js";
|
||||
import { bytesToNumberBE, concatBytes, ensureBytes, inRange, numberToBytesBE, utf8ToBytes, } from "./utils.js";
|
||||
// Seems like generator was produced from some seed:
|
||||
// `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
|
||||
// // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
|
||||
const secp256k1_CURVE = {
|
||||
p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
|
||||
n: BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'),
|
||||
h: BigInt(1),
|
||||
a: BigInt(0),
|
||||
b: BigInt(7),
|
||||
Gx: BigInt('0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
|
||||
Gy: BigInt('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'),
|
||||
};
|
||||
const secp256k1_ENDO = {
|
||||
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
||||
basises: [
|
||||
[BigInt('0x3086d221a7d46bcde86c90e49284eb15'), -BigInt('0xe4437ed6010e88286f547fa90abfe4c3')],
|
||||
[BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8'), BigInt('0x3086d221a7d46bcde86c90e49284eb15')],
|
||||
],
|
||||
};
|
||||
const _0n = /* @__PURE__ */ BigInt(0);
|
||||
const _1n = /* @__PURE__ */ BigInt(1);
|
||||
const _2n = /* @__PURE__ */ BigInt(2);
|
||||
/**
|
||||
* √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.
|
||||
* (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
|
||||
*/
|
||||
function sqrtMod(y) {
|
||||
const P = secp256k1_CURVE.p;
|
||||
// prettier-ignore
|
||||
const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
|
||||
// prettier-ignore
|
||||
const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
|
||||
const b2 = (y * y * y) % P; // x^3, 11
|
||||
const b3 = (b2 * b2 * y) % P; // x^7
|
||||
const b6 = (pow2(b3, _3n, P) * b3) % P;
|
||||
const b9 = (pow2(b6, _3n, P) * b3) % P;
|
||||
const b11 = (pow2(b9, _2n, P) * b2) % P;
|
||||
const b22 = (pow2(b11, _11n, P) * b11) % P;
|
||||
const b44 = (pow2(b22, _22n, P) * b22) % P;
|
||||
const b88 = (pow2(b44, _44n, P) * b44) % P;
|
||||
const b176 = (pow2(b88, _88n, P) * b88) % P;
|
||||
const b220 = (pow2(b176, _44n, P) * b44) % P;
|
||||
const b223 = (pow2(b220, _3n, P) * b3) % P;
|
||||
const t1 = (pow2(b223, _23n, P) * b22) % P;
|
||||
const t2 = (pow2(t1, _6n, P) * b2) % P;
|
||||
const root = pow2(t2, _2n, P);
|
||||
if (!Fpk1.eql(Fpk1.sqr(root), y))
|
||||
throw new Error('Cannot find square root');
|
||||
return root;
|
||||
}
|
||||
const Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
|
||||
/**
|
||||
* secp256k1 curve, ECDSA and ECDH methods.
|
||||
*
|
||||
* Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* import { secp256k1 } from '@noble/curves/secp256k1';
|
||||
* const { secretKey, publicKey } = secp256k1.keygen();
|
||||
* const msg = new TextEncoder().encode('hello');
|
||||
* const sig = secp256k1.sign(msg, secretKey);
|
||||
* const isValid = secp256k1.verify(sig, msg, publicKey) === true;
|
||||
* ```
|
||||
*/
|
||||
export const secp256k1 = createCurve({ ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO }, sha256);
|
||||
// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
||||
/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
|
||||
const TAGGED_HASH_PREFIXES = {};
|
||||
function taggedHash(tag, ...messages) {
|
||||
let tagP = TAGGED_HASH_PREFIXES[tag];
|
||||
if (tagP === undefined) {
|
||||
const tagH = sha256(utf8ToBytes(tag));
|
||||
tagP = concatBytes(tagH, tagH);
|
||||
TAGGED_HASH_PREFIXES[tag] = tagP;
|
||||
}
|
||||
return sha256(concatBytes(tagP, ...messages));
|
||||
}
|
||||
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
|
||||
const pointToBytes = (point) => point.toBytes(true).slice(1);
|
||||
const Pointk1 = /* @__PURE__ */ (() => secp256k1.Point)();
|
||||
const hasEven = (y) => y % _2n === _0n;
|
||||
// Calculate point, scalar and bytes
|
||||
function schnorrGetExtPubKey(priv) {
|
||||
const { Fn, BASE } = Pointk1;
|
||||
const d_ = _normFnElement(Fn, priv);
|
||||
const p = BASE.multiply(d_); // P = d'⋅G; 0 < d' < n check is done inside
|
||||
const scalar = hasEven(p.y) ? d_ : Fn.neg(d_);
|
||||
return { scalar, bytes: pointToBytes(p) };
|
||||
}
|
||||
/**
|
||||
* lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point.
|
||||
* @returns valid point checked for being on-curve
|
||||
*/
|
||||
function lift_x(x) {
|
||||
const Fp = Fpk1;
|
||||
if (!Fp.isValidNot0(x))
|
||||
throw new Error('invalid x: Fail if x ≥ p');
|
||||
const xx = Fp.create(x * x);
|
||||
const c = Fp.create(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
|
||||
let y = Fp.sqrt(c); // Let y = c^(p+1)/4 mod p. Same as sqrt().
|
||||
// Return the unique point P such that x(P) = x and
|
||||
// y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
||||
if (!hasEven(y))
|
||||
y = Fp.neg(y);
|
||||
const p = Pointk1.fromAffine({ x, y });
|
||||
p.assertValidity();
|
||||
return p;
|
||||
}
|
||||
const num = bytesToNumberBE;
|
||||
/**
|
||||
* Create tagged hash, convert it to bigint, reduce modulo-n.
|
||||
*/
|
||||
function challenge(...args) {
|
||||
return Pointk1.Fn.create(num(taggedHash('BIP0340/challenge', ...args)));
|
||||
}
|
||||
/**
|
||||
* Schnorr public key is just `x` coordinate of Point as per BIP340.
|
||||
*/
|
||||
function schnorrGetPublicKey(secretKey) {
|
||||
return schnorrGetExtPubKey(secretKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
||||
}
|
||||
/**
|
||||
* Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
||||
* auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.
|
||||
*/
|
||||
function schnorrSign(message, secretKey, auxRand = randomBytes(32)) {
|
||||
const { Fn } = Pointk1;
|
||||
const m = ensureBytes('message', message);
|
||||
const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey); // checks for isWithinCurveOrder
|
||||
const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array
|
||||
const t = Fn.toBytes(d ^ num(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
||||
const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
||||
// Let k' = int(rand) mod n. Fail if k' = 0. Let R = k'⋅G
|
||||
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(rand);
|
||||
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
||||
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
||||
sig.set(rx, 0);
|
||||
sig.set(Fn.toBytes(Fn.create(k + e * d)), 32);
|
||||
// If Verify(bytes(P), m, sig) (see below) returns failure, abort
|
||||
if (!schnorrVerify(sig, m, px))
|
||||
throw new Error('sign: Invalid signature produced');
|
||||
return sig;
|
||||
}
|
||||
/**
|
||||
* Verifies Schnorr signature.
|
||||
* Will swallow errors & return false except for initial type validation of arguments.
|
||||
*/
|
||||
function schnorrVerify(signature, message, publicKey) {
|
||||
const { Fn, BASE } = Pointk1;
|
||||
const sig = ensureBytes('signature', signature, 64);
|
||||
const m = ensureBytes('message', message);
|
||||
const pub = ensureBytes('publicKey', publicKey, 32);
|
||||
try {
|
||||
const P = lift_x(num(pub)); // P = lift_x(int(pk)); fail if that fails
|
||||
const r = num(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
||||
if (!inRange(r, _1n, secp256k1_CURVE.p))
|
||||
return false;
|
||||
const s = num(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
||||
if (!inRange(s, _1n, secp256k1_CURVE.n))
|
||||
return false;
|
||||
// int(challenge(bytes(r)||bytes(P)||m))%n
|
||||
const e = challenge(Fn.toBytes(r), pointToBytes(P), m);
|
||||
// R = s⋅G - e⋅P, where -eP == (n-e)P
|
||||
const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
|
||||
const { x, y } = R.toAffine();
|
||||
// Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.
|
||||
if (R.is0() || !hasEven(y) || x !== r)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Schnorr signatures over secp256k1.
|
||||
* https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
||||
* @example
|
||||
* ```js
|
||||
* import { schnorr } from '@noble/curves/secp256k1';
|
||||
* const { secretKey, publicKey } = schnorr.keygen();
|
||||
* // const publicKey = schnorr.getPublicKey(secretKey);
|
||||
* const msg = new TextEncoder().encode('hello');
|
||||
* const sig = schnorr.sign(msg, secretKey);
|
||||
* const isValid = schnorr.verify(sig, msg, publicKey);
|
||||
* ```
|
||||
*/
|
||||
export const schnorr = /* @__PURE__ */ (() => {
|
||||
const size = 32;
|
||||
const seedLength = 48;
|
||||
const randomSecretKey = (seed = randomBytes(seedLength)) => {
|
||||
return mapHashToField(seed, secp256k1_CURVE.n);
|
||||
};
|
||||
// TODO: remove
|
||||
secp256k1.utils.randomSecretKey;
|
||||
function keygen(seed) {
|
||||
const secretKey = randomSecretKey(seed);
|
||||
return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };
|
||||
}
|
||||
return {
|
||||
keygen,
|
||||
getPublicKey: schnorrGetPublicKey,
|
||||
sign: schnorrSign,
|
||||
verify: schnorrVerify,
|
||||
Point: Pointk1,
|
||||
utils: {
|
||||
randomSecretKey: randomSecretKey,
|
||||
randomPrivateKey: randomSecretKey,
|
||||
taggedHash,
|
||||
// TODO: remove
|
||||
lift_x,
|
||||
pointToBytes,
|
||||
numberToBytesBE,
|
||||
bytesToNumberBE,
|
||||
mod,
|
||||
},
|
||||
lengths: {
|
||||
secretKey: size,
|
||||
publicKey: size,
|
||||
publicKeyHasPrefix: false,
|
||||
signature: size * 2,
|
||||
seed: seedLength,
|
||||
},
|
||||
};
|
||||
})();
|
||||
const isoMap = /* @__PURE__ */ (() => isogenyMap(Fpk1, [
|
||||
// xNum
|
||||
[
|
||||
'0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7',
|
||||
'0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581',
|
||||
'0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262',
|
||||
'0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c',
|
||||
],
|
||||
// xDen
|
||||
[
|
||||
'0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b',
|
||||
'0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14',
|
||||
'0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1
|
||||
],
|
||||
// yNum
|
||||
[
|
||||
'0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c',
|
||||
'0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3',
|
||||
'0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931',
|
||||
'0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84',
|
||||
],
|
||||
// yDen
|
||||
[
|
||||
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b',
|
||||
'0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573',
|
||||
'0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f',
|
||||
'0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1
|
||||
],
|
||||
].map((i) => i.map((j) => BigInt(j)))))();
|
||||
const mapSWU = /* @__PURE__ */ (() => mapToCurveSimpleSWU(Fpk1, {
|
||||
A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'),
|
||||
B: BigInt('1771'),
|
||||
Z: Fpk1.create(BigInt('-11')),
|
||||
}))();
|
||||
/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */
|
||||
export const secp256k1_hasher = /* @__PURE__ */ (() => createHasher(secp256k1.Point, (scalars) => {
|
||||
const { x, y } = mapSWU(Fpk1.create(scalars[0]));
|
||||
return isoMap(x, y);
|
||||
}, {
|
||||
DST: 'secp256k1_XMD:SHA-256_SSWU_RO_',
|
||||
encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_',
|
||||
p: Fpk1.ORDER,
|
||||
m: 1,
|
||||
k: 128,
|
||||
expand: 'xmd',
|
||||
hash: sha256,
|
||||
}))();
|
||||
/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */
|
||||
export const hashToCurve = /* @__PURE__ */ (() => secp256k1_hasher.hashToCurve)();
|
||||
/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */
|
||||
export const encodeToCurve = /* @__PURE__ */ (() => secp256k1_hasher.encodeToCurve)();
|
||||
//# sourceMappingURL=secp256k1.js.map
|
||||
@@ -0,0 +1,6 @@
|
||||
type DecodeOptions = Parameters<TextDecoder["decode"]>[1];
|
||||
export declare class Wtf8Decoder extends TextDecoder {
|
||||
decode(input?: NodeJS.AllowSharedBufferSource, options?: DecodeOptions): string;
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=wtf8.d.ts.map
|
||||
@@ -0,0 +1,386 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const scope_manager_1 = require("@typescript-eslint/scope-manager");
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const util_1 = require("../util");
|
||||
const explicitReturnTypeUtils_1 = require("../util/explicitReturnTypeUtils");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'explicit-module-boundary-types',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: "Require explicit return and argument types on exported functions' and classes' public class methods",
|
||||
},
|
||||
messages: {
|
||||
anyTypedArg: "Argument '{{name}}' should be typed with a non-any type.",
|
||||
anyTypedArgUnnamed: '{{type}} argument should be typed with a non-any type.',
|
||||
missingArgType: "Argument '{{name}}' should be typed.",
|
||||
missingArgTypeUnnamed: '{{type}} argument should be typed.',
|
||||
missingReturnType: 'Missing return type on function.',
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
allowArgumentsExplicitlyTypedAsAny: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore arguments that are explicitly typed as `any`.',
|
||||
},
|
||||
allowDirectConstAssertionInArrowFunctions: {
|
||||
type: 'boolean',
|
||||
description: [
|
||||
'Whether to ignore return type annotations on body-less arrow functions that return an `as const` type assertion.',
|
||||
'You must still type the parameters of the function.',
|
||||
].join('\n'),
|
||||
},
|
||||
allowedNames: {
|
||||
type: 'array',
|
||||
description: 'An array of function/method names that will not have their arguments or return values checked.',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
allowHigherOrderFunctions: {
|
||||
type: 'boolean',
|
||||
description: [
|
||||
'Whether to ignore return type annotations on functions immediately returning another function expression.',
|
||||
'You must still type the parameters of the function.',
|
||||
].join('\n'),
|
||||
},
|
||||
allowOverloadFunctions: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore return type annotations on functions with overload signatures.',
|
||||
},
|
||||
allowTypedFunctionExpressions: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore type annotations on the variable of a function expression.',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultOptions: [
|
||||
{
|
||||
allowArgumentsExplicitlyTypedAsAny: false,
|
||||
allowDirectConstAssertionInArrowFunctions: true,
|
||||
allowedNames: [],
|
||||
allowHigherOrderFunctions: true,
|
||||
allowOverloadFunctions: false,
|
||||
allowTypedFunctionExpressions: true,
|
||||
},
|
||||
],
|
||||
create(context, [options]) {
|
||||
// tracks all of the functions we've already checked
|
||||
const checkedFunctions = new Set();
|
||||
const functionStack = [];
|
||||
const functionReturnsMap = new Map();
|
||||
// all nodes visited, avoids infinite recursion for cyclic references
|
||||
// (such as class member referring to itself)
|
||||
const alreadyVisited = new Set();
|
||||
function getReturnsInFunction(node) {
|
||||
return functionReturnsMap.get(node) ?? [];
|
||||
}
|
||||
function enterFunction(node) {
|
||||
functionStack.push(node);
|
||||
functionReturnsMap.set(node, []);
|
||||
}
|
||||
function exitFunction() {
|
||||
functionStack.pop();
|
||||
}
|
||||
/*
|
||||
# How the rule works:
|
||||
|
||||
As the rule traverses the AST, it immediately checks every single function that it finds is exported.
|
||||
"exported" means that it is either directly exported, or that its name is exported.
|
||||
|
||||
It also collects a list of every single function it finds on the way, but does not check them.
|
||||
After it's finished traversing the AST, it then iterates through the list of found functions, and checks to see if
|
||||
any of them are part of a higher-order function
|
||||
*/
|
||||
return {
|
||||
'ArrowFunctionExpression, FunctionDeclaration, FunctionExpression': enterFunction,
|
||||
'ArrowFunctionExpression:exit': exitFunction,
|
||||
'ExportDefaultDeclaration:exit'(node) {
|
||||
checkNode(node.declaration);
|
||||
},
|
||||
'ExportNamedDeclaration:not([source]):exit'(node) {
|
||||
if (node.declaration) {
|
||||
checkNode(node.declaration);
|
||||
}
|
||||
else {
|
||||
for (const specifier of node.specifiers) {
|
||||
followReference(specifier.local);
|
||||
}
|
||||
}
|
||||
},
|
||||
'FunctionDeclaration:exit': exitFunction,
|
||||
'FunctionExpression:exit': exitFunction,
|
||||
'Program:exit'() {
|
||||
for (const [node, returns] of functionReturnsMap) {
|
||||
if (isExportedHigherOrderFunction({ node, returns })) {
|
||||
checkNode(node);
|
||||
}
|
||||
}
|
||||
},
|
||||
ReturnStatement(node) {
|
||||
const current = functionStack[functionStack.length - 1];
|
||||
functionReturnsMap.get(current)?.push(node);
|
||||
},
|
||||
'TSExportAssignment:exit'(node) {
|
||||
checkNode(node.expression);
|
||||
},
|
||||
};
|
||||
function checkParameters(node) {
|
||||
function checkParameter(param) {
|
||||
function report(namedMessageId, unnamedMessageId) {
|
||||
if (param.type === utils_1.AST_NODE_TYPES.Identifier) {
|
||||
context.report({
|
||||
node: param,
|
||||
messageId: namedMessageId,
|
||||
data: { name: param.name },
|
||||
});
|
||||
}
|
||||
else if (param.type === utils_1.AST_NODE_TYPES.ArrayPattern) {
|
||||
context.report({
|
||||
node: param,
|
||||
messageId: unnamedMessageId,
|
||||
data: { type: 'Array pattern' },
|
||||
});
|
||||
}
|
||||
else if (param.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
|
||||
context.report({
|
||||
node: param,
|
||||
messageId: unnamedMessageId,
|
||||
data: { type: 'Object pattern' },
|
||||
});
|
||||
}
|
||||
else if (param.type === utils_1.AST_NODE_TYPES.RestElement) {
|
||||
if (param.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
|
||||
context.report({
|
||||
node: param,
|
||||
messageId: namedMessageId,
|
||||
data: { name: param.argument.name },
|
||||
});
|
||||
}
|
||||
else {
|
||||
context.report({
|
||||
node: param,
|
||||
messageId: unnamedMessageId,
|
||||
data: { type: 'Rest' },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (param.type) {
|
||||
case utils_1.AST_NODE_TYPES.ArrayPattern:
|
||||
case utils_1.AST_NODE_TYPES.Identifier:
|
||||
case utils_1.AST_NODE_TYPES.ObjectPattern:
|
||||
case utils_1.AST_NODE_TYPES.RestElement:
|
||||
if (!param.typeAnnotation) {
|
||||
report('missingArgType', 'missingArgTypeUnnamed');
|
||||
}
|
||||
else if (options.allowArgumentsExplicitlyTypedAsAny !== true &&
|
||||
param.typeAnnotation.typeAnnotation.type ===
|
||||
utils_1.AST_NODE_TYPES.TSAnyKeyword) {
|
||||
report('anyTypedArg', 'anyTypedArgUnnamed');
|
||||
}
|
||||
return;
|
||||
case utils_1.AST_NODE_TYPES.TSParameterProperty:
|
||||
return checkParameter(param.parameter);
|
||||
case utils_1.AST_NODE_TYPES.AssignmentPattern: // ignored as it has a type via its assignment
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (const arg of node.params) {
|
||||
checkParameter(arg);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if a function name is allowed and should not be checked.
|
||||
*/
|
||||
function isAllowedName(node) {
|
||||
if (!node || !options.allowedNames || options.allowedNames.length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclarator ||
|
||||
node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
|
||||
return (node.id?.type === utils_1.AST_NODE_TYPES.Identifier &&
|
||||
options.allowedNames.includes(node.id.name));
|
||||
}
|
||||
if (node.type === utils_1.AST_NODE_TYPES.MethodDefinition ||
|
||||
node.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition ||
|
||||
(node.type === utils_1.AST_NODE_TYPES.Property && node.method) ||
|
||||
node.type === utils_1.AST_NODE_TYPES.PropertyDefinition ||
|
||||
node.type === utils_1.AST_NODE_TYPES.AccessorProperty) {
|
||||
return (0, util_1.isStaticMemberAccessOfValue)(node, context, ...options.allowedNames);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isExportedHigherOrderFunction({ node, }) {
|
||||
let current = node.parent;
|
||||
while (current) {
|
||||
if (current.type === utils_1.AST_NODE_TYPES.ReturnStatement) {
|
||||
// the parent of a return will always be a block statement, so we can skip over it
|
||||
current = current.parent.parent;
|
||||
continue;
|
||||
}
|
||||
if (!(0, util_1.isFunction)(current)) {
|
||||
return false;
|
||||
}
|
||||
const returns = getReturnsInFunction(current);
|
||||
if (!(0, explicitReturnTypeUtils_1.doesImmediatelyReturnFunctionExpression)({ node: current, returns })) {
|
||||
return false;
|
||||
}
|
||||
if (checkedFunctions.has(current)) {
|
||||
return true;
|
||||
}
|
||||
current = current.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function followReference(node) {
|
||||
const scope = context.sourceCode.getScope(node);
|
||||
const variable = scope.set.get(node.name);
|
||||
/* istanbul ignore if */ if (!variable) {
|
||||
return;
|
||||
}
|
||||
// check all of the definitions
|
||||
for (const definition of variable.defs) {
|
||||
// cases we don't care about in this rule
|
||||
if ([
|
||||
scope_manager_1.DefinitionType.CatchClause,
|
||||
scope_manager_1.DefinitionType.ImplicitGlobalVariable,
|
||||
scope_manager_1.DefinitionType.ImportBinding,
|
||||
scope_manager_1.DefinitionType.Parameter,
|
||||
].includes(definition.type)) {
|
||||
continue;
|
||||
}
|
||||
checkNode(definition.node);
|
||||
}
|
||||
// follow references to find writes to the variable
|
||||
for (const reference of variable.references) {
|
||||
if (
|
||||
// we don't want to check the initialization ref, as this is handled by the declaration check
|
||||
!reference.init &&
|
||||
reference.writeExpr) {
|
||||
checkNode(reference.writeExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
function checkNode(node) {
|
||||
if (node == null || alreadyVisited.has(node)) {
|
||||
return;
|
||||
}
|
||||
alreadyVisited.add(node);
|
||||
switch (node.type) {
|
||||
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
||||
case utils_1.AST_NODE_TYPES.FunctionExpression: {
|
||||
const returns = getReturnsInFunction(node);
|
||||
return checkFunctionExpression({ node, returns });
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.ArrayExpression:
|
||||
for (const element of node.elements) {
|
||||
checkNode(element);
|
||||
}
|
||||
return;
|
||||
case utils_1.AST_NODE_TYPES.PropertyDefinition:
|
||||
case utils_1.AST_NODE_TYPES.AccessorProperty:
|
||||
case utils_1.AST_NODE_TYPES.MethodDefinition:
|
||||
case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
|
||||
if (node.accessibility === 'private' ||
|
||||
node.key.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
||||
return;
|
||||
}
|
||||
return checkNode(node.value);
|
||||
case utils_1.AST_NODE_TYPES.ClassDeclaration:
|
||||
case utils_1.AST_NODE_TYPES.ClassExpression:
|
||||
for (const element of node.body.body) {
|
||||
checkNode(element);
|
||||
}
|
||||
return;
|
||||
case utils_1.AST_NODE_TYPES.FunctionDeclaration: {
|
||||
const returns = getReturnsInFunction(node);
|
||||
return checkFunction({ node, returns });
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.Identifier:
|
||||
return followReference(node);
|
||||
case utils_1.AST_NODE_TYPES.ObjectExpression:
|
||||
for (const property of node.properties) {
|
||||
checkNode(property);
|
||||
}
|
||||
return;
|
||||
case utils_1.AST_NODE_TYPES.Property:
|
||||
return checkNode(node.value);
|
||||
case utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression:
|
||||
return checkEmptyBodyFunctionExpression(node);
|
||||
case utils_1.AST_NODE_TYPES.VariableDeclaration:
|
||||
for (const declaration of node.declarations) {
|
||||
checkNode(declaration);
|
||||
}
|
||||
return;
|
||||
case utils_1.AST_NODE_TYPES.VariableDeclarator:
|
||||
return checkNode(node.init);
|
||||
}
|
||||
}
|
||||
function checkEmptyBodyFunctionExpression(node) {
|
||||
const isConstructor = node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
|
||||
node.parent.kind === 'constructor';
|
||||
const isSetAccessor = (node.parent.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition ||
|
||||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) &&
|
||||
node.parent.kind === 'set';
|
||||
if (!isConstructor && !isSetAccessor && !node.returnType) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'missingReturnType',
|
||||
});
|
||||
}
|
||||
checkParameters(node);
|
||||
}
|
||||
function checkFunctionExpression({ node, returns, }) {
|
||||
if (checkedFunctions.has(node)) {
|
||||
return;
|
||||
}
|
||||
checkedFunctions.add(node);
|
||||
if (isAllowedName(node.parent) ||
|
||||
(0, explicitReturnTypeUtils_1.isTypedFunctionExpression)(node, options) ||
|
||||
(0, explicitReturnTypeUtils_1.ancestorHasReturnType)(node)) {
|
||||
return;
|
||||
}
|
||||
if (options.allowOverloadFunctions &&
|
||||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
|
||||
(0, util_1.hasOverloadSignatures)(node.parent, context)) {
|
||||
return;
|
||||
}
|
||||
(0, explicitReturnTypeUtils_1.checkFunctionExpressionReturnType)({ node, returns }, options, context.sourceCode, loc => {
|
||||
context.report({
|
||||
loc,
|
||||
node,
|
||||
messageId: 'missingReturnType',
|
||||
});
|
||||
});
|
||||
checkParameters(node);
|
||||
}
|
||||
function checkFunction({ node, returns, }) {
|
||||
if (checkedFunctions.has(node)) {
|
||||
return;
|
||||
}
|
||||
checkedFunctions.add(node);
|
||||
if (isAllowedName(node) || (0, explicitReturnTypeUtils_1.ancestorHasReturnType)(node)) {
|
||||
return;
|
||||
}
|
||||
if (options.allowOverloadFunctions &&
|
||||
(0, util_1.hasOverloadSignatures)(node, context)) {
|
||||
return;
|
||||
}
|
||||
(0, explicitReturnTypeUtils_1.checkFunctionReturnType)({ node, returns }, options, context.sourceCode, loc => {
|
||||
context.report({
|
||||
loc,
|
||||
node,
|
||||
messageId: 'missingReturnType',
|
||||
});
|
||||
});
|
||||
checkParameters(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,336 @@
|
||||
'use strict';
|
||||
|
||||
var has = Object.prototype.hasOwnProperty
|
||||
, prefix = '~';
|
||||
|
||||
/**
|
||||
* Constructor to create a storage for our `EE` objects.
|
||||
* An `Events` instance is a plain object whose properties are event names.
|
||||
*
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
function Events() {}
|
||||
|
||||
//
|
||||
// We try to not inherit from `Object.prototype`. In some engines creating an
|
||||
// instance in this way is faster than calling `Object.create(null)` directly.
|
||||
// If `Object.create(null)` is not supported we prefix the event names with a
|
||||
// character to make sure that the built-in object properties are not
|
||||
// overridden or used as an attack vector.
|
||||
//
|
||||
if (Object.create) {
|
||||
Events.prototype = Object.create(null);
|
||||
|
||||
//
|
||||
// This hack is needed because the `__proto__` property is still inherited in
|
||||
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
||||
//
|
||||
if (!new Events().__proto__) prefix = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of a single event listener.
|
||||
*
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
function EE(fn, context, once) {
|
||||
this.fn = fn;
|
||||
this.context = context;
|
||||
this.once = once || false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} once Specify if the listener is a one-time listener.
|
||||
* @returns {EventEmitter}
|
||||
* @private
|
||||
*/
|
||||
function addListener(emitter, event, fn, context, once) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('The listener must be a function');
|
||||
}
|
||||
|
||||
var listener = new EE(fn, context || emitter, once)
|
||||
, evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
||||
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
||||
else emitter._events[evt] = [emitter._events[evt], listener];
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear event by name.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} evt The Event name.
|
||||
* @private
|
||||
*/
|
||||
function clearEvent(emitter, evt) {
|
||||
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
||||
else delete emitter._events[evt];
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal `EventEmitter` interface that is molded against the Node.js
|
||||
* `EventEmitter` interface.
|
||||
*
|
||||
* @constructor
|
||||
* @public
|
||||
*/
|
||||
function EventEmitter() {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array listing the events for which the emitter has registered
|
||||
* listeners.
|
||||
*
|
||||
* @returns {Array}
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
var names = []
|
||||
, events
|
||||
, name;
|
||||
|
||||
if (this._eventsCount === 0) return names;
|
||||
|
||||
for (name in (events = this._events)) {
|
||||
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
return names.concat(Object.getOwnPropertySymbols(events));
|
||||
}
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Array} The registered listeners.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.listeners = function listeners(event) {
|
||||
var evt = prefix ? prefix + event : event
|
||||
, handlers = this._events[evt];
|
||||
|
||||
if (!handlers) return [];
|
||||
if (handlers.fn) return [handlers.fn];
|
||||
|
||||
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
||||
ee[i] = handlers[i].fn;
|
||||
}
|
||||
|
||||
return ee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the number of listeners listening to a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Number} The number of listeners.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
||||
var evt = prefix ? prefix + event : event
|
||||
, listeners = this._events[evt];
|
||||
|
||||
if (!listeners) return 0;
|
||||
if (listeners.fn) return 1;
|
||||
return listeners.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls each of the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!this._events[evt]) return false;
|
||||
|
||||
var listeners = this._events[evt]
|
||||
, len = arguments.length
|
||||
, args
|
||||
, i;
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1: return listeners.fn.call(listeners.context), true;
|
||||
case 2: return listeners.fn.call(listeners.context, a1), true;
|
||||
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
|
||||
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
||||
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
||||
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
||||
}
|
||||
|
||||
for (i = 1, args = new Array(len -1); i < len; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
listeners.fn.apply(listeners.context, args);
|
||||
} else {
|
||||
var length = listeners.length
|
||||
, j;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1: listeners[i].fn.call(listeners[i].context); break;
|
||||
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
|
||||
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
|
||||
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
|
||||
default:
|
||||
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
|
||||
args[j - 1] = arguments[j];
|
||||
}
|
||||
|
||||
listeners[i].fn.apply(listeners[i].context, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.on = function on(event, fn, context) {
|
||||
return addListener(this, event, fn, context, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a one-time listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.once = function once(event, fn, context) {
|
||||
return addListener(this, event, fn, context, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the listeners of a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn Only remove the listeners that match this function.
|
||||
* @param {*} context Only remove the listeners that have this context.
|
||||
* @param {Boolean} once Only remove one-time listeners.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
|
||||
if (!this._events[evt]) return this;
|
||||
if (!fn) {
|
||||
clearEvent(this, evt);
|
||||
return this;
|
||||
}
|
||||
|
||||
var listeners = this._events[evt];
|
||||
|
||||
if (listeners.fn) {
|
||||
if (
|
||||
listeners.fn === fn &&
|
||||
(!once || listeners.once) &&
|
||||
(!context || listeners.context === context)
|
||||
) {
|
||||
clearEvent(this, evt);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
||||
if (
|
||||
listeners[i].fn !== fn ||
|
||||
(once && !listeners[i].once) ||
|
||||
(context && listeners[i].context !== context)
|
||||
) {
|
||||
events.push(listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the array, or remove it completely if we have no more listeners.
|
||||
//
|
||||
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
|
||||
else clearEvent(this, evt);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove all listeners, or those of the specified event.
|
||||
*
|
||||
* @param {(String|Symbol)} [event] The event name.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
||||
var evt;
|
||||
|
||||
if (event) {
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (this._events[evt]) clearEvent(this, evt);
|
||||
} else {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// Alias methods names because people roll like that.
|
||||
//
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
|
||||
|
||||
//
|
||||
// Expose the prefix.
|
||||
//
|
||||
EventEmitter.prefixed = prefix;
|
||||
|
||||
//
|
||||
// Allow `EventEmitter` to be imported as module namespace.
|
||||
//
|
||||
EventEmitter.EventEmitter = EventEmitter;
|
||||
|
||||
//
|
||||
// Expose the module.
|
||||
//
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = EventEmitter;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
declare module 'path' {
|
||||
/**
|
||||
* A parsed path object generated by path.parse() or consumed by path.format().
|
||||
*/
|
||||
interface ParsedPath {
|
||||
/**
|
||||
* The root of the path such as '/' or 'c:\'
|
||||
*/
|
||||
root: string;
|
||||
/**
|
||||
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||
*/
|
||||
dir: string;
|
||||
/**
|
||||
* The file name including extension (if any) such as 'index.html'
|
||||
*/
|
||||
base: string;
|
||||
/**
|
||||
* The file extension (if any) such as '.html'
|
||||
*/
|
||||
ext: string;
|
||||
/**
|
||||
* The file name without extension (if any) such as 'index'
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
interface FormatInputPathObject {
|
||||
/**
|
||||
* The root of the path such as '/' or 'c:\'
|
||||
*/
|
||||
root?: string | undefined;
|
||||
/**
|
||||
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||
*/
|
||||
dir?: string | undefined;
|
||||
/**
|
||||
* The file name including extension (if any) such as 'index.html'
|
||||
*/
|
||||
base?: string | undefined;
|
||||
/**
|
||||
* The file extension (if any) such as '.html'
|
||||
*/
|
||||
ext?: string | undefined;
|
||||
/**
|
||||
* The file name without extension (if any) such as 'index'
|
||||
*/
|
||||
name?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a string path, reducing '..' and '.' parts.
|
||||
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
|
||||
*
|
||||
* @param p string path to normalize.
|
||||
*/
|
||||
function normalize(p: string): string;
|
||||
/**
|
||||
* Join all arguments together and normalize the resulting path.
|
||||
* Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
|
||||
*
|
||||
* @param paths paths to join.
|
||||
*/
|
||||
function join(...paths: string[]): string;
|
||||
/**
|
||||
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
|
||||
*
|
||||
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
|
||||
*
|
||||
* If {to} isn't already absolute, {from} arguments are prepended in right to left order,
|
||||
* until an absolute path is found. If after using all {from} paths still no absolute path is found,
|
||||
* the current working directory is used as well. The resulting path is normalized,
|
||||
* and trailing slashes are removed unless the path gets resolved to the root directory.
|
||||
*
|
||||
* @param pathSegments string paths to join. Non-string arguments are ignored.
|
||||
*/
|
||||
function resolve(...pathSegments: string[]): string;
|
||||
/**
|
||||
* Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
|
||||
*
|
||||
* @param path path to test.
|
||||
*/
|
||||
function isAbsolute(path: string): boolean;
|
||||
/**
|
||||
* Solve the relative path from {from} to {to}.
|
||||
* At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
|
||||
*/
|
||||
function relative(from: string, to: string): string;
|
||||
/**
|
||||
* Return the directory name of a path. Similar to the Unix dirname command.
|
||||
*
|
||||
* @param p the path to evaluate.
|
||||
*/
|
||||
function dirname(p: string): string;
|
||||
/**
|
||||
* Return the last portion of a path. Similar to the Unix basename command.
|
||||
* Often used to extract the file name from a fully qualified path.
|
||||
*
|
||||
* @param p the path to evaluate.
|
||||
* @param ext optionally, an extension to remove from the result.
|
||||
*/
|
||||
function basename(p: string, ext?: string): string;
|
||||
/**
|
||||
* Return the extension of the path, from the last '.' to end of string in the last portion of the path.
|
||||
* If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string
|
||||
*
|
||||
* @param p the path to evaluate.
|
||||
*/
|
||||
function extname(p: string): string;
|
||||
/**
|
||||
* The platform-specific file separator. '\\' or '/'.
|
||||
*/
|
||||
const sep: '\\' | '/';
|
||||
/**
|
||||
* The platform-specific file delimiter. ';' or ':'.
|
||||
*/
|
||||
const delimiter: ';' | ':';
|
||||
/**
|
||||
* Returns an object from a path string - the opposite of format().
|
||||
*
|
||||
* @param pathString path to evaluate.
|
||||
*/
|
||||
function parse(pathString: string): ParsedPath;
|
||||
/**
|
||||
* Returns a path string from an object - the opposite of parse().
|
||||
*
|
||||
* @param pathString path to evaluate.
|
||||
*/
|
||||
function format(pathObject: FormatInputPathObject): string;
|
||||
|
||||
namespace posix {
|
||||
function normalize(p: string): string;
|
||||
function join(...paths: string[]): string;
|
||||
function resolve(...pathSegments: string[]): string;
|
||||
function isAbsolute(p: string): boolean;
|
||||
function relative(from: string, to: string): string;
|
||||
function dirname(p: string): string;
|
||||
function basename(p: string, ext?: string): string;
|
||||
function extname(p: string): string;
|
||||
const sep: string;
|
||||
const delimiter: string;
|
||||
function parse(p: string): ParsedPath;
|
||||
function format(pP: FormatInputPathObject): string;
|
||||
}
|
||||
|
||||
namespace win32 {
|
||||
function normalize(p: string): string;
|
||||
function join(...paths: string[]): string;
|
||||
function resolve(...pathSegments: string[]): string;
|
||||
function isAbsolute(p: string): boolean;
|
||||
function relative(from: string, to: string): string;
|
||||
function dirname(p: string): string;
|
||||
function basename(p: string, ext?: string): string;
|
||||
function extname(p: string): string;
|
||||
const sep: string;
|
||||
const delimiter: string;
|
||||
function parse(p: string): ParsedPath;
|
||||
function format(pP: FormatInputPathObject): string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# `@typescript-eslint/parser`
|
||||
|
||||
> An ESLint parser which leverages <a href="https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/typescript-estree">TypeScript ESTree</a> to allow for ESLint to lint TypeScript source code.
|
||||
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/parser)
|
||||
[](https://www.npmjs.com/package/@typescript-eslint/parser)
|
||||
|
||||
👉 See **https://typescript-eslint.io/packages/parser** for documentation on this package.
|
||||
|
||||
> See https://typescript-eslint.io for general documentation on typescript-eslint, the tooling that allows you to run ESLint and Prettier on TypeScript code.
|
||||
|
||||
<!-- Local path for docs: docs/packages/Parser.mdx -->
|
||||
@@ -0,0 +1,112 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = prettifyObject
|
||||
|
||||
const {
|
||||
LOGGER_KEYS
|
||||
} = require('../constants')
|
||||
|
||||
const stringifySafe = require('fast-safe-stringify')
|
||||
const joinLinesWithIndentation = require('./join-lines-with-indentation')
|
||||
const prettifyError = require('./prettify-error')
|
||||
|
||||
/**
|
||||
* @typedef {object} PrettifyObjectParams
|
||||
* @property {object} log The object to prettify.
|
||||
* @property {boolean} [excludeLoggerKeys] Indicates if known logger specific
|
||||
* keys should be excluded from prettification. Default: `true`.
|
||||
* @property {string[]} [skipKeys] A set of object keys to exclude from the
|
||||
* * prettified result. Default: `[]`.
|
||||
* @property {PrettyContext} context The context object built from parsing
|
||||
* the options.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prettifies a standard object. Special care is taken when processing the object
|
||||
* to handle child objects that are attached to keys known to contain error
|
||||
* objects.
|
||||
*
|
||||
* @param {PrettifyObjectParams} input
|
||||
*
|
||||
* @returns {string} The prettified string. This can be as little as `''` if
|
||||
* there was nothing to prettify.
|
||||
*/
|
||||
function prettifyObject ({
|
||||
log,
|
||||
excludeLoggerKeys = true,
|
||||
skipKeys = [],
|
||||
context
|
||||
}) {
|
||||
const {
|
||||
EOL: eol,
|
||||
IDENT: ident,
|
||||
customPrettifiers,
|
||||
errorLikeObjectKeys: errorLikeKeys,
|
||||
objectColorizer,
|
||||
singleLine,
|
||||
colorizer
|
||||
} = context
|
||||
const keysToIgnore = [].concat(skipKeys)
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (excludeLoggerKeys === true) Array.prototype.push.apply(keysToIgnore, LOGGER_KEYS)
|
||||
|
||||
let result = ''
|
||||
|
||||
// Split object keys into two categories: error and non-error
|
||||
const { plain, errors } = Object.entries(log).reduce(({ plain, errors }, [k, v]) => {
|
||||
if (keysToIgnore.includes(k) === false) {
|
||||
// Pre-apply custom prettifiers, because all 3 cases below will need this
|
||||
const pretty = typeof customPrettifiers[k] === 'function'
|
||||
? customPrettifiers[k](v, k, log, { colors: colorizer.colors })
|
||||
: v
|
||||
if (errorLikeKeys.includes(k)) {
|
||||
errors[k] = pretty
|
||||
} else {
|
||||
plain[k] = pretty
|
||||
}
|
||||
}
|
||||
return { plain, errors }
|
||||
}, { plain: {}, errors: {} })
|
||||
|
||||
if (singleLine) {
|
||||
// Stringify the entire object as a single JSON line
|
||||
/* istanbul ignore else */
|
||||
if (Object.keys(plain).length > 0) {
|
||||
result += objectColorizer.greyMessage(stringifySafe(plain))
|
||||
}
|
||||
result += eol
|
||||
// Avoid printing the escape character on escaped backslashes.
|
||||
result = result.replace(/\\\\/gi, '\\')
|
||||
} else {
|
||||
// Put each object entry on its own line
|
||||
Object.entries(plain).forEach(([keyName, keyValue]) => {
|
||||
// custom prettifiers are already applied above, so we can skip it now
|
||||
let lines = typeof customPrettifiers[keyName] === 'function'
|
||||
? keyValue
|
||||
: stringifySafe(keyValue, null, 2)
|
||||
|
||||
if (lines === undefined) return
|
||||
|
||||
// Avoid printing the escape character on escaped backslashes.
|
||||
lines = lines.replace(/\\\\/gi, '\\')
|
||||
|
||||
const joinedLines = joinLinesWithIndentation({ input: lines, ident, eol })
|
||||
result += `${ident}${objectColorizer.property(keyName)}:${joinedLines.startsWith(eol) ? '' : ' '}${joinedLines}${eol}`
|
||||
})
|
||||
}
|
||||
|
||||
// Errors
|
||||
Object.entries(errors).forEach(([keyName, keyValue]) => {
|
||||
// custom prettifiers are already applied above, so we can skip it now
|
||||
const lines = typeof customPrettifiers[keyName] === 'function'
|
||||
? keyValue
|
||||
: stringifySafe(keyValue, null, 2)
|
||||
|
||||
if (lines === undefined) return
|
||||
|
||||
result += prettifyError({ keyName, lines, eol, ident })
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
45678
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
var stringify = require('../');
|
||||
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.key < b.key ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
@@ -0,0 +1,47 @@
|
||||
# `siginfo`
|
||||
|
||||
[](https://travis-ci.org/eemilbayes/siginfo)
|
||||
|
||||
> Utility module to print pretty messages on SIGINFO/SIGUSR1
|
||||
|
||||
`SIGINFO` on BSD / macOS and `SIGUSR1` on Linux, usually triggered by
|
||||
`Ctrl + T`, are by convention used to print information about
|
||||
a long running process internal state. Eg. `dd` will tell you how many blocks it
|
||||
has written and at what speed, while `xz` will tell you progress, compression
|
||||
ratio and estimated time remaining.
|
||||
|
||||
This module wraps both signals, checks if the process is connected to TTY and
|
||||
lets you do whatever you want.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var siginfo = require('siginfo')
|
||||
var pkg = require('./package.json')
|
||||
|
||||
siginfo(function () {
|
||||
console.dir({
|
||||
version: pkg.version,
|
||||
uptime: process.uptime()
|
||||
})
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `var removeListener = siginfo(queryFn, [force])`
|
||||
|
||||
`queryFn` can be used for whatever you want (logging, sending a UDP message, etc.).
|
||||
Setting `force = true` will attach the event handlers whether a TTY is present
|
||||
or not.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install siginfo
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[ISC](LICENSE)
|
||||
@@ -0,0 +1,21 @@
|
||||
This software is released under the MIT license:
|
||||
|
||||
Copyright (c) 2017 Evgeny Poberezkin
|
||||
Copyright (c) 2013 James Halliday
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const es2020_symbol_wellknown: LibDefinition;
|
||||
@@ -0,0 +1,289 @@
|
||||
export interface BundleOptions {
|
||||
intro?: string;
|
||||
separator?: string;
|
||||
}
|
||||
|
||||
export interface SourceMapOptions {
|
||||
/**
|
||||
* Whether the mapping should be high-resolution.
|
||||
* Hi-res mappings map every single character, meaning (for example) your devtools will always
|
||||
* be able to pinpoint the exact location of function calls and so on.
|
||||
* With lo-res mappings, devtools may only be able to identify the correct
|
||||
* line - but they're quicker to generate and less bulky.
|
||||
* You can also set `"boundary"` to generate a semi-hi-res mappings segmented per word boundary
|
||||
* instead of per character, suitable for string semantics that are separated by words.
|
||||
* If sourcemap locations have been specified with s.addSourceMapLocation(), they will be used here.
|
||||
*/
|
||||
hires?: boolean | 'boundary';
|
||||
/**
|
||||
* The filename where you plan to write the sourcemap.
|
||||
*/
|
||||
file?: string;
|
||||
/**
|
||||
* The filename of the file containing the original source.
|
||||
*/
|
||||
source?: string;
|
||||
/**
|
||||
* Whether to include the original content in the map's sourcesContent array.
|
||||
*/
|
||||
includeContent?: boolean;
|
||||
}
|
||||
|
||||
export type SourceMapSegment =
|
||||
| [number]
|
||||
| [number, number, number, number]
|
||||
| [number, number, number, number, number];
|
||||
|
||||
export interface DecodedSourceMap {
|
||||
file: string;
|
||||
sources: string[];
|
||||
sourcesContent?: string[];
|
||||
names: string[];
|
||||
mappings: SourceMapSegment[][];
|
||||
x_google_ignoreList?: number[];
|
||||
}
|
||||
|
||||
export class SourceMap {
|
||||
constructor(properties: DecodedSourceMap);
|
||||
|
||||
version: number;
|
||||
file: string;
|
||||
sources: string[];
|
||||
sourcesContent?: string[];
|
||||
names: string[];
|
||||
mappings: string;
|
||||
x_google_ignoreList?: number[];
|
||||
debugId?: string;
|
||||
|
||||
/**
|
||||
* Returns the equivalent of `JSON.stringify(map)`
|
||||
*/
|
||||
toString(): string;
|
||||
/**
|
||||
* Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:
|
||||
* `generateMap(options?: SourceMapOptions): SourceMap;`
|
||||
*/
|
||||
toUrl(): string;
|
||||
}
|
||||
|
||||
export class Bundle {
|
||||
constructor(options?: BundleOptions);
|
||||
/**
|
||||
* Adds the specified source to the bundle, which can either be a `MagicString` object directly,
|
||||
* or an options object that holds a magic string `content` property and optionally provides
|
||||
* a `filename` for the source within the bundle, as well as an optional `ignoreList` hint
|
||||
* (which defaults to `false`). The `filename` is used when constructing the source map for the
|
||||
* bundle, to identify this `source` in the source map's `sources` field. The `ignoreList` hint
|
||||
* is used to populate the `x_google_ignoreList` extension field in the source map, which is a
|
||||
* mechanism for tools to signal to debuggers that certain sources should be ignored by default
|
||||
* (depending on user preferences).
|
||||
*/
|
||||
addSource(
|
||||
source: MagicString | { filename?: string; content: MagicString; ignoreList?: boolean },
|
||||
): this;
|
||||
append(str: string, options?: BundleOptions): this;
|
||||
clone(): this;
|
||||
generateMap(
|
||||
options?: SourceMapOptions,
|
||||
): Omit<SourceMap, 'sourcesContent'> & { sourcesContent: Array<string | null> };
|
||||
generateDecodedMap(
|
||||
options?: SourceMapOptions,
|
||||
): Omit<DecodedSourceMap, 'sourcesContent'> & { sourcesContent: Array<string | null> };
|
||||
getIndentString(): string;
|
||||
indent(indentStr?: string): this;
|
||||
indentExclusionRanges: ExclusionRange | Array<ExclusionRange>;
|
||||
prepend(str: string): this;
|
||||
toString(): string;
|
||||
trimLines(): this;
|
||||
trim(charType?: string): this;
|
||||
trimStart(charType?: string): this;
|
||||
trimEnd(charType?: string): this;
|
||||
isEmpty(): boolean;
|
||||
length(): number;
|
||||
}
|
||||
|
||||
export type ExclusionRange = [number, number];
|
||||
|
||||
export interface MagicStringOptions {
|
||||
filename?: string;
|
||||
indentExclusionRanges?: ExclusionRange | Array<ExclusionRange>;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface IndentOptions {
|
||||
exclude?: ExclusionRange | Array<ExclusionRange>;
|
||||
indentStart?: boolean;
|
||||
}
|
||||
|
||||
export interface OverwriteOptions {
|
||||
storeName?: boolean;
|
||||
contentOnly?: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateOptions {
|
||||
storeName?: boolean;
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
export default class MagicString {
|
||||
constructor(str: string, options?: MagicStringOptions);
|
||||
/**
|
||||
* Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.
|
||||
*/
|
||||
addSourcemapLocation(char: number): void;
|
||||
/**
|
||||
* Appends the specified content to the end of the string.
|
||||
*/
|
||||
append(content: string): this;
|
||||
/**
|
||||
* Appends the specified content at the index in the original string.
|
||||
* If a range *ending* with index is subsequently moved, the insert will be moved with it.
|
||||
* See also `s.prependLeft(...)`.
|
||||
*/
|
||||
appendLeft(index: number, content: string): this;
|
||||
/**
|
||||
* Appends the specified content at the index in the original string.
|
||||
* If a range *starting* with index is subsequently moved, the insert will be moved with it.
|
||||
* See also `s.prependRight(...)`.
|
||||
*/
|
||||
appendRight(index: number, content: string): this;
|
||||
/**
|
||||
* Does what you'd expect.
|
||||
*/
|
||||
clone(): this;
|
||||
/**
|
||||
* Generates a version 3 sourcemap.
|
||||
*/
|
||||
generateMap(options?: SourceMapOptions): SourceMap;
|
||||
/**
|
||||
* Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.
|
||||
* Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.
|
||||
*/
|
||||
generateDecodedMap(options?: SourceMapOptions): DecodedSourceMap;
|
||||
getIndentString(): string;
|
||||
|
||||
/**
|
||||
* Prefixes each line of the string with prefix.
|
||||
* If prefix is not supplied, the indentation will be guessed from the original content, falling back to a single tab character.
|
||||
*/
|
||||
indent(options?: IndentOptions): this;
|
||||
/**
|
||||
* Prefixes each line of the string with prefix.
|
||||
* If prefix is not supplied, the indentation will be guessed from the original content, falling back to a single tab character.
|
||||
*
|
||||
* The options argument can have an exclude property, which is an array of [start, end] character ranges.
|
||||
* These ranges will be excluded from the indentation - useful for (e.g.) multiline strings.
|
||||
*/
|
||||
indent(indentStr?: string, options?: IndentOptions): this;
|
||||
indentExclusionRanges: ExclusionRange | Array<ExclusionRange>;
|
||||
|
||||
/**
|
||||
* Moves the characters from `start` and `end` to `index`.
|
||||
*/
|
||||
move(start: number, end: number, index: number): this;
|
||||
/**
|
||||
* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
|
||||
* that range. The same restrictions as `s.remove()` apply.
|
||||
*
|
||||
* The fourth argument is optional. It can have a storeName property — if true, the original name will be stored
|
||||
* for later inclusion in a sourcemap's names array — and a contentOnly property which determines whether only
|
||||
* the content is overwritten, or anything that was appended/prepended to the range as well.
|
||||
*
|
||||
* It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
|
||||
*/
|
||||
overwrite(
|
||||
start: number,
|
||||
end: number,
|
||||
content: string,
|
||||
options?: boolean | OverwriteOptions,
|
||||
): this;
|
||||
/**
|
||||
* Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.
|
||||
*
|
||||
* The fourth argument is optional. It can have a storeName property — if true, the original name will be stored
|
||||
* for later inclusion in a sourcemap's names array — and an overwrite property which determines whether only
|
||||
* the content is overwritten, or anything that was appended/prepended to the range as well.
|
||||
*/
|
||||
update(start: number, end: number, content: string, options?: boolean | UpdateOptions): this;
|
||||
/**
|
||||
* Prepends the string with the specified content.
|
||||
*/
|
||||
prepend(content: string): this;
|
||||
/**
|
||||
* Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index
|
||||
*/
|
||||
prependLeft(index: number, content: string): this;
|
||||
/**
|
||||
* Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`
|
||||
*/
|
||||
prependRight(index: number, content: string): this;
|
||||
/**
|
||||
* Removes the characters from `start` to `end` (of the original string, **not** the generated string).
|
||||
* Removing the same content twice, or making removals that partially overlap, will cause an error.
|
||||
*/
|
||||
remove(start: number, end: number): this;
|
||||
/**
|
||||
* Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).
|
||||
*/
|
||||
reset(start: number, end: number): this;
|
||||
/**
|
||||
* Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.
|
||||
* Throws error if the indices are for characters that were already removed.
|
||||
*/
|
||||
slice(start: number, end: number): string;
|
||||
/**
|
||||
* Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.
|
||||
*/
|
||||
snip(start: number, end: number): this;
|
||||
/**
|
||||
* Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start and end.
|
||||
*/
|
||||
trim(charType?: string): this;
|
||||
/**
|
||||
* Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start.
|
||||
*/
|
||||
trimStart(charType?: string): this;
|
||||
/**
|
||||
* Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the end.
|
||||
*/
|
||||
trimEnd(charType?: string): this;
|
||||
/**
|
||||
* Removes empty lines from the start and end.
|
||||
*/
|
||||
trimLines(): this;
|
||||
/**
|
||||
* String replacement with RegExp or string.
|
||||
*/
|
||||
replace(
|
||||
regex: RegExp | string,
|
||||
replacement: string | ((substring: string, ...args: any[]) => string),
|
||||
): this;
|
||||
/**
|
||||
* Same as `s.replace`, but replace all matched strings instead of just one.
|
||||
*/
|
||||
replaceAll(
|
||||
regex: RegExp | string,
|
||||
replacement: string | ((substring: string, ...args: any[]) => string),
|
||||
): this;
|
||||
|
||||
lastChar(): string;
|
||||
lastLine(): string;
|
||||
/**
|
||||
* Returns true if the resulting source is empty (disregarding white space).
|
||||
*/
|
||||
isEmpty(): boolean;
|
||||
length(): number;
|
||||
|
||||
/**
|
||||
* Indicates if the string has been changed.
|
||||
*/
|
||||
hasChanged(): boolean;
|
||||
|
||||
original: string;
|
||||
/**
|
||||
* Returns the generated string.
|
||||
*/
|
||||
toString(): string;
|
||||
|
||||
offset: number;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import * as BufferLayout from '@solana/buffer-layout';
|
||||
|
||||
export interface IAccountStateData {
|
||||
readonly typeIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type AccountType<TInputData extends IAccountStateData> = {
|
||||
/** The account type index (from solana upstream program) */
|
||||
index: number;
|
||||
/** The BufferLayout to use to build data */
|
||||
layout: BufferLayout.Layout<TInputData>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode account data buffer using an AccountType
|
||||
* @internal
|
||||
*/
|
||||
export function decodeData<TAccountStateData extends IAccountStateData>(
|
||||
type: AccountType<TAccountStateData>,
|
||||
data: Uint8Array,
|
||||
): TAccountStateData {
|
||||
let decoded: TAccountStateData;
|
||||
try {
|
||||
decoded = type.layout.decode(data);
|
||||
} catch (err) {
|
||||
throw new Error('invalid instruction; ' + err);
|
||||
}
|
||||
|
||||
if (decoded.typeIndex !== type.index) {
|
||||
throw new Error(
|
||||
`invalid account data; account type mismatch ${decoded.typeIndex} != ${type.index}`,
|
||||
);
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
function _iterableToArray(r) {
|
||||
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
|
||||
}
|
||||
export { _iterableToArray as default };
|
||||
@@ -0,0 +1,112 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { once } = require('node:events')
|
||||
const { join } = require('node:path')
|
||||
const ThreadStream = require('..')
|
||||
|
||||
function createStream (mode) {
|
||||
return new ThreadStream({
|
||||
filename: join(__dirname, 'flush-worker.js'),
|
||||
workerData: { mode },
|
||||
sync: false
|
||||
})
|
||||
}
|
||||
|
||||
test('flush waits for worker destination.flush(cb)', async function () {
|
||||
const stream = createStream('flush')
|
||||
let flushed = false
|
||||
|
||||
stream.on('destination-flushed', () => {
|
||||
flushed = true
|
||||
})
|
||||
|
||||
assert.ok(stream.write('hello'))
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.flush((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
assert.strictEqual(flushed, true)
|
||||
|
||||
const close = once(stream, 'close')
|
||||
stream.end()
|
||||
await close
|
||||
})
|
||||
|
||||
test('flush falls back to destination.flushSync()', async function () {
|
||||
const stream = createStream('flush-sync')
|
||||
let called = false
|
||||
|
||||
stream.on('destination-flush-sync', () => {
|
||||
called = true
|
||||
})
|
||||
|
||||
assert.ok(stream.write('hello'))
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.flush((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
assert.strictEqual(called, true)
|
||||
|
||||
const close = once(stream, 'close')
|
||||
stream.end()
|
||||
await close
|
||||
})
|
||||
|
||||
test('flush waits for drain when destination has no flush API', async function () {
|
||||
const stream = createStream('drain')
|
||||
let drained = false
|
||||
|
||||
stream.on('destination-drain', () => {
|
||||
drained = true
|
||||
})
|
||||
|
||||
assert.ok(stream.write('hello'))
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.flush((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
assert.strictEqual(drained, true)
|
||||
|
||||
const close = once(stream, 'close')
|
||||
stream.end()
|
||||
await close
|
||||
})
|
||||
|
||||
test('pending flush callbacks fail when worker exits', async function () {
|
||||
const stream = createStream('exit-on-flush')
|
||||
const close = once(stream, 'close')
|
||||
|
||||
assert.ok(stream.write('hello'))
|
||||
|
||||
const err = await new Promise((resolve) => {
|
||||
stream.flush(resolve)
|
||||
})
|
||||
|
||||
assert.ok(err)
|
||||
assert.strictEqual(err.message, 'the worker has exited')
|
||||
|
||||
await close
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { FlatConfig } from '@typescript-eslint/utils/ts-eslint';
|
||||
export default _default;
|
||||
/**
|
||||
* Contains all of `recommended`, `recommended-type-checked`, and `strict`, along with additional strict rules that require type information.
|
||||
* @see {@link https://typescript-eslint.io/users/configs#strict-type-checked}
|
||||
*/
|
||||
declare function _default(plugin: FlatConfig.Plugin, parser: FlatConfig.Parser): FlatConfig.ConfigArray;
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.selectorTypeToMessageString = exports.SCHEMA = exports.parseOptions = exports.Modifiers = void 0;
|
||||
var enums_1 = require("./enums");
|
||||
Object.defineProperty(exports, "Modifiers", { enumerable: true, get: function () { return enums_1.Modifiers; } });
|
||||
var parse_options_1 = require("./parse-options");
|
||||
Object.defineProperty(exports, "parseOptions", { enumerable: true, get: function () { return parse_options_1.parseOptions; } });
|
||||
var schema_1 = require("./schema");
|
||||
Object.defineProperty(exports, "SCHEMA", { enumerable: true, get: function () { return schema_1.SCHEMA; } });
|
||||
var shared_1 = require("./shared");
|
||||
Object.defineProperty(exports, "selectorTypeToMessageString", { enumerable: true, get: function () { return shared_1.selectorTypeToMessageString; } });
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
const shebangRegex = require('shebang-regex');
|
||||
|
||||
module.exports = (string = '') => {
|
||||
const match = string.match(shebangRegex);
|
||||
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [path, argument] = match[0].replace(/#! ?/, '').split(' ');
|
||||
const binary = path.split('/').pop();
|
||||
|
||||
if (binary === 'env') {
|
||||
return argument;
|
||||
}
|
||||
|
||||
return argument ? `${binary} ${argument}` : binary;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sha3-addons.d.ts","sourceRoot":"","sources":["../src/sha3-addons.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,OAAO,EAGZ,IAAI,EACJ,KAAK,OAAO,EACZ,KAAK,KAAK,EAGX,MAAM,YAAY,CAAC;AAoCpB,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IAAE,eAAe,CAAC,EAAE,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AA0BjF,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3C,CAAC;AACF,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACnD,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACtC,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG;IACrB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IAClD,MAAM,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,YAAY,CAAC;CAC3C,CAAC;AACF,eAAO,MAAM,SAAS,EAAE,OAAiE,CAAC;AAC1F,eAAO,MAAM,SAAS,EAAE,OAAiE,CAAC;AAE1F,qBAAa,IAAK,SAAQ,MAAO,YAAW,OAAO,CAAC,IAAI,CAAC;gBAErD,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,GAAG,EAAE,KAAK,EACV,IAAI,GAAE,UAAe;IAavB,SAAS,CAAC,MAAM,IAAI,IAAI;IAIxB,UAAU,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI;IAW3B,KAAK,IAAI,IAAI;CAGd;AAUD,eAAO,MAAM,OAAO,EAAE;IACpB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5D,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CACK,CAAC;AACpD,eAAO,MAAM,OAAO,EAAE;IACpB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5D,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CACK,CAAC;AACpD,eAAO,MAAM,UAAU,EAAE;IACvB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5D,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CACW,CAAC;AAC1D,eAAO,MAAM,UAAU,EAAE;IACvB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5D,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CACW,CAAC;AAI1D,qBAAa,SAAU,SAAQ,MAAO,YAAW,OAAO,CAAC,SAAS,CAAC;gBACrD,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,GAAE,UAAe;IAY1F,SAAS,CAAC,MAAM,IAAI,IAAI;IAKxB,UAAU,CAAC,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS;IAIrC,KAAK,IAAI,SAAS;CAGnB;AAaD,yBAAyB;AACzB,eAAO,MAAM,YAAY,EAAE,UAA6D,CAAC;AACzF,yBAAyB;AACzB,eAAO,MAAM,YAAY,EAAE,UAA6D,CAAC;AACzF,6BAA6B;AAC7B,eAAO,MAAM,eAAe,EAAE,UAAmE,CAAC;AAClG,6BAA6B;AAC7B,eAAO,MAAM,eAAe,EAAE,UAAmE,CAAC;AAGlG,KAAK,YAAY,GAAG,UAAU,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,qBAAa,YAAa,SAAQ,MAAO,YAAW,OAAO,CAAC,YAAY,CAAC;IACvE,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAEvB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAC5B,SAAS,EAAE,OAAO,EAClB,IAAI,GAAE,YAAiB;IAgCzB,SAAS,CAAC,MAAM,IAAI,IAAI;IAUxB,UAAU,CAAC,EAAE,CAAC,EAAE,YAAY,GAAG,YAAY;IAQ3C,OAAO,IAAI,IAAI;IAIf,KAAK,IAAI,YAAY;CAGtB;AAqBD,uDAAuD;AACvD,eAAO,MAAM,eAAe,EAAE,QAAoE,CAAC;AACnG,uDAAuD;AACvD,eAAO,MAAM,eAAe,EAAE,QAAoE,CAAC;AACnG,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,EAAE,QACS,CAAC;AAC3C,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,EAAE,QACS,CAAC;AAG3C,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG;IACvC,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAWF,mDAAmD;AACnD,eAAO,MAAM,aAAa,EAAE,OAAqD,CAAC;AAClF,mDAAmD;AACnD,eAAO,MAAM,aAAa,EAAE,OAAqD,CAAC;AAYlF,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAGvE,qBAAa,cAAe,SAAQ,MAAO,YAAW,OAAO,CAAC,cAAc,CAAC;IAC3E,QAAQ,CAAC,QAAQ,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;gBAErB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY;IAMpB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAwBzB,SAAS,CAAC,MAAM,IAAI,IAAI;IAYxB,OAAO,IAAI,IAAI;IAMf,UAAU,CAAC,EAAE,CAAC,EAAE,cAAc,GAAG,cAAc;IAW/C,KAAK,IAAI,cAAc;CAGxB;AACD,+CAA+C;AAC/C,eAAO,MAAM,GAAG,EAAE,MAGZ,CAAC;AACP,oDAAoD;AACpD,eAAO,MAAM,GAAG,EAAE,MAGZ,CAAC;AAEP;;GAEG;AACH,qBAAa,SAAU,SAAQ,MAAM;IACnC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC;gBACX,QAAQ,EAAE,MAAM;IAU5B,MAAM,IAAI,IAAI;IAQd,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAKzB,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAGvB,SAAS,CAAC,MAAM,IAAI,IAAI;IACxB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU;IAGxC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAIhC,MAAM,IAAI,IAAI;IAQd,UAAU,CAAC,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS;IAOrC,KAAK,IAAI,SAAS;CAGnB;AAED,gGAAgG;AAChG,eAAO,MAAM,SAAS,GAAI,iBAAc,KAAG,SAAoC,CAAC"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"regularExpressionFlags.d.ts","sourceRoot":"","sources":["../../src/enums/regularExpressionFlags.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,sBAAsB,EAAE,GAAG,CAAC"}
|
||||
Reference in New Issue
Block a user