WIP: bootstrap and partial real Solana watcher implementation

This commit is contained in:
2026-08-16 09:17:45 +00:00
commit dc23412c3f
7232 changed files with 1687637 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
'use strict'
const test = require('node:test')
const assert = require('node:assert')
const { join } = require('node:path')
const { once } = require('node:events')
const { setImmediate: immediate } = require('node:timers/promises')
const pino = require('../../')
test('pino.transport emits error if the worker exits with 0 unexpectably', async (t) => {
// This test will take 10s, because flushSync waits for 10s
const transport = pino.transport({
target: join(__dirname, '..', 'fixtures', 'crashing-transport.js'),
sync: true
})
t.after(transport.end.bind(transport))
await once(transport, 'ready')
let maybeError
transport.on('error', (err) => {
maybeError = err
})
const logger = pino(transport)
for (let i = 0; i < 100000; i++) {
logger.info('hello')
}
await once(transport.worker, 'exit')
await immediate()
assert.equal(maybeError.message, 'the worker has exited')
})

View File

@@ -0,0 +1,38 @@
// Code generated by Herebyfile.mjs generate:enums from internal/nodebuilder/types.go. DO NOT EDIT.
export var NodeBuilderFlags;
(function (NodeBuilderFlags) {
NodeBuilderFlags[NodeBuilderFlags["None"] = 0] = "None";
NodeBuilderFlags[NodeBuilderFlags["NoTruncation"] = 1] = "NoTruncation";
NodeBuilderFlags[NodeBuilderFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType";
NodeBuilderFlags[NodeBuilderFlags["GenerateNamesForShadowedTypeParams"] = 4] = "GenerateNamesForShadowedTypeParams";
NodeBuilderFlags[NodeBuilderFlags["UseStructuralFallback"] = 8] = "UseStructuralFallback";
NodeBuilderFlags[NodeBuilderFlags["ForbidIndexedAccessSymbolReferences"] = 16] = "ForbidIndexedAccessSymbolReferences";
NodeBuilderFlags[NodeBuilderFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature";
NodeBuilderFlags[NodeBuilderFlags["UseFullyQualifiedType"] = 64] = "UseFullyQualifiedType";
NodeBuilderFlags[NodeBuilderFlags["UseOnlyExternalAliasing"] = 128] = "UseOnlyExternalAliasing";
NodeBuilderFlags[NodeBuilderFlags["SuppressAnyReturnType"] = 256] = "SuppressAnyReturnType";
NodeBuilderFlags[NodeBuilderFlags["WriteTypeParametersInQualifiedName"] = 512] = "WriteTypeParametersInQualifiedName";
NodeBuilderFlags[NodeBuilderFlags["MultilineObjectLiterals"] = 1024] = "MultilineObjectLiterals";
NodeBuilderFlags[NodeBuilderFlags["WriteClassExpressionAsTypeLiteral"] = 2048] = "WriteClassExpressionAsTypeLiteral";
NodeBuilderFlags[NodeBuilderFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction";
NodeBuilderFlags[NodeBuilderFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers";
NodeBuilderFlags[NodeBuilderFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope";
NodeBuilderFlags[NodeBuilderFlags["UseSingleQuotesForStringLiteralType"] = 268435456] = "UseSingleQuotesForStringLiteralType";
NodeBuilderFlags[NodeBuilderFlags["NoTypeReduction"] = 536870912] = "NoTypeReduction";
NodeBuilderFlags[NodeBuilderFlags["UseInstantiationExpressions"] = 1073741824] = "UseInstantiationExpressions";
NodeBuilderFlags[NodeBuilderFlags["OmitThisParameter"] = 33554432] = "OmitThisParameter";
NodeBuilderFlags[NodeBuilderFlags["WriteCallStyleSignature"] = 134217728] = "WriteCallStyleSignature";
NodeBuilderFlags[NodeBuilderFlags["AllowThisInObjectLiteral"] = 32768] = "AllowThisInObjectLiteral";
NodeBuilderFlags[NodeBuilderFlags["AllowQualifiedNameInPlaceOfIdentifier"] = 65536] = "AllowQualifiedNameInPlaceOfIdentifier";
NodeBuilderFlags[NodeBuilderFlags["AllowAnonymousIdentifier"] = 131072] = "AllowAnonymousIdentifier";
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyUnionOrIntersection"] = 262144] = "AllowEmptyUnionOrIntersection";
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyTuple"] = 524288] = "AllowEmptyTuple";
NodeBuilderFlags[NodeBuilderFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType";
NodeBuilderFlags[NodeBuilderFlags["AllowEmptyIndexInfoType"] = 2097152] = "AllowEmptyIndexInfoType";
NodeBuilderFlags[NodeBuilderFlags["AllowNodeModulesRelativePaths"] = 67108864] = "AllowNodeModulesRelativePaths";
NodeBuilderFlags[NodeBuilderFlags["IgnoreErrors"] = 70221824] = "IgnoreErrors";
NodeBuilderFlags[NodeBuilderFlags["InObjectTypeLiteral"] = 4194304] = "InObjectTypeLiteral";
NodeBuilderFlags[NodeBuilderFlags["InTypeAlias"] = 8388608] = "InTypeAlias";
NodeBuilderFlags[NodeBuilderFlags["InInitialEntityName"] = 16777216] = "InInitialEntityName";
})(NodeBuilderFlags || (NodeBuilderFlags = {}));
//# sourceMappingURL=nodeBuilderFlags.js.map

View File

@@ -0,0 +1,7 @@
export declare enum DiagnosticCategory {
Warning = 0,
Error = 1,
Suggestion = 2,
Message = 3
}
//# sourceMappingURL=diagnosticCategory.enum.d.ts.map

View File

@@ -0,0 +1,249 @@
'use strict'
const Range = require('../classes/range.js')
const Comparator = require('../classes/comparator.js')
const { ANY } = Comparator
const satisfies = require('../functions/satisfies.js')
const compare = require('../functions/compare.js')
// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
// - Every simple range `r1, r2, ...` is a null set, OR
// - Every simple range `r1, r2, ...` which is not a null set is a subset of
// some `R1, R2, ...`
//
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
// - If c is only the ANY comparator
// - If C is only the ANY comparator, return true
// - Else if in prerelease mode, return false
// - else replace c with `[>=0.0.0]`
// - If C is only the ANY comparator
// - if in prerelease mode, return true
// - else replace C with `[>=0.0.0]`
// - Let EQ be the set of = comparators in c
// - If EQ is more than one, return true (null set)
// - Let GT be the highest > or >= comparator in c
// - Let LT be the lowest < or <= comparator in c
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
// - If any C is a = range, and GT or LT are set, return false
// - If EQ
// - If GT, and EQ does not satisfy GT, return true (null set)
// - If LT, and EQ does not satisfy LT, return true (null set)
// - If EQ satisfies every C, return true
// - Else return false
// - If GT
// - If GT.semver is lower than any > or >= comp in C, return false
// - If GT is >=, and GT.semver does not satisfy every C, return false
// - If GT.semver has a prerelease, and not in prerelease mode
// - If no C has a prerelease and the GT.semver tuple, return false
// - If LT
// - If LT.semver is greater than any < or <= comp in C, return false
// - If LT is <=, and LT.semver does not satisfy every C, return false
// - If LT.semver has a prerelease, and not in prerelease mode
// - If no C has a prerelease and the LT.semver tuple, return false
// - Else return true
const subset = (sub, dom, options = {}) => {
if (sub === dom) {
return true
}
sub = new Range(sub, options)
dom = new Range(dom, options)
let sawNonNull = false
OUTER: for (const simpleSub of sub.set) {
for (const simpleDom of dom.set) {
const isSub = simpleSubset(simpleSub, simpleDom, options)
sawNonNull = sawNonNull || isSub !== null
if (isSub) {
continue OUTER
}
}
// the null set is a subset of everything, but null simple ranges in
// a complex range should be ignored. so if we saw a non-null range,
// then we know this isn't a subset, but if EVERY simple range was null,
// then it is a subset.
if (sawNonNull) {
return false
}
}
return true
}
const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')]
const minimumVersion = [new Comparator('>=0.0.0')]
const simpleSubset = (sub, dom, options) => {
if (sub === dom) {
return true
}
if (sub.length === 1 && sub[0].semver === ANY) {
if (dom.length === 1 && dom[0].semver === ANY) {
return true
} else if (options.includePrerelease) {
sub = minimumVersionWithPreRelease
} else {
sub = minimumVersion
}
}
if (dom.length === 1 && dom[0].semver === ANY) {
if (options.includePrerelease) {
return true
} else {
dom = minimumVersion
}
}
const eqSet = new Set()
let gt, lt
for (const c of sub) {
if (c.operator === '>' || c.operator === '>=') {
gt = higherGT(gt, c, options)
} else if (c.operator === '<' || c.operator === '<=') {
lt = lowerLT(lt, c, options)
} else {
eqSet.add(c.semver)
}
}
if (eqSet.size > 1) {
return null
}
let gtltComp
if (gt && lt) {
gtltComp = compare(gt.semver, lt.semver, options)
if (gtltComp > 0) {
return null
} else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) {
return null
}
}
// will iterate one or zero times
for (const eq of eqSet) {
if (gt && !satisfies(eq, String(gt), options)) {
return null
}
if (lt && !satisfies(eq, String(lt), options)) {
return null
}
for (const c of dom) {
if (!satisfies(eq, String(c), options)) {
return false
}
}
return true
}
let higher, lower
let hasDomLT, hasDomGT
// if the subset has a prerelease, we need a comparator in the superset
// with the same tuple and a prerelease, or it's not a subset
let needDomLTPre = lt &&
!options.includePrerelease &&
lt.semver.prerelease.length ? lt.semver : false
let needDomGTPre = gt &&
!options.includePrerelease &&
gt.semver.prerelease.length ? gt.semver : false
// exception: <1.2.3-0 is the same as <1.2.3
if (needDomLTPre && needDomLTPre.prerelease.length === 1 &&
lt.operator === '<' && needDomLTPre.prerelease[0] === 0) {
needDomLTPre = false
}
for (const c of dom) {
hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
if (gt) {
if (needDomGTPre) {
if (c.semver.prerelease && c.semver.prerelease.length &&
c.semver.major === needDomGTPre.major &&
c.semver.minor === needDomGTPre.minor &&
c.semver.patch === needDomGTPre.patch) {
needDomGTPre = false
}
}
if (c.operator === '>' || c.operator === '>=') {
higher = higherGT(gt, c, options)
if (higher === c && higher !== gt) {
return false
}
} else if (gt.operator === '>=' && !c.test(gt.semver)) {
return false
}
}
if (lt) {
if (needDomLTPre) {
if (c.semver.prerelease && c.semver.prerelease.length &&
c.semver.major === needDomLTPre.major &&
c.semver.minor === needDomLTPre.minor &&
c.semver.patch === needDomLTPre.patch) {
needDomLTPre = false
}
}
if (c.operator === '<' || c.operator === '<=') {
lower = lowerLT(lt, c, options)
if (lower === c && lower !== lt) {
return false
}
} else if (lt.operator === '<=' && !c.test(lt.semver)) {
return false
}
}
if (!c.operator && (lt || gt) && gtltComp !== 0) {
return false
}
}
// if there was a < or >, and nothing in the dom, then must be false
// UNLESS it was limited by another range in the other direction.
// Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
if (gt && hasDomLT && !lt && gtltComp !== 0) {
return false
}
if (lt && hasDomGT && !gt && gtltComp !== 0) {
return false
}
// we needed a prerelease range in a specific tuple, but didn't get one
// then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
// because it includes prereleases in the 1.2.3 tuple
if (needDomGTPre || needDomLTPre) {
return false
}
return true
}
// >=1.2.3 is lower than >1.2.3
const higherGT = (a, b, options) => {
if (!a) {
return b
}
const comp = compare(a.semver, b.semver, options)
return comp > 0 ? a
: comp < 0 ? b
: b.operator === '>' && a.operator === '>=' ? b
: a
}
// <=1.2.3 is higher than <1.2.3
const lowerLT = (a, b, options) => {
if (!a) {
return b
}
const comp = compare(a.semver, b.semver, options)
return comp < 0 ? a
: comp > 0 ? b
: b.operator === '<' && a.operator === '<=' ? b
: a
}
module.exports = subset

View File

@@ -0,0 +1,124 @@
import { describe, expect, it } from "vitest";
import be from "../../../locales/be.js";
describe("Belarusian localization", () => {
const localeError = be().localeError;
describe("pluralization rules", () => {
for (const { type, cases } of TEST_CASES) {
describe(`${type} pluralization`, () => {
for (const { count, expected } of cases) {
it(`correctly pluralizes ${count} ${type}`, () => {
const error = localeError({
code: "too_small",
minimum: count,
type: "number",
inclusive: true,
path: [],
origin: type,
input: count - 1,
});
expect(error).toContain(expected);
});
}
});
}
it("handles negative numbers correctly", () => {
const error = localeError({
code: "too_small",
minimum: -2,
type: "number",
inclusive: true,
path: [],
origin: "array",
input: -3,
});
expect(error).toContain("-2 элементы");
});
it("handles zero correctly", () => {
const error = localeError({
code: "too_small",
minimum: 0,
type: "number",
inclusive: true,
path: [],
origin: "array",
input: -1,
});
expect(error).toContain("0 элементаў");
});
it("handles bigint values correctly", () => {
const error = localeError({
code: "too_small",
minimum: BigInt(21),
type: "number",
inclusive: true,
path: [],
origin: "array",
input: BigInt(20),
});
expect(error).toContain("21 элемент");
});
});
});
const TEST_CASES = [
{
type: "array",
cases: [
{ count: 1, expected: "1 элемент" },
{ count: 2, expected: "2 элементы" },
{ count: 5, expected: "5 элементаў" },
{ count: 11, expected: "11 элементаў" },
{ count: 21, expected: "21 элемент" },
{ count: 22, expected: "22 элементы" },
{ count: 25, expected: "25 элементаў" },
{ count: 101, expected: "101 элемент" },
{ count: 111, expected: "111 элементаў" },
],
},
{
type: "set",
cases: [
{ count: 1, expected: "1 элемент" },
{ count: 2, expected: "2 элементы" },
{ count: 5, expected: "5 элементаў" },
{ count: 11, expected: "11 элементаў" },
{ count: 21, expected: "21 элемент" },
{ count: 22, expected: "22 элементы" },
{ count: 25, expected: "25 элементаў" },
{ count: 101, expected: "101 элемент" },
{ count: 111, expected: "111 элементаў" },
],
},
{
type: "string",
cases: [
{ count: 1, expected: "1 сімвал" },
{ count: 2, expected: "2 сімвалы" },
{ count: 5, expected: "5 сімвалаў" },
{ count: 11, expected: "11 сімвалаў" },
{ count: 21, expected: "21 сімвал" },
{ count: 22, expected: "22 сімвалы" },
{ count: 25, expected: "25 сімвалаў" },
],
},
{
type: "file",
cases: [
{ count: 0, expected: "0 байтаў" },
{ count: 1, expected: "1 байт" },
{ count: 2, expected: "2 байты" },
{ count: 5, expected: "5 байтаў" },
{ count: 11, expected: "11 байтаў" },
{ count: 21, expected: "21 байт" },
{ count: 22, expected: "22 байты" },
{ count: 25, expected: "25 байтаў" },
{ count: 101, expected: "101 байт" },
{ count: 110, expected: "110 байтаў" },
],
},
] as const;

View File

@@ -0,0 +1,122 @@
function x509Error(msg, cert) {
return new Error('SASL channel binding: ' + msg + ' when parsing public certificate ' + cert.toString('base64'))
}
function readASN1Length(data, index) {
let length = data[index++]
if (length < 0x80) return { length, index }
const lengthBytes = length & 0x7f
if (lengthBytes > 4) throw x509Error('bad length', data)
length = 0
for (let i = 0; i < lengthBytes; i++) {
length = (length << 8) | data[index++]
}
return { length, index }
}
function readASN1OID(data, index) {
if (data[index++] !== 0x6) throw x509Error('non-OID data', data) // 6 = OID
const { length: OIDLength, index: indexAfterOIDLength } = readASN1Length(data, index)
index = indexAfterOIDLength
const lastIndex = index + OIDLength
const byte1 = data[index++]
let oid = ((byte1 / 40) >> 0) + '.' + (byte1 % 40)
while (index < lastIndex) {
// loop over numbers in OID
let value = 0
while (index < lastIndex) {
// loop over bytes in number
const nextByte = data[index++]
value = (value << 7) | (nextByte & 0x7f)
if (nextByte < 0x80) break
}
oid += '.' + value
}
return { oid, index }
}
function expectASN1Seq(data, index) {
if (data[index++] !== 0x30) throw x509Error('non-sequence data', data) // 30 = Sequence
return readASN1Length(data, index)
}
function signatureAlgorithmHashFromCertificate(data, index) {
// read this thread: https://www.postgresql.org/message-id/17760-b6c61e752ec07060%40postgresql.org
if (index === undefined) index = 0
index = expectASN1Seq(data, index).index
const { length: certInfoLength, index: indexAfterCertInfoLength } = expectASN1Seq(data, index)
index = indexAfterCertInfoLength + certInfoLength // skip over certificate info
index = expectASN1Seq(data, index).index // skip over signature length field
const { oid, index: indexAfterOID } = readASN1OID(data, index)
switch (oid) {
// RSA
case '1.2.840.113549.1.1.4':
return 'MD5'
case '1.2.840.113549.1.1.5':
return 'SHA-1'
case '1.2.840.113549.1.1.11':
return 'SHA-256'
case '1.2.840.113549.1.1.12':
return 'SHA-384'
case '1.2.840.113549.1.1.13':
return 'SHA-512'
case '1.2.840.113549.1.1.14':
return 'SHA-224'
case '1.2.840.113549.1.1.15':
return 'SHA512-224'
case '1.2.840.113549.1.1.16':
return 'SHA512-256'
// ECDSA
case '1.2.840.10045.4.1':
return 'SHA-1'
case '1.2.840.10045.4.3.1':
return 'SHA-224'
case '1.2.840.10045.4.3.2':
return 'SHA-256'
case '1.2.840.10045.4.3.3':
return 'SHA-384'
case '1.2.840.10045.4.3.4':
return 'SHA-512'
// RSASSA-PSS: hash is indicated separately
case '1.2.840.113549.1.1.10': {
index = indexAfterOID
index = expectASN1Seq(data, index).index
if (data[index++] !== 0xa0) throw x509Error('non-tag data', data) // a0 = constructed tag 0
index = readASN1Length(data, index).index // skip over tag length field
index = expectASN1Seq(data, index).index // skip over sequence length field
const { oid: hashOID } = readASN1OID(data, index)
switch (hashOID) {
// standalone hash OIDs
case '1.2.840.113549.2.5':
return 'MD5'
case '1.3.14.3.2.26':
return 'SHA-1'
case '2.16.840.1.101.3.4.2.1':
return 'SHA-256'
case '2.16.840.1.101.3.4.2.2':
return 'SHA-384'
case '2.16.840.1.101.3.4.2.3':
return 'SHA-512'
}
throw x509Error('unknown hash OID ' + hashOID, data)
}
// Ed25519 -- see https: return//github.com/openssl/openssl/issues/15477
case '1.3.101.110':
case '1.3.101.112': // ph
return 'SHA-512'
// Ed448 -- still not in pg 17.2 (if supported, digest would be SHAKE256 x 64 bytes)
case '1.3.101.111':
case '1.3.101.113': // ph
throw x509Error('Ed448 certificate channel binding is not currently supported by Postgres')
}
throw x509Error('unknown OID ' + oid, data)
}
module.exports = { signatureAlgorithmHashFromCertificate }

View File

@@ -0,0 +1,2 @@
export declare const crypto: any;
//# sourceMappingURL=crypto.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"}

View File

@@ -0,0 +1,15 @@
"use strict";
function _extends() {
exports._ = _extends = Object.assign || function assign(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
}
return target;
};
return _extends.apply(this, arguments);
}
exports._ = _extends;

View File

@@ -0,0 +1,383 @@
/**
* @fileoverview Rule to flag dangling underscores in variable declarations.
* @author Matt DuVall <http://www.mattduvall.com>
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
defaultOptions: [
{
allow: [],
allowAfterSuper: false,
allowAfterThis: false,
allowAfterThisConstructor: false,
allowFunctionParams: true,
allowInArrayDestructuring: true,
allowInObjectDestructuring: true,
enforceInClassFields: false,
enforceInMethodNames: false,
},
],
docs: {
description: "Disallow dangling underscores in identifiers",
recommended: false,
frozen: true,
url: "https://eslint.org/docs/latest/rules/no-underscore-dangle",
},
schema: [
{
type: "object",
properties: {
allow: {
type: "array",
items: {
type: "string",
},
},
allowAfterThis: {
type: "boolean",
},
allowAfterSuper: {
type: "boolean",
},
allowAfterThisConstructor: {
type: "boolean",
},
enforceInMethodNames: {
type: "boolean",
},
allowFunctionParams: {
type: "boolean",
},
enforceInClassFields: {
type: "boolean",
},
allowInArrayDestructuring: {
type: "boolean",
},
allowInObjectDestructuring: {
type: "boolean",
},
},
additionalProperties: false,
},
],
messages: {
unexpectedUnderscore:
"Unexpected dangling '_' in '{{identifier}}'.",
},
},
create(context) {
const [
{
allow,
allowAfterSuper,
allowAfterThis,
allowAfterThisConstructor,
allowFunctionParams,
allowInArrayDestructuring,
allowInObjectDestructuring,
enforceInClassFields,
enforceInMethodNames,
},
] = context.options;
const sourceCode = context.sourceCode;
//-------------------------------------------------------------------------
// Helpers
//-------------------------------------------------------------------------
/**
* Check if identifier is present inside the allowed option
* @param {string} identifier name of the node
* @returns {boolean} true if its is present
* @private
*/
function isAllowed(identifier) {
return allow.includes(identifier);
}
/**
* Check if identifier has a dangling underscore
* @param {string} identifier name of the node
* @returns {boolean} true if its is present
* @private
*/
function hasDanglingUnderscore(identifier) {
const len = identifier.length;
return (
identifier !== "_" &&
(identifier[0] === "_" || identifier[len - 1] === "_")
);
}
/**
* Check if identifier is a special case member expression
* @param {string} identifier name of the node
* @returns {boolean} true if its is a special case
* @private
*/
function isSpecialCaseIdentifierForMemberExpression(identifier) {
return identifier === "__proto__";
}
/**
* Check if identifier is a special case variable expression
* @param {string} identifier name of the node
* @returns {boolean} true if its is a special case
* @private
*/
function isSpecialCaseIdentifierInVariableExpression(identifier) {
// Checks for the underscore library usage here
return identifier === "_";
}
/**
* Check if a node is a member reference of this.constructor
* @param {ASTNode} node node to evaluate
* @returns {boolean} true if it is a reference on this.constructor
* @private
*/
function isThisConstructorReference(node) {
return (
node.object.type === "MemberExpression" &&
node.object.property.name === "constructor" &&
node.object.object.type === "ThisExpression"
);
}
/**
* Check if function parameter has a dangling underscore.
* @param {ASTNode} node function node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInFunctionParameters(node) {
if (!allowFunctionParams) {
node.params.forEach(param => {
const { type } = param;
let nodeToCheck;
if (type === "RestElement") {
nodeToCheck = param.argument;
} else if (type === "AssignmentPattern") {
nodeToCheck = param.left;
} else {
nodeToCheck = param;
}
if (nodeToCheck.type === "Identifier") {
const identifier = nodeToCheck.name;
if (
hasDanglingUnderscore(identifier) &&
!isAllowed(identifier)
) {
context.report({
node: param,
messageId: "unexpectedUnderscore",
data: {
identifier,
},
});
}
}
});
}
}
/**
* Check if function has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInFunction(node) {
if (node.type === "FunctionDeclaration" && node.id) {
const identifier = node.id.name;
if (
typeof identifier !== "undefined" &&
hasDanglingUnderscore(identifier) &&
!isAllowed(identifier)
) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier,
},
});
}
}
checkForDanglingUnderscoreInFunctionParameters(node);
}
/**
* Check if variable expression has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInVariableExpression(node) {
sourceCode.getDeclaredVariables(node).forEach(variable => {
const definition = variable.defs.find(def => def.node === node);
const identifierNode = definition.name;
const identifier = identifierNode.name;
let parent = identifierNode.parent;
while (
![
"VariableDeclarator",
"ArrayPattern",
"ObjectPattern",
].includes(parent.type)
) {
parent = parent.parent;
}
if (
hasDanglingUnderscore(identifier) &&
!isSpecialCaseIdentifierInVariableExpression(identifier) &&
!isAllowed(identifier) &&
!(
allowInArrayDestructuring &&
parent.type === "ArrayPattern"
) &&
!(
allowInObjectDestructuring &&
parent.type === "ObjectPattern"
)
) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier,
},
});
}
});
}
/**
* Check if member expression has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInMemberExpression(node) {
const identifier = node.property.name,
isMemberOfThis = node.object.type === "ThisExpression",
isMemberOfSuper = node.object.type === "Super",
isMemberOfThisConstructor = isThisConstructorReference(node);
if (
typeof identifier !== "undefined" &&
hasDanglingUnderscore(identifier) &&
!(isMemberOfThis && allowAfterThis) &&
!(isMemberOfSuper && allowAfterSuper) &&
!(isMemberOfThisConstructor && allowAfterThisConstructor) &&
!isSpecialCaseIdentifierForMemberExpression(identifier) &&
!isAllowed(identifier)
) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier,
},
});
}
}
/**
* Check if method declaration or method property has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInMethod(node) {
const identifier = node.key.name;
const isMethod =
node.type === "MethodDefinition" ||
(node.type === "Property" && node.method);
if (
typeof identifier !== "undefined" &&
enforceInMethodNames &&
isMethod &&
hasDanglingUnderscore(identifier) &&
!isAllowed(identifier)
) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier:
node.key.type === "PrivateIdentifier"
? `#${identifier}`
: identifier,
},
});
}
}
/**
* Check if a class field has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInClassField(node) {
const identifier = node.key.name;
if (
typeof identifier !== "undefined" &&
hasDanglingUnderscore(identifier) &&
enforceInClassFields &&
!isAllowed(identifier)
) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier:
node.key.type === "PrivateIdentifier"
? `#${identifier}`
: identifier,
},
});
}
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
FunctionDeclaration: checkForDanglingUnderscoreInFunction,
VariableDeclarator: checkForDanglingUnderscoreInVariableExpression,
MemberExpression: checkForDanglingUnderscoreInMemberExpression,
MethodDefinition: checkForDanglingUnderscoreInMethod,
PropertyDefinition: checkForDanglingUnderscoreInClassField,
Property: checkForDanglingUnderscoreInMethod,
FunctionExpression: checkForDanglingUnderscoreInFunction,
ArrowFunctionExpression: checkForDanglingUnderscoreInFunction,
};
},
};

View File

@@ -0,0 +1,117 @@
/**
* @fileoverview Rule to check multiple var declarations per line
* @author Alberto Rodríguez
* @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: "one-var-declaration-per-line",
url: "https://eslint.style/rules/one-var-declaration-per-line",
},
},
],
},
type: "suggestion",
docs: {
description:
"Require or disallow newlines around variable declarations",
recommended: false,
url: "https://eslint.org/docs/latest/rules/one-var-declaration-per-line",
},
schema: [
{
enum: ["always", "initializations"],
},
],
fixable: "whitespace",
messages: {
expectVarOnNewline:
"Expected variable declaration to be on a new line.",
},
},
create(context) {
const always = context.options[0] === "always";
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
* Determine if provided keyword is a variant of for specifiers
* @private
* @param {string} keyword keyword to test
* @returns {boolean} True if `keyword` is a variant of for specifier
*/
function isForTypeSpecifier(keyword) {
return (
keyword === "ForStatement" ||
keyword === "ForInStatement" ||
keyword === "ForOfStatement"
);
}
/**
* Checks newlines around variable declarations.
* @private
* @param {ASTNode} node `VariableDeclaration` node to test
* @returns {void}
*/
function checkForNewLine(node) {
if (isForTypeSpecifier(node.parent.type)) {
return;
}
const declarations = node.declarations;
let prev;
declarations.forEach(current => {
if (prev && prev.loc.end.line === current.loc.start.line) {
if (always || prev.init || current.init) {
context.report({
node,
messageId: "expectVarOnNewline",
loc: current.loc,
fix: fixer => fixer.insertTextBefore(current, "\n"),
});
}
}
prev = current;
});
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
VariableDeclaration: checkForNewLine,
};
},
};

View File

@@ -0,0 +1,29 @@
'use strict'
const pino = require('../..')
const transport = pino.transport({
targets: [{
level: 'info',
target: 'pino/file',
options: {
destination: process.argv[2]
}
}]
})
const logger = pino(transport)
const toWrite = 1000000
transport.on('ready', run)
let total = 0
function run () {
if (total++ === 8) {
return
}
for (let i = 0; i < toWrite; i++) {
logger.info(`hello ${i}`)
}
transport.once('drain', run)
}

View File

@@ -0,0 +1,66 @@
/**
* @fileoverview Rule to check use of chained assignment expressions
* @author Stewart Rand
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
defaultOptions: [
{
ignoreNonDeclaration: false,
},
],
docs: {
description: "Disallow use of chained assignment expressions",
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-multi-assign",
},
schema: [
{
type: "object",
properties: {
ignoreNonDeclaration: {
type: "boolean",
},
},
additionalProperties: false,
},
],
messages: {
unexpectedChain: "Unexpected chained assignment.",
},
},
create(context) {
const [{ ignoreNonDeclaration }] = context.options;
const selectors = [
"VariableDeclarator > AssignmentExpression.init",
"PropertyDefinition > AssignmentExpression.value",
];
if (!ignoreNonDeclaration) {
selectors.push("AssignmentExpression > AssignmentExpression.right");
}
return {
[selectors](node) {
context.report({
node,
messageId: "unexpectedChain",
});
},
};
},
};

View File

@@ -0,0 +1,56 @@
var util = require('util');
var eyes = require('../lib/eyes');
eyes.inspect({
number: 42,
string: "John Galt",
regexp: /[a-z]+/,
array: [99, 168, 'x', {}],
func: function () {},
bool: false,
nil: null,
undef: undefined,
object: {attr: []}
}, "native types");
eyes.inspect({
number: new(Number)(42),
string: new(String)("John Galt"),
regexp: new(RegExp)(/[a-z]+/),
array: new(Array)(99, 168, 'x', {}),
bool: new(Boolean)(false),
object: new(Object)({attr: []}),
date: new(Date)
}, "wrapped types");
var obj = {};
obj.that = { self: obj };
obj.self = obj;
eyes.inspect(obj, "circular object");
eyes.inspect({hello: 'moto'}, "small object");
eyes.inspect({hello: new(Array)(6) }, "big object");
eyes.inspect(["hello 'world'", 'hello "world"'], "quotes");
eyes.inspect({
recommendations: [{
id: 'a7a6576c2c822c8e2bd81a27e41437d8',
key: [ 'spree', 3.764316258020699 ],
value: {
_id: 'a7a6576c2c822c8e2bd81a27e41437d8',
_rev: '1-2e2d2f7fd858c4a5984bcf809d22ed98',
type: 'domain',
domain: 'spree',
weight: 3.764316258020699,
product_id: 30
}
}]
}, 'complex');
eyes.inspect([null], "null in array");
var inspect = eyes.inspector({ stream: null });
util.puts(inspect('something', "something"));
util.puts(inspect("something else"));
util.puts(inspect(["no color"], null, { styles: false }));

View File

@@ -0,0 +1,16 @@
/**
* NIST secp521r1 aka p521.
* @module
*/
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
import {} from "./abstract/hash-to-curve.js";
import { p521_hasher, p521 as p521n } from "./nist.js";
/** @deprecated use `import { p521 } from '@noble/curves/nist.js';` */
export const p521 = p521n;
/** @deprecated use `import { p521 } from '@noble/curves/nist.js';` */
export const secp521r1 = p521n;
/** @deprecated use `import { p521_hasher } from '@noble/curves/nist.js';` */
export const hashToCurve = /* @__PURE__ */ (() => p521_hasher.hashToCurve)();
/** @deprecated use `import { p521_hasher } from '@noble/curves/nist.js';` */
export const encodeToCurve = /* @__PURE__ */ (() => p521_hasher.encodeToCurve)();
//# sourceMappingURL=p521.js.map

View File

@@ -0,0 +1,164 @@
/**
* @fileoverview restrict values that can be used as Promise rejection reasons
* @author Teddy Katz
*/
"use strict";
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
defaultOptions: [
{
allowEmptyReject: false,
},
],
docs: {
description:
"Require using Error objects as Promise rejection reasons",
recommended: false,
url: "https://eslint.org/docs/latest/rules/prefer-promise-reject-errors",
},
fixable: null,
schema: [
{
type: "object",
properties: {
allowEmptyReject: { type: "boolean" },
},
additionalProperties: false,
},
],
messages: {
rejectAnError:
"Expected the Promise rejection reason to be an Error.",
},
},
create(context) {
const [{ allowEmptyReject }] = context.options;
const sourceCode = context.sourceCode;
//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
/**
* Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
* @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
* @returns {void}
*/
function checkRejectCall(callExpression) {
if (!callExpression.arguments.length && allowEmptyReject) {
return;
}
const rejectionReason = callExpression.arguments[0];
if (
!callExpression.arguments.length ||
!astUtils.couldBeError(rejectionReason) ||
(rejectionReason.type === "Identifier" &&
rejectionReason.name === "undefined" &&
sourceCode.isGlobalReference(rejectionReason))
) {
context.report({
node: callExpression,
messageId: "rejectAnError",
});
}
}
/**
* Determines whether a function call is a Promise.reject() call
* @param {ASTNode} node A CallExpression node
* @returns {boolean} `true` if the call is a Promise.reject() call
*/
function isPromiseRejectCall(node) {
return (
astUtils.isSpecificMemberAccess(
node.callee,
"Promise",
"reject",
) &&
sourceCode.isGlobalReference(
astUtils.skipChainExpression(node.callee).object,
)
);
}
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
return {
// Check `Promise.reject(value)` calls.
CallExpression(node) {
if (isPromiseRejectCall(node)) {
checkRejectCall(node);
}
},
/*
* Check for `new Promise((resolve, reject) => {})`, and check for reject() calls.
* This function is run on "NewExpression:exit" instead of "NewExpression" to ensure that
* the nodes in the expression already have the `parent` property.
*/
"NewExpression:exit"(node) {
if (
node.callee.type === "Identifier" &&
node.callee.name === "Promise" &&
sourceCode.isGlobalReference(node.callee) &&
node.arguments.length &&
astUtils.isFunction(node.arguments[0]) &&
node.arguments[0].params.length > 1 &&
node.arguments[0].params[1].type === "Identifier"
) {
sourceCode
.getDeclaredVariables(node.arguments[0])
/*
* Find the first variable that matches the second parameter's name.
* If the first parameter has the same name as the second parameter, then the variable will actually
* be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
* by the second parameter. It's not possible for an expression with the variable to be evaluated before
* the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
* default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
* this case.
*/
.find(
variable =>
variable.name ===
node.arguments[0].params[1].name,
)
// Get the references to that variable.
.references // Only check the references that read the parameter's value.
.filter(ref => ref.isRead())
// Only check the references that are used as the callee in a function call, e.g. `reject(foo)`.
.filter(
ref =>
ref.identifier.parent.type ===
"CallExpression" &&
ref.identifier === ref.identifier.parent.callee,
)
// Check the argument of the function call to determine whether it's an Error.
.forEach(ref => checkRejectCall(ref.identifier.parent));
}
},
};
},
};

View File

@@ -0,0 +1,43 @@
"use strict";
/* eslint-disable @typescript-eslint/no-namespace */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Scope = void 0;
const scopeManager = __importStar(require("@typescript-eslint/scope-manager"));
var Scope;
(function (Scope) {
Scope.ScopeType = scopeManager.ScopeType;
Scope.DefinitionType = scopeManager.DefinitionType;
})(Scope || (exports.Scope = Scope = {}));

View File

@@ -0,0 +1,128 @@
'use strict'
const metadata = Symbol.for('pino.metadata')
const split = require('split2')
const { Duplex } = require('stream')
const { parentPort, workerData } = require('worker_threads')
function createDeferred () {
let resolve
let reject
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})
promise.resolve = resolve
promise.reject = reject
return promise
}
module.exports = function build (fn, opts = {}) {
const waitForConfig = opts.expectPinoConfig === true && workerData?.workerData?.pinoWillSendConfig === true
const parseLines = opts.parse === 'lines'
const parseLine = typeof opts.parseLine === 'function' ? opts.parseLine : JSON.parse
const close = opts.close || defaultClose
const stream = split(function (line) {
let value
try {
value = parseLine(line)
} catch (error) {
this.emit('unknown', line, error)
return
}
if (value === null) {
this.emit('unknown', line, 'Null value ignored')
return
}
if (typeof value !== 'object') {
value = {
data: value,
time: Date.now()
}
}
if (stream[metadata]) {
stream.lastTime = value.time
stream.lastLevel = value.level
stream.lastObj = value
}
if (parseLines) {
return line
}
return value
}, { autoDestroy: true })
stream._destroy = function (err, cb) {
const promise = close(err, cb)
if (promise && typeof promise.then === 'function') {
promise.then(cb, cb)
}
}
if (opts.expectPinoConfig === true && workerData?.workerData?.pinoWillSendConfig !== true) {
setImmediate(() => {
stream.emit('error', new Error('This transport is not compatible with the current version of pino. Please upgrade pino to the latest version.'))
})
}
if (opts.metadata !== false) {
stream[metadata] = true
stream.lastTime = 0
stream.lastLevel = 0
stream.lastObj = null
}
if (waitForConfig) {
let pinoConfig = {}
const configReceived = createDeferred()
parentPort.on('message', function handleMessage (message) {
if (message.code === 'PINO_CONFIG') {
pinoConfig = message.config
configReceived.resolve()
parentPort.off('message', handleMessage)
}
})
Object.defineProperties(stream, {
levels: {
get () { return pinoConfig.levels }
},
messageKey: {
get () { return pinoConfig.messageKey }
},
errorKey: {
get () { return pinoConfig.errorKey }
}
})
return configReceived.then(finish)
}
return finish()
function finish () {
let res = fn(stream)
if (res && typeof res.catch === 'function') {
res.catch((err) => {
stream.destroy(err)
})
// set it to null to not retain a reference to the promise
res = null
} else if (opts.enablePipelining && res) {
return Duplex.from({ writable: stream, readable: res })
}
return stream
}
}
function defaultClose (err, cb) {
process.nextTick(cb, err)
}

View File

@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2020_string: LibDefinition;

View File

@@ -0,0 +1 @@
{"version":3,"file":"moduleResolutionKind.d.ts","sourceRoot":"","sources":["../../src/enums/moduleResolutionKind.ts"],"names":[],"mappings":"AACA,eAAO,IAAI,oBAAoB,EAAE,GAAG,CAAC"}

View File

@@ -0,0 +1,23 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2017" />
/// <reference lib="dom" />
/// <reference lib="webworker.importscripts" />
/// <reference lib="scripthost" />
/// <reference lib="dom.iterable" />

View File

@@ -0,0 +1 @@
{"version":3,"file":"jubjub.d.ts","sourceRoot":"","sources":["../src/jubjub.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAEtF,wEAAwE;AACxE,eAAO,MAAM,MAAM,EAAE,OAAO,OAAiB,CAAC;AAC9C,sFAAsF;AACtF,eAAO,MAAM,aAAa,EAAE,OAAO,oBAA2C,CAAC;AAC/E,kFAAkF;AAClF,eAAO,MAAM,SAAS,EAAE,OAAO,gBAAmC,CAAC"}

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const ast_utils_1 = require("@typescript-eslint/utils/ast-utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-array-constructor',
meta: {
type: 'suggestion',
docs: {
description: 'Disallow generic `Array` constructors',
extendsBaseRule: true,
recommended: 'recommended',
},
fixable: 'code',
messages: {
useLiteral: 'The array literal notation [] is preferable.',
},
schema: [],
},
defaultOptions: [],
create(context) {
const sourceCode = context.sourceCode;
function getArgumentsText(node) {
const lastToken = sourceCode.getLastToken(node);
if (lastToken == null || !(0, ast_utils_1.isClosingParenToken)(lastToken)) {
return '';
}
let firstToken = node.callee;
do {
firstToken = sourceCode.getTokenAfter(firstToken);
if (!firstToken || firstToken === lastToken) {
return '';
}
} while (!(0, ast_utils_1.isOpeningParenToken)(firstToken));
return sourceCode.text.slice(firstToken.range[1], lastToken.range[0]);
}
/**
* Disallow construction of dense arrays using the Array constructor
* @param node node to evaluate
*/
function check(node) {
if (node.arguments.length !== 1 &&
node.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
node.callee.name === 'Array' &&
!node.typeArguments) {
context.report({
node,
messageId: 'useLiteral',
fix(fixer) {
const argsText = getArgumentsText(node);
return fixer.replaceText(node, `[${argsText}]`);
},
});
}
}
return {
CallExpression: check,
NewExpression: check,
};
},
});

View File

@@ -0,0 +1,8 @@
import { isCI } from 'std-env';
const isNode = typeof process < "u" && typeof process.stdout < "u" && !process.versions?.deno && !globalThis.window;
const isDeno = typeof process < "u" && typeof process.stdout < "u" && process.versions?.deno !== void 0;
const isWindows = (isNode || isDeno) && process.platform === "win32";
const isTTY = (isNode || isDeno) && process.stdout?.isTTY && !isCI;
export { isWindows as a, isTTY as i };

View File

@@ -0,0 +1 @@
{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,iBAAiB,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACrD,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAClE,YAAY,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,UAAU,CAAC;IAC7C,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,UAAU,CAAC;QAClC,wCAAwC;QACxC,gBAAgB,EAAE,MAAM,UAAU,CAAC;KACpC,CAAC;IACF,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,KAAK;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC;CACjF,CAAC;AACF,MAAM,MAAM,OAAO,GAAG,cAAc,CAAC;AAUrC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,cAAc,CAyI9D"}

View File

@@ -0,0 +1,824 @@
const { test } = require('node:test')
const { strict: assert } = require('node:assert')
const slowRedact = require('../index.js')
test('basic path redaction', () => {
const obj = {
headers: {
cookie: 'secret-cookie',
authorization: 'Bearer token'
},
body: { message: 'hello' }
}
const redact = slowRedact({ paths: ['headers.cookie'] })
const result = redact(obj)
// Original object should remain unchanged
assert.strictEqual(obj.headers.cookie, 'secret-cookie')
// Result should have redacted path
const parsed = JSON.parse(result)
assert.strictEqual(parsed.headers.cookie, '[REDACTED]')
assert.strictEqual(parsed.headers.authorization, 'Bearer token')
assert.strictEqual(parsed.body.message, 'hello')
})
test('multiple paths redaction', () => {
const obj = {
user: { name: 'john', password: 'secret' },
session: { token: 'abc123' }
}
const redact = slowRedact({
paths: ['user.password', 'session.token']
})
const result = redact(obj)
// Original unchanged
assert.strictEqual(obj.user.password, 'secret')
assert.strictEqual(obj.session.token, 'abc123')
// Result redacted
const parsed = JSON.parse(result)
assert.strictEqual(parsed.user.password, '[REDACTED]')
assert.strictEqual(parsed.session.token, '[REDACTED]')
assert.strictEqual(parsed.user.name, 'john')
})
test('custom censor value', () => {
const obj = { secret: 'hidden' }
const redact = slowRedact({
paths: ['secret'],
censor: '***'
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.secret, '***')
})
test('serialize: false returns object with restore method', () => {
const obj = { secret: 'hidden' }
const redact = slowRedact({
paths: ['secret'],
serialize: false
})
const result = redact(obj)
// Should be object, not string
assert.strictEqual(typeof result, 'object')
assert.strictEqual(result.secret, '[REDACTED]')
// Should have restore method
assert.strictEqual(typeof result.restore, 'function')
const restored = result.restore()
assert.strictEqual(restored.secret, 'hidden')
})
test('bracket notation paths', () => {
const obj = {
'weird-key': { 'another-weird': 'secret' },
normal: 'public'
}
const redact = slowRedact({
paths: ['["weird-key"]["another-weird"]']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed['weird-key']['another-weird'], '[REDACTED]')
assert.strictEqual(parsed.normal, 'public')
})
test('array paths', () => {
const obj = {
users: [
{ name: 'john', password: 'secret1' },
{ name: 'jane', password: 'secret2' }
]
}
const redact = slowRedact({
paths: ['users[0].password', 'users[1].password']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.users[0].password, '[REDACTED]')
assert.strictEqual(parsed.users[1].password, '[REDACTED]')
assert.strictEqual(parsed.users[0].name, 'john')
assert.strictEqual(parsed.users[1].name, 'jane')
})
test('wildcard at end of path', () => {
const obj = {
secrets: {
key1: 'secret1',
key2: 'secret2'
},
public: 'data'
}
const redact = slowRedact({
paths: ['secrets.*']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.secrets.key1, '[REDACTED]')
assert.strictEqual(parsed.secrets.key2, '[REDACTED]')
assert.strictEqual(parsed.public, 'data')
})
test('wildcard with arrays', () => {
const obj = {
items: ['secret1', 'secret2', 'secret3']
}
const redact = slowRedact({
paths: ['items.*']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.items[0], '[REDACTED]')
assert.strictEqual(parsed.items[1], '[REDACTED]')
assert.strictEqual(parsed.items[2], '[REDACTED]')
})
test('intermediate wildcard', () => {
const obj = {
users: {
user1: { password: 'secret1' },
user2: { password: 'secret2' }
}
}
const redact = slowRedact({
paths: ['users.*.password']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.users.user1.password, '[REDACTED]')
assert.strictEqual(parsed.users.user2.password, '[REDACTED]')
})
test('censor function', () => {
const obj = { secret: 'hidden' }
const redact = slowRedact({
paths: ['secret'],
censor: (value, path) => `REDACTED:${path.join('.')}`
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.secret, 'REDACTED:secret')
})
test('custom serialize function', () => {
const obj = { secret: 'hidden', public: 'data' }
const redact = slowRedact({
paths: ['secret'],
serialize: (obj) => `custom:${JSON.stringify(obj)}`
})
const result = redact(obj)
assert(result.startsWith('custom:'))
const parsed = JSON.parse(result.slice(7))
assert.strictEqual(parsed.secret, '[REDACTED]')
assert.strictEqual(parsed.public, 'data')
})
test('nested paths', () => {
const obj = {
level1: {
level2: {
level3: {
secret: 'hidden'
}
}
}
}
const redact = slowRedact({
paths: ['level1.level2.level3.secret']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.level1.level2.level3.secret, '[REDACTED]')
})
test('non-existent paths are ignored', () => {
const obj = { existing: 'value' }
const redact = slowRedact({
paths: ['nonexistent.path']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.existing, 'value')
assert.strictEqual(parsed.nonexistent, undefined)
})
test('null and undefined handling', () => {
const obj = {
nullValue: null,
undefinedValue: undefined,
nested: {
nullValue: null
}
}
const redact = slowRedact({
paths: ['nullValue', 'nested.nullValue']
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.nullValue, '[REDACTED]')
assert.strictEqual(parsed.nested.nullValue, '[REDACTED]')
})
test('original object remains unchanged', () => {
const original = {
secret: 'hidden',
nested: { secret: 'hidden2' }
}
const copy = JSON.parse(JSON.stringify(original))
const redact = slowRedact({
paths: ['secret', 'nested.secret']
})
redact(original)
// Original should be completely unchanged
assert.deepStrictEqual(original, copy)
})
test('strict mode with primitives', () => {
const redact = slowRedact({
paths: ['test'],
strict: true
})
const stringResult = redact('primitive')
assert.strictEqual(stringResult, '"primitive"')
const numberResult = redact(42)
assert.strictEqual(numberResult, '42')
})
// Path validation tests to match fast-redact behavior
test('path validation - non-string paths should throw', () => {
assert.throws(() => {
slowRedact({ paths: [123] })
}, {
message: 'Paths must be (non-empty) strings'
})
assert.throws(() => {
slowRedact({ paths: [null] })
}, {
message: 'Paths must be (non-empty) strings'
})
assert.throws(() => {
slowRedact({ paths: [undefined] })
}, {
message: 'Paths must be (non-empty) strings'
})
})
test('path validation - empty string should throw', () => {
assert.throws(() => {
slowRedact({ paths: [''] })
}, {
message: 'Invalid redaction path ()'
})
})
test('path validation - double dots should throw', () => {
assert.throws(() => {
slowRedact({ paths: ['invalid..path'] })
}, {
message: 'Invalid redaction path (invalid..path)'
})
assert.throws(() => {
slowRedact({ paths: ['a..b..c'] })
}, {
message: 'Invalid redaction path (a..b..c)'
})
})
test('path validation - unmatched brackets should throw', () => {
assert.throws(() => {
slowRedact({ paths: ['invalid[unclosed'] })
}, {
message: 'Invalid redaction path (invalid[unclosed)'
})
assert.throws(() => {
slowRedact({ paths: ['invalid]unopened'] })
}, {
message: 'Invalid redaction path (invalid]unopened)'
})
assert.throws(() => {
slowRedact({ paths: ['nested[a[b]'] })
}, {
message: 'Invalid redaction path (nested[a[b])'
})
})
test('path validation - comma-separated paths should throw', () => {
assert.throws(() => {
slowRedact({ paths: ['req,headers.cookie'] })
}, {
message: 'Invalid redaction path (req,headers.cookie)'
})
assert.throws(() => {
slowRedact({ paths: ['user,profile,name'] })
}, {
message: 'Invalid redaction path (user,profile,name)'
})
assert.throws(() => {
slowRedact({ paths: ['a,b'] })
}, {
message: 'Invalid redaction path (a,b)'
})
})
test('path validation - mixed valid and invalid should throw', () => {
assert.throws(() => {
slowRedact({ paths: ['valid.path', 123, 'another.valid'] })
}, {
message: 'Paths must be (non-empty) strings'
})
assert.throws(() => {
slowRedact({ paths: ['valid.path', 'invalid..path'] })
}, {
message: 'Invalid redaction path (invalid..path)'
})
assert.throws(() => {
slowRedact({ paths: ['valid.path', 'req,headers.cookie'] })
}, {
message: 'Invalid redaction path (req,headers.cookie)'
})
})
test('path validation - valid paths should work', () => {
// These should not throw
assert.doesNotThrow(() => {
slowRedact({ paths: [] })
})
assert.doesNotThrow(() => {
slowRedact({ paths: ['valid.path'] })
})
assert.doesNotThrow(() => {
slowRedact({ paths: ['user.password', 'data[0].secret'] })
})
assert.doesNotThrow(() => {
slowRedact({ paths: ['["quoted-key"].value'] })
})
assert.doesNotThrow(() => {
slowRedact({ paths: ["['single-quoted'].value"] })
})
assert.doesNotThrow(() => {
slowRedact({ paths: ['array[0]', 'object.property', 'wildcard.*'] })
})
})
// fast-redact compatibility tests
test('censor function receives path as array (fast-redact compatibility)', () => {
const obj = {
headers: {
authorization: 'Bearer token',
'x-api-key': 'secret-key'
}
}
const pathsReceived = []
const redact = slowRedact({
paths: ['headers.authorization', 'headers["x-api-key"]'],
censor: (value, path) => {
pathsReceived.push(path)
assert(Array.isArray(path), 'Path should be an array')
return '[REDACTED]'
}
})
redact(obj)
// Verify paths are arrays
assert.strictEqual(pathsReceived.length, 2)
assert.deepStrictEqual(pathsReceived[0], ['headers', 'authorization'])
assert.deepStrictEqual(pathsReceived[1], ['headers', 'x-api-key'])
})
test('censor function with nested paths receives correct array', () => {
const obj = {
user: {
profile: {
credentials: {
password: 'secret123'
}
}
}
}
let receivedPath
const redact = slowRedact({
paths: ['user.profile.credentials.password'],
censor: (value, path) => {
receivedPath = path
assert.strictEqual(value, 'secret123')
assert(Array.isArray(path))
return '[REDACTED]'
}
})
redact(obj)
assert.deepStrictEqual(receivedPath, ['user', 'profile', 'credentials', 'password'])
})
test('censor function with wildcards receives correct array paths', () => {
const obj = {
users: {
user1: { password: 'secret1' },
user2: { password: 'secret2' }
}
}
const pathsReceived = []
const redact = slowRedact({
paths: ['users.*.password'],
censor: (value, path) => {
pathsReceived.push([...path]) // copy the array
assert(Array.isArray(path))
return '[REDACTED]'
}
})
redact(obj)
assert.strictEqual(pathsReceived.length, 2)
assert.deepStrictEqual(pathsReceived[0], ['users', 'user1', 'password'])
assert.deepStrictEqual(pathsReceived[1], ['users', 'user2', 'password'])
})
test('censor function with array wildcard receives correct array paths', () => {
const obj = {
items: [
{ secret: 'value1' },
{ secret: 'value2' }
]
}
const pathsReceived = []
const redact = slowRedact({
paths: ['items.*.secret'],
censor: (value, path) => {
pathsReceived.push([...path])
assert(Array.isArray(path))
return '[REDACTED]'
}
})
redact(obj)
assert.strictEqual(pathsReceived.length, 2)
assert.deepStrictEqual(pathsReceived[0], ['items', '0', 'secret'])
assert.deepStrictEqual(pathsReceived[1], ['items', '1', 'secret'])
})
test('censor function with end wildcard receives correct array paths', () => {
const obj = {
secrets: {
key1: 'secret1',
key2: 'secret2'
}
}
const pathsReceived = []
const redact = slowRedact({
paths: ['secrets.*'],
censor: (value, path) => {
pathsReceived.push([...path])
assert(Array.isArray(path))
return '[REDACTED]'
}
})
redact(obj)
assert.strictEqual(pathsReceived.length, 2)
// Sort paths for consistent testing since object iteration order isn't guaranteed
pathsReceived.sort((a, b) => a[1].localeCompare(b[1]))
assert.deepStrictEqual(pathsReceived[0], ['secrets', 'key1'])
assert.deepStrictEqual(pathsReceived[1], ['secrets', 'key2'])
})
test('type safety: accessing properties on primitive values should not throw', () => {
// Test case from GitHub issue #5
const redactor = slowRedact({ paths: ['headers.authorization'] })
const data = {
headers: 123 // primitive value
}
assert.doesNotThrow(() => {
const result = redactor(data)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.headers, 123) // Should remain unchanged
})
// Test wildcards with primitives
const redactor2 = slowRedact({ paths: ['data.*.nested'] })
const data2 = {
data: {
item1: 123, // primitive, trying to access .nested on it
item2: { nested: 'secret' }
}
}
assert.doesNotThrow(() => {
const result2 = redactor2(data2)
const parsed2 = JSON.parse(result2)
assert.strictEqual(parsed2.data.item1, 123) // Primitive unchanged
assert.strictEqual(parsed2.data.item2.nested, '[REDACTED]') // Object property redacted
})
// Test deep nested access on primitives
const redactor3 = slowRedact({ paths: ['user.name.first.charAt'] })
const data3 = {
user: {
name: 'John' // string primitive
}
}
assert.doesNotThrow(() => {
const result3 = redactor3(data3)
const parsed3 = JSON.parse(result3)
assert.strictEqual(parsed3.user.name, 'John') // Should remain unchanged
})
})
// Remove option tests
test('remove option: basic key removal', () => {
const obj = { username: 'john', password: 'secret123' }
const redact = slowRedact({ paths: ['password'], remove: true })
const result = redact(obj)
// Original object should remain unchanged
assert.strictEqual(obj.password, 'secret123')
// Result should have password completely removed
const parsed = JSON.parse(result)
assert.strictEqual(parsed.username, 'john')
assert.strictEqual('password' in parsed, false)
assert.strictEqual(parsed.password, undefined)
})
test('remove option: multiple paths removal', () => {
const obj = {
user: { name: 'john', password: 'secret' },
session: { token: 'abc123', id: 'session1' }
}
const redact = slowRedact({
paths: ['user.password', 'session.token'],
remove: true
})
const result = redact(obj)
// Original unchanged
assert.strictEqual(obj.user.password, 'secret')
assert.strictEqual(obj.session.token, 'abc123')
// Result has keys completely removed
const parsed = JSON.parse(result)
assert.strictEqual(parsed.user.name, 'john')
assert.strictEqual(parsed.session.id, 'session1')
assert.strictEqual('password' in parsed.user, false)
assert.strictEqual('token' in parsed.session, false)
})
test('remove option: wildcard removal', () => {
const obj = {
secrets: {
key1: 'secret1',
key2: 'secret2'
},
public: 'data'
}
const redact = slowRedact({
paths: ['secrets.*'],
remove: true
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.public, 'data')
assert.deepStrictEqual(parsed.secrets, {}) // All keys removed
})
test('remove option: array wildcard removal', () => {
const obj = {
items: ['secret1', 'secret2', 'secret3'],
meta: 'data'
}
const redact = slowRedact({
paths: ['items.*'],
remove: true
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.meta, 'data')
// Array items set to undefined are omitted by JSON.stringify
assert.deepStrictEqual(parsed.items, [null, null, null])
})
test('remove option: intermediate wildcard removal', () => {
const obj = {
users: {
user1: { password: 'secret1', name: 'john' },
user2: { password: 'secret2', name: 'jane' }
}
}
const redact = slowRedact({
paths: ['users.*.password'],
remove: true
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.users.user1.name, 'john')
assert.strictEqual(parsed.users.user2.name, 'jane')
assert.strictEqual('password' in parsed.users.user1, false)
assert.strictEqual('password' in parsed.users.user2, false)
})
test('remove option: serialize false returns object with removed keys', () => {
const obj = { secret: 'hidden', public: 'data' }
const redact = slowRedact({
paths: ['secret'],
remove: true,
serialize: false
})
const result = redact(obj)
// Should be object, not string
assert.strictEqual(typeof result, 'object')
assert.strictEqual(result.public, 'data')
assert.strictEqual('secret' in result, false)
// Should have restore method
assert.strictEqual(typeof result.restore, 'function')
const restored = result.restore()
assert.strictEqual(restored.secret, 'hidden')
})
test('remove option: non-existent paths are ignored', () => {
const obj = { existing: 'value' }
const redact = slowRedact({
paths: ['nonexistent.path'],
remove: true
})
const result = redact(obj)
const parsed = JSON.parse(result)
assert.strictEqual(parsed.existing, 'value')
assert.strictEqual(parsed.nonexistent, undefined)
})
// Test for Issue #13: Empty string bracket notation paths not being redacted correctly
test('empty string bracket notation path', () => {
const obj = { '': { c: 'sensitive-data' } }
const redact = slowRedact({ paths: ["[''].c"] })
const result = redact(obj)
// Original object should remain unchanged
assert.strictEqual(obj[''].c, 'sensitive-data')
// Result should have redacted path
const parsed = JSON.parse(result)
assert.strictEqual(parsed[''].c, '[REDACTED]')
})
test('empty string bracket notation with double quotes', () => {
const obj = { '': { c: 'sensitive-data' } }
const redact = slowRedact({ paths: ['[""].c'] })
const result = redact(obj)
// Original object should remain unchanged
assert.strictEqual(obj[''].c, 'sensitive-data')
// Result should have redacted path
const parsed = JSON.parse(result)
assert.strictEqual(parsed[''].c, '[REDACTED]')
})
test('empty string key with nested bracket notation', () => {
const obj = { '': { '': { secret: 'value' } } }
const redact = slowRedact({ paths: ["[''][''].secret"] })
const result = redact(obj)
// Original object should remain unchanged
assert.strictEqual(obj[''][''].secret, 'value')
// Result should have redacted path
const parsed = JSON.parse(result)
assert.strictEqual(parsed[''][''].secret, '[REDACTED]')
})
// Test for Pino issue #2313: censor should only be called when path exists
test('censor function not called for non-existent paths', () => {
let censorCallCount = 0
const censorCalls = []
const redact = slowRedact({
paths: ['a.b.c', 'req.authorization', 'url'],
serialize: false,
censor (value, path) {
censorCallCount++
censorCalls.push({ value, path: path.slice() })
return '***'
}
})
// Test case 1: { req: { id: 'test' } }
// req.authorization doesn't exist, censor should not be called for it
censorCallCount = 0
censorCalls.length = 0
redact({ req: { id: 'test' } })
// Should not have been called for any path since none exist
assert.strictEqual(censorCallCount, 0, 'censor should not be called when paths do not exist')
// Test case 2: { a: { d: 'test' } }
// a.b.c doesn't exist (a.d exists, but not a.b.c)
censorCallCount = 0
redact({ a: { d: 'test' } })
assert.strictEqual(censorCallCount, 0)
// Test case 3: paths that do exist should still call censor
censorCallCount = 0
censorCalls.length = 0
const result = redact({ req: { authorization: 'bearer token' } })
assert.strictEqual(censorCallCount, 1, 'censor should be called when path exists')
assert.deepStrictEqual(censorCalls[0].path, ['req', 'authorization'])
assert.strictEqual(censorCalls[0].value, 'bearer token')
assert.strictEqual(result.req.authorization, '***')
})
test('censor function not called for non-existent nested paths', () => {
let censorCallCount = 0
const redact = slowRedact({
paths: ['headers.authorization'],
serialize: false,
censor (value, path) {
censorCallCount++
return '[REDACTED]'
}
})
// headers exists but authorization doesn't
censorCallCount = 0
const result1 = redact({ headers: { 'content-type': 'application/json' } })
assert.strictEqual(censorCallCount, 0)
assert.deepStrictEqual(result1.headers, { 'content-type': 'application/json' })
// headers doesn't exist at all
censorCallCount = 0
const result2 = redact({ body: 'data' })
assert.strictEqual(censorCallCount, 0)
assert.strictEqual(result2.body, 'data')
assert.strictEqual(typeof result2.restore, 'function')
// headers.authorization exists - should call censor
censorCallCount = 0
const result3 = redact({ headers: { authorization: 'Bearer token' } })
assert.strictEqual(censorCallCount, 1)
assert.strictEqual(result3.headers.authorization, '[REDACTED]')
})