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 @@
{"version":3,"file":"p521.js","sourceRoot":"","sources":["src/p521.ts"],"names":[],"mappings":";;;AAMA,uCAAuD;AACvD,sEAAsE;AACzD,QAAA,IAAI,GAAiB,cAAK,CAAC;AACxC,sEAAsE;AACzD,QAAA,SAAS,GAAiB,cAAK,CAAC;AAC7C,6EAA6E;AAChE,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,qBAAW,CAAC,WAAW,CAAC,EAAE,CAAC;AAChG,6EAA6E;AAChE,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,qBAAW,CAAC,aAAa,CAAC,EAAE,CAAC"}

View File

@@ -0,0 +1,15 @@
import type { Node, SourceFile } from "../../ast/index.ts";
/**
* Encode a SourceFile AST node into the binary format.
*/
export declare function encodeSourceFile(sourceFile: SourceFile): Uint8Array;
/**
* Encode an arbitrary AST node into the binary format.
* When encoding a non-SourceFile node, the header hash and parse options fields will be zero.
*/
export declare function encodeNode(node: Node): Uint8Array;
/**
* Encode a Uint8Array to a base64 string.
*/
export declare function uint8ArrayToBase64(data: Uint8Array): string;
//# sourceMappingURL=encoder.d.ts.map

View File

@@ -0,0 +1,70 @@
import { Codec, Decoder, Encoder, FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder, VariableSizeCodec, VariableSizeDecoder, VariableSizeEncoder } from './codec';
import { ReadonlyUint8Array } from './readonly-uint8array';
/**
* Creates an encoder that writes a `Uint8Array` sentinel after the encoded value.
* This is useful to delimit the encoded value when being read by a decoder.
*
* See {@link addCodecSentinel} for more information.
*
* @typeParam TFrom - The type of the value to encode.
*
* @see {@link addCodecSentinel}
*/
export declare function addEncoderSentinel<TFrom>(encoder: FixedSizeEncoder<TFrom>, sentinel: ReadonlyUint8Array): FixedSizeEncoder<TFrom>;
export declare function addEncoderSentinel<TFrom>(encoder: Encoder<TFrom>, sentinel: ReadonlyUint8Array): VariableSizeEncoder<TFrom>;
/**
* Creates a decoder that continues reading until
* a given `Uint8Array` sentinel is found.
*
* See {@link addCodecSentinel} for more information.
*
* @typeParam TTo - The type of the decoded value.
*
* @see {@link addCodecSentinel}
*/
export declare function addDecoderSentinel<TTo>(decoder: FixedSizeDecoder<TTo>, sentinel: ReadonlyUint8Array): FixedSizeDecoder<TTo>;
export declare function addDecoderSentinel<TTo>(decoder: Decoder<TTo>, sentinel: ReadonlyUint8Array): VariableSizeDecoder<TTo>;
/**
* Creates a Codec that writes a given `Uint8Array` sentinel after the encoded
* value and, when decoding, continues reading until the sentinel is found.
*
* This sets a limit on variable-size codecs and tells us when to stop decoding.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
*
* @example
* ```ts
* const codec = addCodecSentinel(getUtf8Codec(), new Uint8Array([255, 255]));
* codec.encode('hello');
* // 0x68656c6c6fffff
* // | └-- Our sentinel.
* // └-- Our encoded string.
* ```
*
* @remarks
* Note that the sentinel _must not_ be present in the encoded data and
* _must_ be present in the decoded data for this to work.
* If this is not the case, dedicated errors will be thrown.
*
* ```ts
* const sentinel = new Uint8Array([108, 108]); // 'll'
* const codec = addCodecSentinel(getUtf8Codec(), sentinel);
*
* codec.encode('hello'); // Throws: sentinel is in encoded data.
* codec.decode(new Uint8Array([1, 2, 3])); // Throws: sentinel missing in decoded data.
* ```
*
* Separate {@link addEncoderSentinel} and {@link addDecoderSentinel} functions are also available.
*
* ```ts
* const bytes = addEncoderSentinel(getUtf8Encoder(), sentinel).encode('hello');
* const value = addDecoderSentinel(getUtf8Decoder(), sentinel).decode(bytes);
* ```
*
* @see {@link addEncoderSentinel}
* @see {@link addDecoderSentinel}
*/
export declare function addCodecSentinel<TFrom, TTo extends TFrom>(codec: FixedSizeCodec<TFrom, TTo>, sentinel: ReadonlyUint8Array): FixedSizeCodec<TFrom, TTo>;
export declare function addCodecSentinel<TFrom, TTo extends TFrom>(codec: Codec<TFrom, TTo>, sentinel: ReadonlyUint8Array): VariableSizeCodec<TFrom, TTo>;
//# sourceMappingURL=add-codec-sentinel.d.ts.map

View File

@@ -0,0 +1,325 @@
import { expect, test } from "vitest";
import * as z from "zod/v4";
test("z.number() basic validation", () => {
const schema = z.number();
expect(schema.parse(1234)).toEqual(1234);
});
test("NaN validation", () => {
const schema = z.number();
expect(() => schema.parse(Number.NaN)).toThrow();
});
test("Infinity validation", () => {
const schema = z.number();
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"expected": "number",
"code": "invalid_type",
"received": "Infinity",
"path": [],
"message": "Invalid input: expected number, received number"
}
]],
"success": false,
}
`);
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"expected": "number",
"code": "invalid_type",
"received": "Infinity",
"path": [],
"message": "Invalid input: expected number, received number"
}
]],
"success": false,
}
`);
});
test(".gt() validation", () => {
const schema = z.number().gt(0).gt(5);
expect(schema.parse(6)).toEqual(6);
expect(() => schema.parse(5)).toThrow();
});
test(".gte() validation", () => {
const schema = z.number().gt(0).gte(1).gte(5);
expect(schema.parse(5)).toEqual(5);
expect(() => schema.parse(4)).toThrow();
});
test(".min() validation", () => {
const schema = z.number().min(0).min(5);
expect(schema.parse(5)).toEqual(5);
expect(() => schema.parse(4)).toThrow();
});
test(".lt() validation", () => {
const schema = z.number().lte(10).lt(5);
expect(schema.parse(4)).toEqual(4);
expect(() => schema.parse(5)).toThrow();
});
test(".lte() validation", () => {
const schema = z.number().lte(10).lte(5);
expect(schema.parse(5)).toEqual(5);
expect(() => schema.parse(6)).toThrow();
});
test(".max() validation", () => {
const schema = z.number().max(10).max(5);
expect(schema.parse(5)).toEqual(5);
expect(() => schema.parse(6)).toThrow();
});
test(".int() validation", () => {
const schema = z.number().int();
expect(schema.parse(4)).toEqual(4);
expect(() => schema.parse(3.14)).toThrow();
});
test(".positive() validation", () => {
const schema = z.number().positive();
expect(schema.parse(1)).toEqual(1);
expect(() => schema.parse(0)).toThrow();
expect(() => schema.parse(-1)).toThrow();
});
test(".negative() validation", () => {
const schema = z.number().negative();
expect(schema.parse(-1)).toEqual(-1);
expect(() => schema.parse(0)).toThrow();
expect(() => schema.parse(1)).toThrow();
});
test(".nonpositive() validation", () => {
const schema = z.number().nonpositive();
expect(schema.parse(0)).toEqual(0);
expect(schema.parse(-1)).toEqual(-1);
expect(() => schema.parse(1)).toThrow();
});
test(".nonnegative() validation", () => {
const schema = z.number().nonnegative();
expect(schema.parse(0)).toEqual(0);
expect(schema.parse(1)).toEqual(1);
expect(() => schema.parse(-1)).toThrow();
});
test("multipleOf", () => {
const numbers = {
number3: 5.123,
number6: 5.123456,
number7: 5.1234567,
number8: 5.12345678,
};
const schemas = {
schema6: z.number().multipleOf(0.000001),
schema7: z.number().multipleOf(0.0000001),
};
expect(() => schemas.schema6.parse(numbers.number3)).not.toThrow();
expect(() => schemas.schema6.parse(numbers.number6)).not.toThrow();
expect(() => schemas.schema6.parse(numbers.number7)).toThrow();
expect(() => schemas.schema6.parse(numbers.number8)).toThrow();
expect(() => schemas.schema7.parse(numbers.number3)).not.toThrow();
expect(() => schemas.schema7.parse(numbers.number6)).not.toThrow();
expect(() => schemas.schema7.parse(numbers.number7)).not.toThrow();
expect(() => schemas.schema7.parse(numbers.number8)).toThrow();
});
test(".multipleOf() with positive divisor", () => {
const schema = z.number().multipleOf(5);
expect(schema.parse(15)).toEqual(15);
expect(schema.parse(-15)).toEqual(-15);
expect(() => schema.parse(7.5)).toThrow();
expect(() => schema.parse(-7.5)).toThrow();
});
test(".multipleOf() with negative divisor", () => {
const schema = z.number().multipleOf(-5);
expect(schema.parse(-15)).toEqual(-15);
expect(schema.parse(15)).toEqual(15);
expect(() => schema.parse(-7.5)).toThrow();
expect(() => schema.parse(7.5)).toThrow();
});
test(".multipleOf() with scientific notation (multi-digit exponents)", () => {
// Regression test for https://github.com/colinhacks/zod/pull/5687
// The regex was using \d? which only matches single-digit exponents
const schema = z.number().multipleOf(1e-10);
// These should all pass - they are valid multiples of 1e-10
expect(schema.parse(1e-10)).toEqual(1e-10);
expect(schema.parse(5e-10)).toEqual(5e-10);
expect(schema.parse(1e-9)).toEqual(1e-9); // 10 * 1e-10
// Test with 1e-15 (exponent = 15, two digits)
const schema15 = z.number().multipleOf(1e-15);
expect(schema15.parse(1e-15)).toEqual(1e-15);
expect(schema15.parse(3e-15)).toEqual(3e-15);
});
test(".multipleOf() with small floats / scientific notation (#5792)", () => {
const schema = z.number().multipleOf(1e-7);
// Valid multiples (integer * 1e-7)
expect(schema.safeParse(0).success).toBe(true);
expect(schema.safeParse(1e-7).success).toBe(true);
expect(schema.safeParse(2e-7).success).toBe(true);
expect(schema.safeParse(3e-7).success).toBe(true);
// Invalid — 2.5 and 1.5 are not integers
expect(schema.safeParse(2.5e-7).success).toBe(false);
expect(schema.safeParse(1.5e-7).success).toBe(false);
});
test(".step() validation", () => {
const schemaPointOne = z.number().step(0.1);
const schemaPointZeroZeroZeroOne = z.number().step(0.0001);
const schemaSixPointFour = z.number().step(6.4);
expect(schemaPointOne.parse(6)).toEqual(6);
expect(schemaPointOne.parse(6.1)).toEqual(6.1);
expect(schemaSixPointFour.parse(12.8)).toEqual(12.8);
expect(schemaPointZeroZeroZeroOne.parse(3.01)).toEqual(3.01);
expect(() => schemaPointOne.parse(6.11)).toThrow();
expect(() => schemaPointOne.parse(6.1000000001)).toThrow();
expect(() => schemaSixPointFour.parse(6.41)).toThrow();
});
test(".finite() validation", () => {
const schema = z.number().finite();
expect(schema.parse(123)).toEqual(123);
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"expected": "number",
"code": "invalid_type",
"received": "Infinity",
"path": [],
"message": "Invalid input: expected number, received number"
}
]],
"success": false,
}
`);
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"expected": "number",
"code": "invalid_type",
"received": "Infinity",
"path": [],
"message": "Invalid input: expected number, received number"
}
]],
"success": false,
}
`);
});
test(".safe() validation", () => {
const schema = z.number().safe();
expect(schema.parse(Number.MIN_SAFE_INTEGER)).toEqual(Number.MIN_SAFE_INTEGER);
expect(schema.parse(Number.MAX_SAFE_INTEGER)).toEqual(Number.MAX_SAFE_INTEGER);
expect(() => schema.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow();
expect(() => schema.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow();
});
test("min value getters", () => {
expect(z.number().minValue).toBeNull;
expect(z.number().lt(5).minValue).toBeNull;
expect(z.number().lte(5).minValue).toBeNull;
expect(z.number().max(5).minValue).toBeNull;
expect(z.number().negative().minValue).toBeNull;
expect(z.number().nonpositive().minValue).toBeNull;
expect(z.number().int().minValue).toBeNull;
expect(z.number().multipleOf(5).minValue).toBeNull;
expect(z.number().finite().minValue).toBeNull;
expect(z.number().gt(5).minValue).toEqual(5);
expect(z.number().gte(5).minValue).toEqual(5);
expect(z.number().min(5).minValue).toEqual(5);
expect(z.number().min(5).min(10).minValue).toEqual(10);
expect(z.number().positive().minValue).toEqual(0);
expect(z.number().nonnegative().minValue).toEqual(0);
expect(z.number().safe().minValue).toEqual(Number.MIN_SAFE_INTEGER);
});
test("max value getters", () => {
expect(z.number().maxValue).toBeNull;
expect(z.number().gt(5).maxValue).toBeNull;
expect(z.number().gte(5).maxValue).toBeNull;
expect(z.number().min(5).maxValue).toBeNull;
expect(z.number().positive().maxValue).toBeNull;
expect(z.number().nonnegative().maxValue).toBeNull;
expect(z.number().int().minValue).toBeNull;
expect(z.number().multipleOf(5).minValue).toBeNull;
expect(z.number().finite().minValue).toBeNull;
expect(z.number().lt(5).maxValue).toEqual(5);
expect(z.number().lte(5).maxValue).toEqual(5);
expect(z.number().max(5).maxValue).toEqual(5);
expect(z.number().max(5).max(1).maxValue).toEqual(1);
expect(z.number().negative().maxValue).toEqual(0);
expect(z.number().nonpositive().maxValue).toEqual(0);
expect(z.number().safe().maxValue).toEqual(Number.MAX_SAFE_INTEGER);
});
test("int getter", () => {
expect(z.number().isInt).toEqual(false);
expect(z.number().int().isInt).toEqual(true);
expect(z.number().safe().isInt).toEqual(true);
expect(z.number().multipleOf(5).isInt).toEqual(true);
});
/** In Zod 4, number schemas don't accept infinite values. */
test("finite getter", () => {
expect(z.number().isFinite).toEqual(true);
});
test("string format methods", () => {
const a = z.int32().min(5);
expect(a.parse(6)).toEqual(6);
expect(() => a.parse(1)).toThrow();
});
test("negative zero edge case", () => {
const schema = z.number();
const negativeZero = -0;
const positiveZero = 0;
// Both -0 and 0 should be valid (parse succeeds)
expect(schema.safeParse(negativeZero).success).toBe(true);
expect(schema.safeParse(positiveZero).success).toBe(true);
// Note: -0 is normalized to 0 after parsing
expect(schema.parse(negativeZero) === 0).toBe(true);
expect(schema.parse(positiveZero)).toEqual(0);
// With positive() constraint, both should be invalid (0 is not positive)
const positiveSchema = z.number().positive();
expect(() => positiveSchema.parse(negativeZero)).toThrow();
expect(() => positiveSchema.parse(positiveZero)).toThrow();
// With nonnegative(), both should be valid (0 is non-negative)
const nonnegativeSchema = z.number().nonnegative();
expect(nonnegativeSchema.safeParse(negativeZero).success).toBe(true);
expect(nonnegativeSchema.safeParse(positiveZero).success).toBe(true);
expect(nonnegativeSchema.parse(negativeZero) === 0).toBe(true);
expect(nonnegativeSchema.parse(positiveZero)).toEqual(0);
});
test("error customization", () => {
z.number().gte(5, { error: (iss) => "Min: " + iss.minimum.valueOf() });
z.number().lte(5, { error: (iss) => "Max: " + iss.maximum.valueOf() });
});

View File

@@ -0,0 +1,42 @@
'use strict'
const test = require('node:test')
const assert = require('node:assert')
const { join } = require('node:path')
const { createReadStream } = require('node:fs')
const { promisify } = require('node:util')
const stream = require('node:stream')
const execa = require('execa')
const split = require('split2')
const { file } = require('../helper')
const pipeline = promisify(stream.pipeline)
const { Writable } = stream
const sleep = promisify(setTimeout)
const skip = process.env.CI || process.env.CITGM
test('eight million lines', { skip }, async () => {
const destination = file()
await execa(process.argv[0], [join(__dirname, '..', 'fixtures', 'transport-many-lines.js'), destination])
if (process.platform !== 'win32') {
try {
await execa('sync') // Wait for the file to be written to disk
} catch {
// Just a fallback, this should be unreachable
}
}
await sleep(1_000) // It seems that sync is not enough (even in POSIX systems)
const toWrite = 8 * 1_000_000
let count = 0
await pipeline(createReadStream(destination), split(), new Writable({
write (chunk, enc, cb) {
count++
cb()
}
}))
assert.equal(count, toWrite)
})

View File

@@ -0,0 +1,98 @@
'use strict'
const { join } = require('path')
const { fork } = require('child_process')
const fs = require('fs')
const SonicBoom = require('../')
const { file, runTests } = require('./helper')
runTests(buildTests)
function buildTests (test, sync) {
// Reset the umask for testing
process.umask(0o000)
test('end after reopen', (t) => {
t.plan(4)
const dest = file()
const stream = new SonicBoom({ dest, minLength: 4096, sync })
stream.once('ready', () => {
t.pass('ready emitted')
const after = dest + '-moved'
stream.reopen(after)
stream.write('after reopen\n')
stream.on('finish', () => {
t.pass('finish emitted')
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
})
})
stream.end()
})
})
test('end after 2x reopen', (t) => {
t.plan(4)
const dest = file()
const stream = new SonicBoom({ dest, minLength: 4096, sync })
stream.once('ready', () => {
t.pass('ready emitted')
stream.reopen(dest + '-moved')
const after = dest + '-moved-moved'
stream.reopen(after)
stream.write('after reopen\n')
stream.on('finish', () => {
t.pass('finish emitted')
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
})
})
stream.end()
})
})
test('end if not ready', (t) => {
t.plan(3)
const dest = file()
const stream = new SonicBoom({ dest, minLength: 4096, sync })
const after = dest + '-moved'
stream.reopen(after)
stream.write('after reopen\n')
stream.on('finish', () => {
t.pass('finish emitted')
fs.readFile(after, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'after reopen\n')
})
})
stream.end()
})
test('chunk data accordingly', (t) => {
t.plan(2)
const child = fork(join(__dirname, '..', 'fixtures', 'firehose.js'), { silent: true })
const str = Buffer.alloc(10000).fill('a').toString()
let data = ''
child.stdout.on('data', function (chunk) {
data += chunk.toString()
})
child.stdout.on('end', function () {
t.equal(data, str)
})
child.on('close', function (code) {
t.equal(code, 0)
})
})
}

View File

@@ -0,0 +1,835 @@
import { E as createBuilder, J as createLogger, dt as require_picocolors, lt as VERSION, mt as __toESM } from "./chunks/node.js";
import fs from "node:fs";
import path from "node:path";
import { inspect } from "node:util";
import { performance } from "node:perf_hooks";
//#region ../../node_modules/.pnpm/cac@7.0.0/node_modules/cac/dist/index.js
function toArr(any) {
return any == null ? [] : Array.isArray(any) ? any : [any];
}
function toVal(out, key, val, opts) {
var x, old = out[key], nxt = !!~opts.string.indexOf(key) ? val == null || val === true ? "" : String(val) : typeof val === "boolean" ? val : !!~opts.boolean.indexOf(key) ? val === "false" ? false : val === "true" || (out._.push((x = +val, x * 0 === 0) ? x : val), !!val) : (x = +val, x * 0 === 0) ? x : val;
out[key] = old == null ? nxt : Array.isArray(old) ? old.concat(nxt) : [old, nxt];
}
function lib_default(args, opts) {
args = args || [];
opts = opts || {};
var k, arr, arg, name, val, out = { _: [] };
var i = 0, j = 0, idx = 0, len = args.length;
const alibi = opts.alias !== void 0;
const strict = opts.unknown !== void 0;
const defaults = opts.default !== void 0;
opts.alias = opts.alias || {};
opts.string = toArr(opts.string);
opts.boolean = toArr(opts.boolean);
if (alibi) for (k in opts.alias) {
arr = opts.alias[k] = toArr(opts.alias[k]);
for (i = 0; i < arr.length; i++) (opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
}
for (i = opts.boolean.length; i-- > 0;) {
arr = opts.alias[opts.boolean[i]] || [];
for (j = arr.length; j-- > 0;) opts.boolean.push(arr[j]);
}
for (i = opts.string.length; i-- > 0;) {
arr = opts.alias[opts.string[i]] || [];
for (j = arr.length; j-- > 0;) opts.string.push(arr[j]);
}
if (defaults) for (k in opts.default) {
name = typeof opts.default[k];
arr = opts.alias[k] = opts.alias[k] || [];
if (opts[name] !== void 0) {
opts[name].push(k);
for (i = 0; i < arr.length; i++) opts[name].push(arr[i]);
}
}
const keys = strict ? Object.keys(opts.alias) : [];
for (i = 0; i < len; i++) {
arg = args[i];
if (arg === "--") {
out._ = out._.concat(args.slice(++i));
break;
}
for (j = 0; j < arg.length; j++) if (arg.charCodeAt(j) !== 45) break;
if (j === 0) out._.push(arg);
else if (arg.substring(j, j + 3) === "no-") {
name = arg.substring(j + 3);
if (strict && !~keys.indexOf(name)) return opts.unknown(arg);
out[name] = false;
} else {
for (idx = j + 1; idx < arg.length; idx++) if (arg.charCodeAt(idx) === 61) break;
name = arg.substring(j, idx);
val = arg.substring(++idx) || i + 1 === len || ("" + args[i + 1]).charCodeAt(0) === 45 || args[++i];
arr = j === 2 ? [name] : name;
for (idx = 0; idx < arr.length; idx++) {
name = arr[idx];
if (strict && !~keys.indexOf(name)) return opts.unknown("-".repeat(j) + name);
toVal(out, name, idx + 1 < arr.length || val, opts);
}
}
}
if (defaults) {
for (k in opts.default) if (out[k] === void 0) out[k] = opts.default[k];
}
if (alibi) for (k in out) {
arr = opts.alias[k] || [];
while (arr.length > 0) out[arr.shift()] = out[k];
}
return out;
}
function removeBrackets(v) {
return v.replace(/[<[].+/, "").trim();
}
function findAllBrackets(v) {
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
const res = [];
const parse = (match) => {
let variadic = false;
let value = match[1];
if (value.startsWith("...")) {
value = value.slice(3);
variadic = true;
}
return {
required: match[0].startsWith("<"),
value,
variadic
};
};
let angledMatch;
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) res.push(parse(angledMatch));
let squareMatch;
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) res.push(parse(squareMatch));
return res;
}
function getMriOptions(options) {
const result = {
alias: {},
boolean: []
};
for (const [index, option] of options.entries()) {
if (option.names.length > 1) result.alias[option.names[0]] = option.names.slice(1);
if (option.isBoolean) if (option.negated) {
if (!options.some((o, i) => {
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
})) result.boolean.push(option.names[0]);
} else result.boolean.push(option.names[0]);
}
return result;
}
function findLongest(arr) {
return arr.sort((a, b) => {
return a.length > b.length ? -1 : 1;
})[0];
}
function padRight(str, length) {
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
}
function camelcase(input) {
return input.replaceAll(/([a-z])-([a-z])/g, (_, p1, p2) => {
return p1 + p2.toUpperCase();
});
}
function setDotProp(obj, keys, val) {
let current = obj;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (i === keys.length - 1) {
current[key] = val;
return;
}
if (current[key] == null) {
const nextKeyIsArrayIndex = +keys[i + 1] > -1;
current[key] = nextKeyIsArrayIndex ? [] : {};
}
current = current[key];
}
}
function setByType(obj, transforms) {
for (const key of Object.keys(transforms)) {
const transform = transforms[key];
if (transform.shouldTransform) {
obj[key] = [obj[key]].flat();
if (typeof transform.transformFunction === "function") obj[key] = obj[key].map(transform.transformFunction);
}
}
}
function getFileName(input) {
const m = /([^\\/]+)$/.exec(input);
return m ? m[1] : "";
}
function camelcaseOptionName(name) {
return name.split(".").map((v, i) => {
return i === 0 ? camelcase(v) : v;
}).join(".");
}
var CACError = class extends Error {
constructor(message) {
super(message);
this.name = "CACError";
if (typeof Error.captureStackTrace !== "function") this.stack = new Error(message).stack;
}
};
var Option = class {
rawName;
description;
/** Option name */
name;
/** Option name and aliases */
names;
isBoolean;
required;
config;
negated;
constructor(rawName, description, config) {
this.rawName = rawName;
this.description = description;
this.config = Object.assign({}, config);
rawName = rawName.replaceAll(".*", "");
this.negated = false;
this.names = removeBrackets(rawName).split(",").map((v) => {
let name = v.trim().replace(/^-{1,2}/, "");
if (name.startsWith("no-")) {
this.negated = true;
name = name.replace(/^no-/, "");
}
return camelcaseOptionName(name);
}).sort((a, b) => a.length > b.length ? 1 : -1);
this.name = this.names.at(-1);
if (this.negated && this.config.default == null) this.config.default = true;
if (rawName.includes("<")) this.required = true;
else if (rawName.includes("[")) this.required = false;
else this.isBoolean = true;
}
};
let runtimeProcessArgs;
let runtimeInfo;
if (typeof process !== "undefined") {
let runtimeName;
if (typeof Deno !== "undefined" && typeof Deno.version?.deno === "string") runtimeName = "deno";
else if (typeof Bun !== "undefined" && typeof Bun.version === "string") runtimeName = "bun";
else runtimeName = "node";
runtimeInfo = `${process.platform}-${process.arch} ${runtimeName}-${process.version}`;
runtimeProcessArgs = process.argv;
} else if (typeof navigator === "undefined") runtimeInfo = `unknown`;
else runtimeInfo = `${navigator.platform} ${navigator.userAgent}`;
var Command = class {
rawName;
description;
config;
cli;
options;
aliasNames;
name;
args;
commandAction;
usageText;
versionNumber;
examples;
helpCallback;
globalCommand;
constructor(rawName, description, config = {}, cli) {
this.rawName = rawName;
this.description = description;
this.config = config;
this.cli = cli;
this.options = [];
this.aliasNames = [];
this.name = removeBrackets(rawName);
this.args = findAllBrackets(rawName);
this.examples = [];
}
usage(text) {
this.usageText = text;
return this;
}
allowUnknownOptions() {
this.config.allowUnknownOptions = true;
return this;
}
ignoreOptionDefaultValue() {
this.config.ignoreOptionDefaultValue = true;
return this;
}
version(version, customFlags = "-v, --version") {
this.versionNumber = version;
this.option(customFlags, "Display version number");
return this;
}
example(example) {
this.examples.push(example);
return this;
}
/**
* Add a option for this command
* @param rawName Raw option name(s)
* @param description Option description
* @param config Option config
*/
option(rawName, description, config) {
const option = new Option(rawName, description, config);
this.options.push(option);
return this;
}
alias(name) {
this.aliasNames.push(name);
return this;
}
action(callback) {
this.commandAction = callback;
return this;
}
/**
* Check if a command name is matched by this command
* @param name Command name
*/
isMatched(name) {
return this.name === name || this.aliasNames.includes(name);
}
get isDefaultCommand() {
return this.name === "" || this.aliasNames.includes("!");
}
get isGlobalCommand() {
return this instanceof GlobalCommand;
}
/**
* Check if an option is registered in this command
* @param name Option name
*/
hasOption(name) {
name = name.split(".")[0];
return this.options.find((option) => {
return option.names.includes(name);
});
}
outputHelp() {
const { name, commands } = this.cli;
const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand;
let sections = [{ body: `${name}${versionNumber ? `/${versionNumber}` : ""}` }];
sections.push({
title: "Usage",
body: ` $ ${name} ${this.usageText || this.rawName}`
});
if ((this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0) {
const longestCommandName = findLongest(commands.map((command) => command.rawName));
sections.push({
title: "Commands",
body: commands.map((command) => {
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
}).join("\n")
}, {
title: `For more info, run any command with the \`--help\` flag`,
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
});
}
let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
if (!this.isGlobalCommand && !this.isDefaultCommand) options = options.filter((option) => option.name !== "version");
if (options.length > 0) {
const longestOptionName = findLongest(options.map((option) => option.rawName));
sections.push({
title: "Options",
body: options.map((option) => {
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
}).join("\n")
});
}
if (this.examples.length > 0) sections.push({
title: "Examples",
body: this.examples.map((example) => {
if (typeof example === "function") return example(name);
return example;
}).join("\n")
});
if (helpCallback) sections = helpCallback(sections) || sections;
console.info(sections.map((section) => {
return section.title ? `${section.title}:\n${section.body}` : section.body;
}).join("\n\n"));
}
outputVersion() {
const { name } = this.cli;
const { versionNumber } = this.cli.globalCommand;
if (versionNumber) console.info(`${name}/${versionNumber} ${runtimeInfo}`);
}
checkRequiredArgs() {
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
if (this.cli.args.length < minimalArgsCount) throw new CACError(`missing required args for command \`${this.rawName}\``);
}
/**
* Check if the parsed options contain any unknown options
*
* Exit and output error when true
*/
checkUnknownOptions() {
const { options, globalCommand } = this.cli;
if (!this.config.allowUnknownOptions) {
for (const name of Object.keys(options)) if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
}
}
/**
* Check if the required string-type options exist
*/
checkOptionValue() {
const { options: parsedOptions, globalCommand } = this.cli;
const options = [...globalCommand.options, ...this.options];
for (const option of options) {
const value = parsedOptions[option.name.split(".")[0]];
if (option.required) {
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
if (value === true || value === false && !hasNegated) throw new CACError(`option \`${option.rawName}\` value is missing`);
}
}
}
/**
* Check if the number of args is more than expected
*/
checkUnusedArgs() {
const maximumArgsCount = this.args.some((arg) => arg.variadic) ? Infinity : this.args.length;
if (maximumArgsCount < this.cli.args.length) throw new CACError(`Unused args: ${this.cli.args.slice(maximumArgsCount).map((arg) => `\`${arg}\``).join(", ")}`);
}
};
var GlobalCommand = class extends Command {
constructor(cli) {
super("@@global@@", "", {}, cli);
}
};
var CAC = class extends EventTarget {
/** The program name to display in help and version message */
name;
commands;
globalCommand;
matchedCommand;
matchedCommandName;
/**
* Raw CLI arguments
*/
rawArgs;
/**
* Parsed CLI arguments
*/
args;
/**
* Parsed CLI options, camelCased
*/
options;
showHelpOnExit;
showVersionOnExit;
/**
* @param name The program name to display in help and version message
*/
constructor(name = "") {
super();
this.name = name;
this.commands = [];
this.rawArgs = [];
this.args = [];
this.options = {};
this.globalCommand = new GlobalCommand(this);
this.globalCommand.usage("<command> [options]");
}
/**
* Add a global usage text.
*
* This is not used by sub-commands.
*/
usage(text) {
this.globalCommand.usage(text);
return this;
}
/**
* Add a sub-command
*/
command(rawName, description, config) {
const command = new Command(rawName, description || "", config, this);
command.globalCommand = this.globalCommand;
this.commands.push(command);
return command;
}
/**
* Add a global CLI option.
*
* Which is also applied to sub-commands.
*/
option(rawName, description, config) {
this.globalCommand.option(rawName, description, config);
return this;
}
/**
* Show help message when `-h, --help` flags appear.
*
*/
help(callback) {
this.globalCommand.option("-h, --help", "Display this message");
this.globalCommand.helpCallback = callback;
this.showHelpOnExit = true;
return this;
}
/**
* Show version number when `-v, --version` flags appear.
*
*/
version(version, customFlags = "-v, --version") {
this.globalCommand.version(version, customFlags);
this.showVersionOnExit = true;
return this;
}
/**
* Add a global example.
*
* This example added here will not be used by sub-commands.
*/
example(example) {
this.globalCommand.example(example);
return this;
}
/**
* Output the corresponding help message
* When a sub-command is matched, output the help message for the command
* Otherwise output the global one.
*
*/
outputHelp() {
if (this.matchedCommand) this.matchedCommand.outputHelp();
else this.globalCommand.outputHelp();
}
/**
* Output the version number.
*
*/
outputVersion() {
this.globalCommand.outputVersion();
}
setParsedInfo({ args, options }, matchedCommand, matchedCommandName) {
this.args = args;
this.options = options;
if (matchedCommand) this.matchedCommand = matchedCommand;
if (matchedCommandName) this.matchedCommandName = matchedCommandName;
return this;
}
unsetMatchedCommand() {
this.matchedCommand = void 0;
this.matchedCommandName = void 0;
}
/**
* Parse argv
*/
parse(argv, { run = true } = {}) {
if (!argv) {
if (!runtimeProcessArgs) throw new Error("No argv provided and runtime process argv is not available.");
argv = runtimeProcessArgs;
}
this.rawArgs = argv;
if (!this.name) this.name = argv[1] ? getFileName(argv[1]) : "cli";
let shouldParse = true;
for (const command of this.commands) {
const parsed = this.mri(argv.slice(2), command);
const commandName = parsed.args[0];
if (command.isMatched(commandName)) {
shouldParse = false;
const parsedInfo = {
...parsed,
args: parsed.args.slice(1)
};
this.setParsedInfo(parsedInfo, command, commandName);
this.dispatchEvent(new CustomEvent(`command:${commandName}`, { detail: command }));
}
}
if (shouldParse) {
for (const command of this.commands) if (command.isDefaultCommand) {
shouldParse = false;
const parsed = this.mri(argv.slice(2), command);
this.setParsedInfo(parsed, command);
this.dispatchEvent(new CustomEvent("command:!", { detail: command }));
}
}
if (shouldParse) {
const parsed = this.mri(argv.slice(2));
this.setParsedInfo(parsed);
}
if (this.options.help && this.showHelpOnExit) {
this.outputHelp();
run = false;
this.unsetMatchedCommand();
}
if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
this.outputVersion();
run = false;
this.unsetMatchedCommand();
}
const parsedArgv = {
args: this.args,
options: this.options
};
if (run) this.runMatchedCommand();
if (!this.matchedCommand && this.args[0]) this.dispatchEvent(new CustomEvent("command:*", { detail: this.args[0] }));
return parsedArgv;
}
mri(argv, command) {
const cliOptions = [...this.globalCommand.options, ...command ? command.options : []];
const mriOptions = getMriOptions(cliOptions);
let argsAfterDoubleDashes = [];
const doubleDashesIndex = argv.indexOf("--");
if (doubleDashesIndex !== -1) {
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
argv = argv.slice(0, doubleDashesIndex);
}
let parsed = lib_default(argv, mriOptions);
parsed = Object.keys(parsed).reduce((res, name) => {
return {
...res,
[camelcaseOptionName(name)]: parsed[name]
};
}, { _: [] });
const args = parsed._;
const options = { "--": argsAfterDoubleDashes };
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
const transforms = Object.create(null);
for (const cliOption of cliOptions) {
if (!ignoreDefault && cliOption.config.default !== void 0) for (const name of cliOption.names) options[name] = cliOption.config.default;
if (Array.isArray(cliOption.config.type) && transforms[cliOption.name] === void 0) {
transforms[cliOption.name] = Object.create(null);
transforms[cliOption.name].shouldTransform = true;
transforms[cliOption.name].transformFunction = cliOption.config.type[0];
}
}
for (const key of Object.keys(parsed)) if (key !== "_") {
setDotProp(options, key.split("."), parsed[key]);
setByType(options, transforms);
}
return {
args,
options
};
}
runMatchedCommand() {
const { args, options, matchedCommand: command } = this;
if (!command || !command.commandAction) return;
command.checkUnknownOptions();
command.checkOptionValue();
command.checkRequiredArgs();
command.checkUnusedArgs();
const actionArgs = [];
command.args.forEach((arg, index) => {
if (arg.variadic) actionArgs.push(args.slice(index));
else actionArgs.push(args[index]);
});
actionArgs.push(options);
return command.commandAction.apply(this, actionArgs);
}
};
/**
* @param name The program name to display in help and version message
*/
const cac = (name = "") => new CAC(name);
//#endregion
//#region src/node/cli.ts
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
function checkNodeVersion(nodeVersion) {
const currentVersion = nodeVersion.split(".");
const major = parseInt(currentVersion[0], 10);
const minor = parseInt(currentVersion[1], 10);
return major === 20 && minor >= 19 || major === 22 && minor >= 12 || major > 22;
}
if (!checkNodeVersion(process.versions.node)) console.warn(import_picocolors.default.yellow(`You are using Node.js ${process.versions.node}. Vite requires Node.js version 20.19+ or 22.12+. Please upgrade your Node.js version.`));
const cli = cac("vite");
let profileSession = global.__vite_profile_session;
let profileCount = 0;
const stopProfiler = (log) => {
if (!profileSession) return;
return new Promise((res, rej) => {
profileSession.post("Profiler.stop", (err, { profile }) => {
if (!err) {
const outPath = path.resolve(`./vite-profile-${profileCount++}.cpuprofile`);
fs.writeFileSync(outPath, JSON.stringify(profile));
log(import_picocolors.default.yellow(`CPU profile written to ${import_picocolors.default.white(import_picocolors.default.dim(outPath))}`));
profileSession = void 0;
res();
} else rej(err);
});
});
};
const filterDuplicateOptions = (options) => {
for (const [key, value] of Object.entries(options)) if (Array.isArray(value)) options[key] = value[value.length - 1];
};
/**
* removing global flags before passing as command specific sub-configs
*/
function cleanGlobalCLIOptions(options) {
const ret = { ...options };
delete ret["--"];
delete ret.c;
delete ret.config;
delete ret.base;
delete ret.l;
delete ret.logLevel;
delete ret.clearScreen;
delete ret.configLoader;
delete ret.d;
delete ret.debug;
delete ret.f;
delete ret.filter;
delete ret.m;
delete ret.mode;
delete ret.force;
delete ret.w;
if ("sourcemap" in ret) {
const sourcemap = ret.sourcemap;
ret.sourcemap = sourcemap === "true" ? true : sourcemap === "false" ? false : ret.sourcemap;
}
if ("watch" in ret) ret.watch = ret.watch ? {} : void 0;
return ret;
}
/**
* removing builder flags before passing as command specific sub-configs
*/
function cleanBuilderCLIOptions(options) {
const ret = { ...options };
delete ret.app;
return ret;
}
/**
* host may be a number (like 0), should convert to string
*/
const convertHost = (v) => {
if (typeof v === "number") return String(v);
return v;
};
/**
* base may be a number (like 0), should convert to empty string
*/
const convertBase = (v) => {
if (v === 0) return "";
return v;
};
cli.option("-c, --config <file>", `[string] use specified config file`).option("--base <path>", `[string] public base path (default: /)`, { type: [convertBase] }).option("-l, --logLevel <level>", `[string] info | warn | error | silent`).option("--clearScreen", `[boolean] allow/disable clear screen when logging`).option("--configLoader <loader>", `[string] use 'bundle' to bundle the config with Rolldown, or 'runner' (experimental) to process it on the fly, or 'native' (experimental) to load using the native runtime (default: bundle)`).option("-d, --debug [feat]", `[string | boolean] show debug logs`).option("-f, --filter <filter>", `[string] filter debug logs`).option("-m, --mode <mode>", `[string] set env mode`);
cli.command("[root]", "start dev server").alias("serve").alias("dev").option("--host [host]", `[string] specify hostname`, { type: [convertHost] }).option("--port <port>", `[number] specify port`).option("--open [path]", `[boolean | string] open browser on startup`).option("--cors", `[boolean] enable CORS`).option("--strictPort", `[boolean] exit if specified port is already in use`).option("--force", `[boolean] force the optimizer to ignore the cache and re-bundle`).option("--experimentalBundle", `[boolean] use experimental full bundle mode (this is highly experimental)`).action(async (root, options) => {
filterDuplicateOptions(options);
const { createServer } = await import("./chunks/node.js").then((n) => n.j);
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
configLoader: options.configLoader,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
server: cleanGlobalCLIOptions(options),
forceOptimizeDeps: options.force,
experimental: { bundledDev: options.experimentalBundle }
});
if (!server.httpServer) throw new Error("HTTP server not available");
await server.listen();
const info = server.config.logger.info;
const modeString = options.mode && options.mode !== "development" ? ` ${import_picocolors.default.bgGreen(` ${import_picocolors.default.bold(options.mode)} `)}` : "";
const viteStartTime = global.__vite_start_time ?? false;
const startupDurationString = viteStartTime ? import_picocolors.default.dim(`ready in ${import_picocolors.default.reset(import_picocolors.default.bold(Math.ceil(performance.now() - viteStartTime)))} ms`) : "";
const hasExistingLogs = process.stdout.bytesWritten > 0 || process.stderr.bytesWritten > 0;
info(`\n ${import_picocolors.default.green(`${import_picocolors.default.bold("VITE")} v${VERSION}`)}${modeString} ${startupDurationString}\n`, { clear: !hasExistingLogs });
server.printUrls();
const customShortcuts = [];
if (profileSession) customShortcuts.push({
key: "p",
description: "start/stop the profiler",
async action(server) {
if (profileSession) await stopProfiler(server.config.logger.info);
else {
const inspector = await import("node:inspector").then((r) => r.default);
await new Promise((res) => {
profileSession = new inspector.Session();
profileSession.connect();
profileSession.post("Profiler.enable", () => {
profileSession.post("Profiler.start", () => {
server.config.logger.info("Profiler started");
res();
});
});
});
}
}
});
server.bindCLIShortcuts({
print: true,
customShortcuts
});
} catch (e) {
const logger = createLogger(options.logLevel);
logger.error(import_picocolors.default.red(`error when starting dev server:\n${inspect(e)}`), { error: e });
await stopProfiler(logger.info);
process.exit(1);
}
});
cli.command("build [root]", "build for production").option("--target <target>", `[string] transpile target (default: 'baseline-widely-available')`).option("--outDir <dir>", `[string] output directory (default: dist)`).option("--assetsDir <dir>", `[string] directory under outDir to place assets in (default: assets)`).option("--assetsInlineLimit <number>", `[number] static asset base64 inline threshold in bytes (default: 4096)`).option("--ssr [entry]", `[string] build specified entry for server-side rendering`).option("--sourcemap [output]", `[boolean | "inline" | "hidden"] output source maps for build (default: false)`).option("--minify [minifier]", "[boolean | \"oxc\" | \"terser\" | \"esbuild\"] enable/disable minification, or specify minifier to use (default: oxc)").option("--manifest [name]", `[boolean | string] emit build manifest json`).option("--ssrManifest [name]", `[boolean | string] emit ssr manifest json`).option("--emptyOutDir", `[boolean] force empty outDir when it's outside of root`).option("-w, --watch", `[boolean] rebuilds when modules have changed on disk`).option("--app", `[boolean] same as \`builder: {}\``).action(async (root, options) => {
filterDuplicateOptions(options);
const buildOptions = cleanGlobalCLIOptions(cleanBuilderCLIOptions(options));
try {
const builder = await createBuilder({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
configLoader: options.configLoader,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
build: buildOptions,
...options.app ? { builder: {} } : {}
}, null);
await builder.buildApp();
await builder.runDevTools();
} catch (e) {
createLogger(options.logLevel).error(import_picocolors.default.red(`error during build:\n${inspect(e)}`), { error: e });
process.exit(1);
} finally {
await stopProfiler((message) => createLogger(options.logLevel).info(message));
}
});
cli.command("optimize [root]", "pre-bundle dependencies (deprecated, the pre-bundle process runs automatically and does not need to be called)").option("--force", `[boolean] force the optimizer to ignore the cache and re-bundle`).action(async (root, options) => {
filterDuplicateOptions(options);
const { resolveConfig } = await import("./chunks/node.js").then((n) => n.f);
const { optimizeDeps } = await import("./chunks/node.js").then((n) => n.O);
try {
await optimizeDeps(await resolveConfig({
root,
base: options.base,
configFile: options.config,
configLoader: options.configLoader,
logLevel: options.logLevel,
mode: options.mode
}, "serve"), options.force, true);
} catch (e) {
createLogger(options.logLevel).error(import_picocolors.default.red(`error when optimizing deps:\n${inspect(e)}`), { error: e });
process.exit(1);
}
});
cli.command("preview [root]", "locally preview production build").option("--host [host]", `[string] specify hostname`, { type: [convertHost] }).option("--port <port>", `[number] specify port`).option("--strictPort", `[boolean] exit if specified port is already in use`).option("--open [path]", `[boolean | string] open browser on startup`).option("--outDir <dir>", `[string] output directory (default: dist)`).action(async (root, options) => {
filterDuplicateOptions(options);
const { preview } = await import("./chunks/node.js").then((n) => n.y);
try {
const server = await preview({
root,
base: options.base,
configFile: options.config,
configLoader: options.configLoader,
logLevel: options.logLevel,
mode: options.mode,
build: { outDir: options.outDir },
preview: {
port: options.port,
strictPort: options.strictPort,
host: options.host,
open: options.open
}
});
server.printUrls();
server.bindCLIShortcuts({ print: true });
} catch (e) {
createLogger(options.logLevel).error(import_picocolors.default.red(`error when starting preview server:\n${inspect(e)}`), { error: e });
process.exit(1);
} finally {
await stopProfiler((message) => createLogger(options.logLevel).info(message));
}
});
cli.help();
cli.version(VERSION);
cli.parse();
//#endregion
export { stopProfiler };

View File

@@ -0,0 +1,76 @@
"use strict";
var _overload_yield = require("./_overload_yield.cjs");
function _async_generator(gen) {
var front, back;
function send(key, arg) {
return new Promise(function(resolve, reject) {
var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null };
if (back) back = back.next = request;
else {
front = back = request;
resume(key, arg);
}
});
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
var overloaded = value instanceof _overload_yield._;
Promise.resolve(overloaded ? value.v : value).then(function(arg) {
if (overloaded) {
var nextKey = key === "return" ? "return" : "next";
if (!value.k || arg.done) return resume(nextKey, arg);
else arg = gen[nextKey](arg).value;
}
settle(result.done ? "return" : "normal", arg);
}, function(err) {
resume("throw", err);
});
} catch (err) {
settle("throw", err);
}
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({ value: value, done: true });
break;
case "throw":
front.reject(value);
break;
default:
front.resolve({ value: value, done: false });
break;
}
front = front.next;
if (front) resume(front.key, front.arg);
else back = null;
}
this._invoke = send;
if (typeof gen.return !== "function") this.return = undefined;
}
_async_generator.prototype[(typeof Symbol === "function" && Symbol.asyncIterator) || "@@asyncIterator"] = function() {
return this;
};
_async_generator.prototype.next = function(arg) {
return this._invoke("next", arg);
};
_async_generator.prototype.throw = function(arg) {
return this._invoke("throw", arg);
};
_async_generator.prototype.return = function(arg) {
return this._invoke("return", arg);
};
exports._ = _async_generator;

View File

@@ -0,0 +1,177 @@
/**
* @fileoverview Utility to get information about the execution environment.
* @author Kai Cataldo
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const path = require("node:path");
const spawn = require("cross-spawn");
const os = require("node:os");
const log = require("../shared/logging");
const packageJson = require("../../package.json");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Generates and returns execution environment information.
* @returns {string} A string that contains execution environment information.
*/
function environment() {
const cache = new Map();
/**
* Checks if a path is a child of a directory.
* @param {string} parentPath The parent path to check.
* @param {string} childPath The path to check.
* @returns {boolean} Whether or not the given path is a child of a directory.
*/
function isChildOfDirectory(parentPath, childPath) {
return !path.relative(parentPath, childPath).startsWith("..");
}
/**
* Synchronously executes a shell command and formats the result.
* @param {string} cmd The command to execute.
* @param {Array} args The arguments to be executed with the command.
* @throws {Error} As may be collected by `cross-spawn.sync`.
* @returns {string} The version returned by the command.
*/
function execCommand(cmd, args) {
const key = [cmd, ...args].join(" ");
if (cache.has(key)) {
return cache.get(key);
}
const process = spawn.sync(cmd, args, { encoding: "utf8" });
if (process.error) {
throw process.error;
}
const result = process.stdout.trim();
cache.set(key, result);
return result;
}
/**
* Normalizes a version number.
* @param {string} versionStr The string to normalize.
* @returns {string} The normalized version number.
*/
function normalizeVersionStr(versionStr) {
return versionStr.startsWith("v") ? versionStr : `v${versionStr}`;
}
/**
* Gets bin version.
* @param {string} bin The bin to check.
* @throws {Error} As may be collected by `cross-spawn.sync`.
* @returns {string} The normalized version returned by the command.
*/
function getBinVersion(bin) {
const binArgs = ["--version"];
try {
return normalizeVersionStr(execCommand(bin, binArgs));
} catch (e) {
log.error(
`Error finding ${bin} version running the command \`${bin} ${binArgs.join(" ")}\``,
);
throw e;
}
}
/**
* Gets installed npm package version.
* @param {string} pkg The package to check.
* @param {boolean} global Whether to check globally or not.
* @throws {Error} As may be collected by `cross-spawn.sync`.
* @returns {string} The normalized version returned by the command.
*/
function getNpmPackageVersion(pkg, { global = false } = {}) {
const npmBinArgs = ["bin", "-g"];
const npmLsArgs = ["ls", "--depth=0", "--json", pkg];
if (global) {
npmLsArgs.push("-g");
}
try {
const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs));
/*
* Checking globally returns an empty JSON object, while local checks
* include the name and version of the local project.
*/
if (
Object.keys(parsedStdout).length === 0 ||
!(parsedStdout.dependencies && parsedStdout.dependencies.eslint)
) {
return "Not found";
}
const [, processBinPath] = process.argv;
let npmBinPath;
try {
npmBinPath = execCommand("npm", npmBinArgs);
} catch (e) {
log.error(
`Error finding npm binary path when running command \`npm ${npmBinArgs.join(" ")}\``,
);
throw e;
}
const isGlobal = isChildOfDirectory(npmBinPath, processBinPath);
let pkgVersion = parsedStdout.dependencies.eslint.version;
if ((global && isGlobal) || (!global && !isGlobal)) {
pkgVersion += " (Currently used)";
}
return normalizeVersionStr(pkgVersion);
} catch (e) {
log.error(
`Error finding ${pkg} version running the command \`npm ${npmLsArgs.join(" ")}\``,
);
throw e;
}
}
return [
"Environment Info:",
"",
`Node version: ${process.version}`,
`npm version: ${getBinVersion("npm")}`,
`Local ESLint version: ${getNpmPackageVersion("eslint", { global: false })}`,
`Global ESLint version: ${getNpmPackageVersion("eslint", { global: true })}`,
`Operating System: ${os.platform()} ${os.release()}`,
].join("\n");
}
/**
* Returns version of currently executing ESLint.
* @returns {string} The version from the currently executing ESLint's package.json.
*/
function version() {
return `v${packageJson.version}`;
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
module.exports = {
__esModule: true, // Indicate intent for imports, remove ambiguity for Knip (see: https://github.com/eslint/eslint/pull/18005#discussion_r1484422616)
environment,
version,
};

View File

@@ -0,0 +1,33 @@
/*! *****************************************************************************
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"/>
interface String {
/**
* Replace all instances of a substring in a string, using a regular expression or search string.
* @param searchValue A string to search for.
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
*/
replaceAll(searchValue: string | RegExp, replaceValue: string): string;
/**
* Replace all instances of a substring in a string, using a regular expression or search string.
* @param searchValue A string to search for.
* @param replacer A function that returns the replacement text.
*/
replaceAll(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;
}

View File

@@ -0,0 +1,116 @@
'use strict'
const fs = require('fs')
const path = require('path')
const SonicBoom = require('../')
const { file, runTests } = require('./helper')
const isWindows = process.platform === 'win32'
runTests(buildTests)
function buildTests (test, sync) {
// Reset the umask for testing
process.umask(0o000)
test('mode', { skip: isWindows }, (t) => {
t.plan(6)
const dest = file()
const mode = 0o666
const stream = new SonicBoom({ dest, sync, mode })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
stream.end()
stream.on('finish', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
t.equal(fs.statSync(dest).mode & 0o777, stream.mode)
})
})
})
test('mode default', { skip: isWindows }, (t) => {
t.plan(6)
const dest = file()
const defaultMode = 0o666
const stream = new SonicBoom({ dest, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
t.ok(stream.write('something else\n'))
stream.end()
stream.on('finish', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\nsomething else\n')
t.equal(fs.statSync(dest).mode & 0o777, defaultMode)
})
})
})
test('mode on mkdir', { skip: isWindows }, (t) => {
t.plan(5)
const dest = path.join(file(), 'out.log')
const mode = 0o666
const stream = new SonicBoom({ dest, mkdir: true, mode, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('hello world\n'))
stream.flush()
stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'hello world\n')
t.equal(fs.statSync(dest).mode & 0o777, stream.mode)
stream.end()
})
})
})
test('mode on append', { skip: isWindows }, (t) => {
t.plan(5)
const dest = file()
fs.writeFileSync(dest, 'hello world\n', 'utf8', 0o422)
const mode = isWindows ? 0o444 : 0o666
const stream = new SonicBoom({ dest, append: false, mode, sync })
stream.on('ready', () => {
t.pass('ready emitted')
})
t.ok(stream.write('something else\n'))
stream.flush()
stream.on('drain', () => {
fs.readFile(dest, 'utf8', (err, data) => {
t.error(err)
t.equal(data, 'something else\n')
t.equal(fs.statSync(dest).mode & 0o777, stream.mode)
stream.end()
})
})
})
}

View File

@@ -0,0 +1,193 @@
'use strict'
const { test } = require('node:test')
const colors = require('../colors')
const prettifyObject = require('./prettify-object')
const {
ERROR_LIKE_KEYS
} = require('../constants')
const context = {
EOL: '\n',
IDENT: ' ',
customPrettifiers: {},
errorLikeObjectKeys: ERROR_LIKE_KEYS,
objectColorizer: colors(),
singleLine: false,
colorizer: colors()
}
test('returns empty string if no properties present', t => {
const str = prettifyObject({ log: {}, context })
t.assert.strictEqual(str, '')
})
test('works with single level properties', t => {
const str = prettifyObject({ log: { foo: 'bar' }, context })
t.assert.strictEqual(str, ' foo: "bar"\n')
})
test('works with multiple level properties', t => {
const str = prettifyObject({ log: { foo: { bar: 'baz' } }, context })
t.assert.strictEqual(str, ' foo: {\n "bar": "baz"\n }\n')
})
test('skips specified keys', t => {
const str = prettifyObject({
log: { foo: 'bar', hello: 'world' },
skipKeys: ['foo'],
context
})
t.assert.strictEqual(str, ' hello: "world"\n')
})
test('ignores predefined keys', t => {
const str = prettifyObject({ log: { foo: 'bar', pid: 12345 }, context })
t.assert.strictEqual(str, ' foo: "bar"\n')
})
test('ignores escaped backslashes in string values', t => {
const str = prettifyObject({ log: { foo_regexp: '\\[^\\w\\s]\\' }, context })
t.assert.strictEqual(str, ' foo_regexp: "\\[^\\w\\s]\\"\n')
})
test('ignores escaped backslashes in string values (singleLine option)', t => {
const str = prettifyObject({
log: { foo_regexp: '\\[^\\w\\s]\\' },
context: {
...context,
singleLine: true
}
})
t.assert.strictEqual(str, '{"foo_regexp":"\\[^\\w\\s]\\"}\n')
})
test('works with error props', t => {
const err = Error('Something went wrong')
const serializedError = {
message: err.message,
stack: err.stack
}
const str = prettifyObject({ log: { error: serializedError }, context })
t.assert.ok(str.startsWith(' error:'))
t.assert.ok(str.includes(' "message": "Something went wrong",'))
t.assert.ok(str.includes(' Error: Something went wrong'))
})
test('customPrettifiers gets applied', t => {
const customPrettifiers = {
foo: v => v.toUpperCase()
}
const str = prettifyObject({
log: { foo: 'foo' },
context: {
...context,
customPrettifiers
}
})
t.assert.strictEqual(str.startsWith(' foo: FOO'), true)
})
test('skips lines omitted by customPrettifiers', t => {
const customPrettifiers = {
foo: () => { return undefined }
}
const str = prettifyObject({
log: { foo: 'foo', bar: 'bar' },
context: {
...context,
customPrettifiers
}
})
t.assert.strictEqual(str.includes('bar: "bar"'), true)
t.assert.strictEqual(str.includes('foo: "foo"'), false)
})
test('joined lines omits starting eol', t => {
const str = prettifyObject({
log: { msg: 'doing work', calls: ['step 1', 'step 2', 'step 3'], level: 30 },
context: {
...context,
IDENT: '',
customPrettifiers: {
calls: val => '\n' + val.map(it => ' ' + it).join('\n')
}
}
})
t.assert.strictEqual(str, [
'msg: "doing work"',
'calls:',
' step 1',
' step 2',
' step 3',
''
].join('\n'))
})
test('errors skips prettifiers', t => {
const customPrettifiers = {
err: () => { return 'is_err' }
}
const str = prettifyObject({
log: { err: Error('boom') },
context: {
...context,
customPrettifiers
}
})
t.assert.strictEqual(str.includes('err: is_err'), true)
})
test('errors skips prettifying if no lines are present', t => {
const customPrettifiers = {
err: () => { return undefined }
}
const str = prettifyObject({
log: { err: Error('boom') },
context: {
...context,
customPrettifiers
}
})
t.assert.strictEqual(str, '')
})
test('works with single level properties', t => {
const colorizer = colors(true)
const str = prettifyObject({
log: { foo: 'bar' },
context: {
...context,
objectColorizer: colorizer,
colorizer
}
})
t.assert.strictEqual(str, ` ${colorizer.colors.magenta('foo')}: "bar"\n`)
})
test('works with customColors', t => {
const colorizer = colors(true, [])
t.assert.doesNotThrow(() => {
prettifyObject({
log: { foo: 'bar' },
context: {
...context,
objectColorizer: colorizer,
colorizer
}
})
})
})
test('customColors gets applied', t => {
const colorizer = colors(true, [['property', 'green']])
const str = prettifyObject({
log: { foo: 'bar' },
context: {
...context,
objectColorizer: colorizer,
colorizer
}
})
t.assert.strictEqual(str, ` ${colorizer.colors.green('foo')}: "bar"\n`)
})

View File

@@ -0,0 +1,5 @@
const file10 = require("./file10.js")
module.exports = function () {
file10()
}

View File

@@ -0,0 +1,24 @@
# json-buffer
JSON functions that can convert buffers!
[![build status](https://secure.travis-ci.org/dominictarr/json-buffer.png)](http://travis-ci.org/dominictarr/json-buffer)
[![testling badge](https://ci.testling.com/dominictarr/json-buffer.png)](https://ci.testling.com/dominictarr/json-buffer)
JSON mangles buffers by converting to an array...
which isn't helpful. json-buffers converts to base64 instead,
and deconverts base64 to a buffer.
``` js
var JSONB = require('json-buffer')
var Buffer = require('buffer').Buffer
var str = JSONB.stringify(Buffer.from('hello there!'))
console.log(JSONB.parse(str)) //GET a BUFFER back
```
## License
MIT

View File

@@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright © 2025-PRESENT Kevin Deng (https://github.com/sxzz)
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2018-2021 Josh Junon
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.

View File

@@ -0,0 +1,192 @@
"use strict";
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 });
const tsutils = __importStar(require("ts-api-utils"));
const ts = __importStar(require("typescript"));
const util_1 = require("../util");
const shared_1 = require("./enum-utils/shared");
/**
* @returns Whether the right type is an unsafe comparison against any left type.
*/
function typeViolates(leftTypeParts, rightType) {
const leftEnumValueTypes = new Set(leftTypeParts.map(getEnumValueType));
return ((leftEnumValueTypes.has(ts.TypeFlags.Number) && isNumberLike(rightType)) ||
(leftEnumValueTypes.has(ts.TypeFlags.String) && isStringLike(rightType)));
}
function isNumberLike(type) {
return tsutils
.unionConstituents(type)
.every(unionPart => tsutils
.intersectionConstituents(unionPart)
.some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.Number | ts.TypeFlags.NumberLike)));
}
function isStringLike(type) {
return tsutils
.unionConstituents(type)
.every(unionPart => tsutils
.intersectionConstituents(unionPart)
.some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.String | ts.TypeFlags.StringLike)));
}
/**
* @returns What type a type's enum value is (number or string), if either.
*/
function getEnumValueType(type) {
return tsutils.isTypeFlagSet(type, ts.TypeFlags.EnumLike)
? tsutils.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral)
? ts.TypeFlags.Number
: ts.TypeFlags.String
: undefined;
}
exports.default = (0, util_1.createRule)({
name: 'no-unsafe-enum-comparison',
meta: {
type: 'suggestion',
docs: {
description: 'Disallow comparing an enum value with a non-enum value',
recommended: 'recommended',
requiresTypeChecking: true,
},
hasSuggestions: true,
messages: {
mismatchedCase: 'The case statement does not have a shared enum type with the switch predicate.',
mismatchedCondition: 'The two values in this comparison do not have a shared enum type.',
replaceValueWithEnum: 'Replace with an enum value comparison.',
},
schema: [],
},
defaultOptions: [],
create(context) {
const parserServices = (0, util_1.getParserServices)(context);
const typeChecker = parserServices.program.getTypeChecker();
function isMismatchedComparison(leftType, rightType) {
// Allow comparisons that don't have anything to do with enums:
//
// ```ts
// 1 === 2;
// ```
const leftEnumTypes = (0, shared_1.getEnumTypes)(typeChecker, leftType);
const rightEnumTypes = new Set((0, shared_1.getEnumTypes)(typeChecker, rightType));
if (leftEnumTypes.length === 0 && rightEnumTypes.size === 0) {
return false;
}
// Allow comparisons that share an enum type:
//
// ```ts
// Fruit.Apple === Fruit.Banana;
// ```
for (const leftEnumType of leftEnumTypes) {
if (rightEnumTypes.has(leftEnumType)) {
return false;
}
}
// We need to split the type into the union type parts in order to find
// valid enum comparisons like:
//
// ```ts
// declare const something: Fruit | Vegetable;
// something === Fruit.Apple;
// ```
const leftTypeParts = tsutils.unionConstituents(leftType);
const rightTypeParts = tsutils.unionConstituents(rightType);
// If a type exists in both sides, we consider this comparison safe:
//
// ```ts
// declare const fruit: Fruit.Apple | 0;
// fruit === 0;
// ```
for (const leftTypePart of leftTypeParts) {
if (rightTypeParts.includes(leftTypePart)) {
return false;
}
}
return (typeViolates(leftTypeParts, rightType) ||
typeViolates(rightTypeParts, leftType));
}
return {
'BinaryExpression[operator=/^[<>!=]?={0,2}$/]'(node) {
const leftType = parserServices.getTypeAtLocation(node.left);
const rightType = parserServices.getTypeAtLocation(node.right);
if (isMismatchedComparison(leftType, rightType)) {
context.report({
node,
messageId: 'mismatchedCondition',
suggest: [
{
messageId: 'replaceValueWithEnum',
fix(fixer) {
// Replace the right side with an enum key if possible:
//
// ```ts
// Fruit.Apple === 'apple'; // Fruit.Apple === Fruit.Apple
// ```
const leftEnumKey = (0, shared_1.getEnumKeyForLiteral)((0, shared_1.getEnumLiterals)(leftType), (0, util_1.getStaticValue)(node.right)?.value);
if (leftEnumKey) {
return fixer.replaceText(node.right, leftEnumKey);
}
// Replace the left side with an enum key if possible:
//
// ```ts
// declare const fruit: Fruit;
// 'apple' === Fruit.Apple; // Fruit.Apple === Fruit.Apple
// ```
const rightEnumKey = (0, shared_1.getEnumKeyForLiteral)((0, shared_1.getEnumLiterals)(rightType), (0, util_1.getStaticValue)(node.left)?.value);
if (rightEnumKey) {
return fixer.replaceText(node.left, rightEnumKey);
}
return null;
},
},
],
});
}
},
SwitchCase(node) {
// Ignore `default` cases.
if (node.test == null) {
return;
}
const { parent } = node;
const leftType = parserServices.getTypeAtLocation(parent.discriminant);
const rightType = parserServices.getTypeAtLocation(node.test);
if (isMismatchedComparison(leftType, rightType)) {
context.report({
node,
messageId: 'mismatchedCase',
});
}
},
};
},
});

View File

@@ -0,0 +1,115 @@
export {};
import * as webstreams from "stream/web";
type _ByteLengthQueuingStrategy = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ByteLengthQueuingStrategy;
type _CompressionStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.CompressionStream;
type _CountQueuingStrategy = typeof globalThis extends { onmessage: any } ? {} : webstreams.CountQueuingStrategy;
type _DecompressionStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.DecompressionStream;
type _QueuingStrategy<T = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.QueuingStrategy<T>;
type _ReadableByteStreamController = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ReadableByteStreamController;
type _ReadableStream<R = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.ReadableStream<R>;
type _ReadableStreamBYOBReader = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ReadableStreamBYOBReader;
type _ReadableStreamBYOBRequest = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ReadableStreamBYOBRequest;
type _ReadableStreamDefaultController<R = any> = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ReadableStreamDefaultController<R>;
type _ReadableStreamDefaultReader<R = any> = typeof globalThis extends { onmessage: any } ? {}
: webstreams.ReadableStreamDefaultReader<R>;
type _TextDecoderStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.TextDecoderStream;
type _TextEncoderStream = typeof globalThis extends { onmessage: any } ? {} : webstreams.TextEncoderStream;
type _TransformStream<I = any, O = any> = typeof globalThis extends { onmessage: any } ? {}
: webstreams.TransformStream<I, O>;
type _TransformStreamDefaultController<O = any> = typeof globalThis extends { onmessage: any } ? {}
: webstreams.TransformStreamDefaultController<O>;
type _WritableStream<W = any> = typeof globalThis extends { onmessage: any } ? {} : webstreams.WritableStream<W>;
type _WritableStreamDefaultController = typeof globalThis extends { onmessage: any } ? {}
: webstreams.WritableStreamDefaultController;
type _WritableStreamDefaultWriter<W = any> = typeof globalThis extends { onmessage: any } ? {}
: webstreams.WritableStreamDefaultWriter<W>;
declare global {
interface ByteLengthQueuingStrategy extends _ByteLengthQueuingStrategy {}
var ByteLengthQueuingStrategy: typeof globalThis extends { onmessage: any; ByteLengthQueuingStrategy: infer T } ? T
: typeof webstreams.ByteLengthQueuingStrategy;
interface CompressionStream extends _CompressionStream {}
var CompressionStream: typeof globalThis extends {
onmessage: any;
CompressionStream: infer T;
} ? T
: typeof webstreams.CompressionStream;
interface CountQueuingStrategy extends _CountQueuingStrategy {}
var CountQueuingStrategy: typeof globalThis extends { onmessage: any; CountQueuingStrategy: infer T } ? T
: typeof webstreams.CountQueuingStrategy;
interface DecompressionStream extends _DecompressionStream {}
var DecompressionStream: typeof globalThis extends {
onmessage: any;
DecompressionStream: infer T;
} ? T
: typeof webstreams.DecompressionStream;
interface QueuingStrategy<T = any> extends _QueuingStrategy<T> {}
interface ReadableByteStreamController extends _ReadableByteStreamController {}
var ReadableByteStreamController: typeof globalThis extends
{ onmessage: any; ReadableByteStreamController: infer T } ? T : typeof webstreams.ReadableByteStreamController;
interface ReadableStream<R = any> extends _ReadableStream<R> {}
var ReadableStream: typeof globalThis extends { onmessage: any; ReadableStream: infer T } ? T
: typeof webstreams.ReadableStream;
interface ReadableStreamBYOBReader extends _ReadableStreamBYOBReader {}
var ReadableStreamBYOBReader: typeof globalThis extends { onmessage: any; ReadableStreamBYOBReader: infer T } ? T
: typeof webstreams.ReadableStreamBYOBReader;
interface ReadableStreamBYOBRequest extends _ReadableStreamBYOBRequest {}
var ReadableStreamBYOBRequest: typeof globalThis extends { onmessage: any; ReadableStreamBYOBRequest: infer T } ? T
: typeof webstreams.ReadableStreamBYOBRequest;
interface ReadableStreamDefaultController<R = any> extends _ReadableStreamDefaultController<R> {}
var ReadableStreamDefaultController: typeof globalThis extends
{ onmessage: any; ReadableStreamDefaultController: infer T } ? T
: typeof webstreams.ReadableStreamDefaultController;
interface ReadableStreamDefaultReader<R = any> extends _ReadableStreamDefaultReader<R> {}
var ReadableStreamDefaultReader: typeof globalThis extends { onmessage: any; ReadableStreamDefaultReader: infer T }
? T
: typeof webstreams.ReadableStreamDefaultReader;
interface TextDecoderStream extends _TextDecoderStream {}
var TextDecoderStream: typeof globalThis extends { onmessage: any; TextDecoderStream: infer T } ? T
: typeof webstreams.TextDecoderStream;
interface TextEncoderStream extends _TextEncoderStream {}
var TextEncoderStream: typeof globalThis extends { onmessage: any; TextEncoderStream: infer T } ? T
: typeof webstreams.TextEncoderStream;
interface TransformStream<I = any, O = any> extends _TransformStream<I, O> {}
var TransformStream: typeof globalThis extends { onmessage: any; TransformStream: infer T } ? T
: typeof webstreams.TransformStream;
interface TransformStreamDefaultController<O = any> extends _TransformStreamDefaultController<O> {}
var TransformStreamDefaultController: typeof globalThis extends
{ onmessage: any; TransformStreamDefaultController: infer T } ? T
: typeof webstreams.TransformStreamDefaultController;
interface WritableStream<W = any> extends _WritableStream<W> {}
var WritableStream: typeof globalThis extends { onmessage: any; WritableStream: infer T } ? T
: typeof webstreams.WritableStream;
interface WritableStreamDefaultController extends _WritableStreamDefaultController {}
var WritableStreamDefaultController: typeof globalThis extends
{ onmessage: any; WritableStreamDefaultController: infer T } ? T
: typeof webstreams.WritableStreamDefaultController;
interface WritableStreamDefaultWriter<W = any> extends _WritableStreamDefaultWriter<W> {}
var WritableStreamDefaultWriter: typeof globalThis extends { onmessage: any; WritableStreamDefaultWriter: infer T }
? T
: typeof webstreams.WritableStreamDefaultWriter;
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Madeline Gurriarán
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.

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isNodeEqual = isNodeEqual;
const utils_1 = require("@typescript-eslint/utils");
function isNodeEqual(a, b) {
if (a.type !== b.type) {
return false;
}
if (a.type === utils_1.AST_NODE_TYPES.ThisExpression &&
b.type === utils_1.AST_NODE_TYPES.ThisExpression) {
return true;
}
if (a.type === utils_1.AST_NODE_TYPES.Literal && b.type === utils_1.AST_NODE_TYPES.Literal) {
return a.value === b.value;
}
if (a.type === utils_1.AST_NODE_TYPES.Identifier &&
b.type === utils_1.AST_NODE_TYPES.Identifier) {
return a.name === b.name;
}
if (a.type === utils_1.AST_NODE_TYPES.MemberExpression &&
b.type === utils_1.AST_NODE_TYPES.MemberExpression) {
return (isNodeEqual(a.property, b.property) && isNodeEqual(a.object, b.object));
}
return false;
}

View File

@@ -0,0 +1,71 @@
import { FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder } from '@solana/codecs-core';
/**
* Returns an encoder for 8-bit unsigned integers (`u8`).
*
* This encoder serializes `u8` values using a single byte.
*
* For more details, see {@link getU8Codec}.
*
* @returns A `FixedSizeEncoder<number | bigint, 1>` for encoding `u8` values.
*
* @example
* Encoding a `u8` value.
* ```ts
* const encoder = getU8Encoder();
* const bytes = encoder.encode(42); // 0x2a
* ```
*
* @see {@link getU8Codec}
*/
export declare const getU8Encoder: () => FixedSizeEncoder<bigint | number, 1>;
/**
* Returns a decoder for 8-bit unsigned integers (`u8`).
*
* This decoder deserializes `u8` values from a single byte.
*
* For more details, see {@link getU8Codec}.
*
* @returns A `FixedSizeDecoder<number, 1>` for decoding `u8` values.
*
* @example
* Decoding a `u8` value.
* ```ts
* const decoder = getU8Decoder();
* const value = decoder.decode(new Uint8Array([0xff])); // 255
* ```
*
* @see {@link getU8Codec}
*/
export declare const getU8Decoder: () => FixedSizeDecoder<number, 1>;
/**
* Returns a codec for encoding and decoding 8-bit unsigned integers (`u8`).
*
* This codec serializes `u8` values using a single byte.
*
* @returns A `FixedSizeCodec<number | bigint, number, 1>` for encoding and decoding `u8` values.
*
* @example
* Encoding and decoding a `u8` value.
* ```ts
* const codec = getU8Codec();
* const bytes = codec.encode(255); // 0xff
* const value = codec.decode(bytes); // 255
* ```
*
* @remarks
* This codec supports values between `0` and `2^8 - 1` (0 to 255).
* If you need larger integers, consider using {@link getU16Codec}, {@link getU32Codec}, or {@link getU64Codec}.
* For signed integers, use {@link getI8Codec}.
*
* Separate {@link getU8Encoder} and {@link getU8Decoder} functions are available.
*
* ```ts
* const bytes = getU8Encoder().encode(42);
* const value = getU8Decoder().decode(bytes);
* ```
*
* @see {@link getU8Encoder}
* @see {@link getU8Decoder}
*/
export declare const getU8Codec: () => FixedSizeCodec<bigint | number, number, 1>;
//# sourceMappingURL=u8.d.ts.map

View File

@@ -0,0 +1,166 @@
import { a as namespaces, i as enabled, n as disable, o as humanize, r as enable$1, s as selectColor, t as createDebug$1 } from "./core.js";
//#region src/browser.ts
const colors = [
"#0000CC",
"#0000FF",
"#0033CC",
"#0033FF",
"#0066CC",
"#0066FF",
"#0099CC",
"#0099FF",
"#00CC00",
"#00CC33",
"#00CC66",
"#00CC99",
"#00CCCC",
"#00CCFF",
"#3300CC",
"#3300FF",
"#3333CC",
"#3333FF",
"#3366CC",
"#3366FF",
"#3399CC",
"#3399FF",
"#33CC00",
"#33CC33",
"#33CC66",
"#33CC99",
"#33CCCC",
"#33CCFF",
"#6600CC",
"#6600FF",
"#6633CC",
"#6633FF",
"#66CC00",
"#66CC33",
"#9900CC",
"#9900FF",
"#9933CC",
"#9933FF",
"#99CC00",
"#99CC33",
"#CC0000",
"#CC0033",
"#CC0066",
"#CC0099",
"#CC00CC",
"#CC00FF",
"#CC3300",
"#CC3333",
"#CC3366",
"#CC3399",
"#CC33CC",
"#CC33FF",
"#CC6600",
"#CC6633",
"#CC9900",
"#CC9933",
"#CCCC00",
"#CCCC33",
"#FF0000",
"#FF0033",
"#FF0066",
"#FF0099",
"#FF00CC",
"#FF00FF",
"#FF3300",
"#FF3333",
"#FF3366",
"#FF3399",
"#FF33CC",
"#FF33FF",
"#FF6600",
"#FF6633",
"#FF9900",
"#FF9933",
"#FFCC00",
"#FFCC33"
];
/**
* Colorize log arguments if enabled.
*/
function formatArgs(diff, args) {
const { useColors } = this;
args[0] = `${(useColors ? "%c" : "") + this.namespace + (useColors ? " %c" : " ") + args[0] + (useColors ? "%c " : " ")}+${this.humanize(diff)}`;
if (!useColors) return;
const c = `color: ${this.color}`;
args.splice(1, 0, c, "color: inherit");
let index = 0;
let lastC = 0;
args[0].replace(/%[a-z%]/gi, (match) => {
if (match === "%%") return;
index++;
if (match === "%c") lastC = index;
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.debug()` when available.
* No-op when `console.debug` is not a "function".
* If `console.debug` is not available, falls back
* to `console.log`.
*/
const log = console.debug || console.log || (() => {});
const storage = localstorage();
const defaultOptions = {
useColors: true,
formatArgs,
formatters: {
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
j(v) {
try {
return JSON.stringify(v);
} catch (error) {
return `[UnexpectedJSONParseError]: ${error.message}`;
}
} },
inspectOpts: {},
humanize,
log
};
function createDebug(namespace, options) {
var _ref;
const color = (_ref = options && options.color) !== null && _ref !== void 0 ? _ref : selectColor(colors, namespace);
return createDebug$1(namespace, Object.assign(defaultOptions, { color }, options));
}
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*/
function localstorage() {
try {
return localStorage;
} catch (_unused) {}
}
function load() {
let r;
try {
r = storage.getItem("debug") || storage.getItem("DEBUG");
} catch (_unused2) {}
if (!r && typeof process !== "undefined" && "env" in process) r = process.env.DEBUG;
return r || "";
}
function save(namespaces) {
try {
if (namespaces) storage.setItem("debug", namespaces);
else storage.removeItem("debug");
} catch (_unused3) {}
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*/
function enable(namespaces) {
save(namespaces);
enable$1(namespaces);
}
enable$1(load());
//#endregion
export { createDebug, disable, enable, enabled, namespaces };

View File

@@ -0,0 +1,239 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OptionKeys = void 0;
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
var OptionKeys;
(function (OptionKeys) {
OptionKeys["ArrayDestructuring"] = "arrayDestructuring";
OptionKeys["ArrowParameter"] = "arrowParameter";
OptionKeys["MemberVariableDeclaration"] = "memberVariableDeclaration";
OptionKeys["ObjectDestructuring"] = "objectDestructuring";
OptionKeys["Parameter"] = "parameter";
OptionKeys["PropertyDeclaration"] = "propertyDeclaration";
OptionKeys["VariableDeclaration"] = "variableDeclaration";
OptionKeys["VariableDeclarationIgnoreFunction"] = "variableDeclarationIgnoreFunction";
})(OptionKeys || (exports.OptionKeys = OptionKeys = {}));
exports.default = (0, util_1.createRule)({
name: 'typedef',
meta: {
type: 'suggestion',
deprecated: {
deprecatedSince: '8.33.0',
message: 'This is an old rule that is no longer recommended for use.',
},
docs: {
description: 'Require type annotations in certain places',
},
messages: {
expectedTypedef: 'Expected a type annotation.',
expectedTypedefNamed: 'Expected {{name}} to have a type annotation.',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
[OptionKeys.ArrayDestructuring]: {
type: 'boolean',
description: 'Whether to enforce type annotations on variables declared using array destructuring.',
},
[OptionKeys.ArrowParameter]: {
type: 'boolean',
description: 'Whether to enforce type annotations for parameters of arrow functions.',
},
[OptionKeys.MemberVariableDeclaration]: {
type: 'boolean',
description: 'Whether to enforce type annotations on member variables of classes.',
},
[OptionKeys.ObjectDestructuring]: {
type: 'boolean',
description: 'Whether to enforce type annotations on variables declared using object destructuring.',
},
[OptionKeys.Parameter]: {
type: 'boolean',
description: 'Whether to enforce type annotations for parameters of functions and methods.',
},
[OptionKeys.PropertyDeclaration]: {
type: 'boolean',
description: 'Whether to enforce type annotations for properties of interfaces and types.',
},
[OptionKeys.VariableDeclaration]: {
type: 'boolean',
description: 'Whether to enforce type annotations for variable declarations, excluding array and object destructuring.',
},
[OptionKeys.VariableDeclarationIgnoreFunction]: {
type: 'boolean',
description: 'Whether to ignore variable declarations for non-arrow and arrow functions.',
},
},
},
],
},
defaultOptions: [
{
[OptionKeys.ArrayDestructuring]: false,
[OptionKeys.ArrowParameter]: false,
[OptionKeys.MemberVariableDeclaration]: false,
[OptionKeys.ObjectDestructuring]: false,
[OptionKeys.Parameter]: false,
[OptionKeys.PropertyDeclaration]: false,
[OptionKeys.VariableDeclaration]: false,
[OptionKeys.VariableDeclarationIgnoreFunction]: false,
},
],
create(context, [{ arrayDestructuring, arrowParameter, memberVariableDeclaration, objectDestructuring, parameter, propertyDeclaration, variableDeclaration, variableDeclarationIgnoreFunction, },]) {
function report(location, name) {
context.report({
node: location,
messageId: name ? 'expectedTypedefNamed' : 'expectedTypedef',
data: { name },
});
}
function getNodeName(node) {
return node.type === utils_1.AST_NODE_TYPES.Identifier ? node.name : undefined;
}
function isForOfStatementContext(node) {
let current = node.parent;
while (current) {
switch (current.type) {
case utils_1.AST_NODE_TYPES.VariableDeclarator:
case utils_1.AST_NODE_TYPES.VariableDeclaration:
case utils_1.AST_NODE_TYPES.ObjectPattern:
case utils_1.AST_NODE_TYPES.ArrayPattern:
case utils_1.AST_NODE_TYPES.Property:
current = current.parent;
break;
case utils_1.AST_NODE_TYPES.ForOfStatement:
return true;
default:
current = undefined;
}
}
return false;
}
function checkParameters(params) {
for (const param of params) {
let annotationNode;
switch (param.type) {
case utils_1.AST_NODE_TYPES.AssignmentPattern:
annotationNode = param.left;
break;
case utils_1.AST_NODE_TYPES.TSParameterProperty:
annotationNode = param.parameter;
// Check TS parameter property with default value like `constructor(private param: string = 'something') {}`
if (annotationNode.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
annotationNode = annotationNode.left;
}
break;
default:
annotationNode = param;
break;
}
if (!annotationNode.typeAnnotation) {
report(param, getNodeName(param));
}
}
}
function isVariableDeclarationIgnoreFunction(node) {
return (variableDeclarationIgnoreFunction === true &&
(node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
node.type === utils_1.AST_NODE_TYPES.FunctionExpression));
}
function isAncestorHasTypeAnnotation(node) {
let ancestor = node.parent;
while (ancestor) {
if ((ancestor.type === utils_1.AST_NODE_TYPES.ObjectPattern ||
ancestor.type === utils_1.AST_NODE_TYPES.ArrayPattern) &&
ancestor.typeAnnotation) {
return true;
}
ancestor = ancestor.parent;
}
return false;
}
return {
...(arrayDestructuring && {
ArrayPattern(node) {
if (node.parent.type === utils_1.AST_NODE_TYPES.RestElement &&
node.parent.typeAnnotation) {
return;
}
if (!node.typeAnnotation &&
!isForOfStatementContext(node) &&
!isAncestorHasTypeAnnotation(node) &&
node.parent.type !== utils_1.AST_NODE_TYPES.AssignmentExpression) {
report(node);
}
},
}),
...(arrowParameter && {
ArrowFunctionExpression(node) {
checkParameters(node.params);
},
}),
...(memberVariableDeclaration && {
PropertyDefinition(node) {
if (!(node.value && isVariableDeclarationIgnoreFunction(node.value)) &&
!node.typeAnnotation) {
report(node, node.key.type === utils_1.AST_NODE_TYPES.Identifier
? node.key.name
: undefined);
}
},
}),
...(parameter && {
'FunctionDeclaration, FunctionExpression'(node) {
checkParameters(node.params);
},
}),
...(objectDestructuring && {
ObjectPattern(node) {
if (!node.typeAnnotation &&
!isForOfStatementContext(node) &&
!isAncestorHasTypeAnnotation(node)) {
report(node);
}
},
}),
...(propertyDeclaration && {
'TSIndexSignature, TSPropertySignature'(node) {
if (!node.typeAnnotation) {
report(node, node.type === utils_1.AST_NODE_TYPES.TSPropertySignature
? getNodeName(node.key)
: undefined);
}
},
}),
VariableDeclarator(node) {
if (!variableDeclaration ||
node.id.typeAnnotation ||
(node.id.type === utils_1.AST_NODE_TYPES.ArrayPattern &&
!arrayDestructuring) ||
(node.id.type === utils_1.AST_NODE_TYPES.ObjectPattern &&
!objectDestructuring) ||
(node.init && isVariableDeclarationIgnoreFunction(node.init))) {
return;
}
let current = node.parent;
while (current) {
switch (current.type) {
case utils_1.AST_NODE_TYPES.VariableDeclaration:
// Keep looking upwards
current = current.parent;
break;
case utils_1.AST_NODE_TYPES.ForOfStatement:
case utils_1.AST_NODE_TYPES.ForInStatement:
// Stop traversing and don't report an error
return;
default:
// Stop traversing
current = undefined;
break;
}
}
report(node, getNodeName(node.id));
},
};
},
});

View File

@@ -0,0 +1,37 @@
'use strict';
var test = require('tape');
var parse = require('../');
test('boolean default true', function (t) {
var argv = parse([], {
boolean: 'sometrue',
default: { sometrue: true },
});
t.equal(argv.sometrue, true);
t.end();
});
test('boolean default false', function (t) {
var argv = parse([], {
boolean: 'somefalse',
default: { somefalse: false },
});
t.equal(argv.somefalse, false);
t.end();
});
test('boolean default to null', function (t) {
var argv = parse([], {
boolean: 'maybe',
default: { maybe: null },
});
t.equal(argv.maybe, null);
var argvLong = parse(['--maybe'], {
boolean: 'maybe',
default: { maybe: null },
});
t.equal(argvLong.maybe, true);
t.end();
});

View File

@@ -0,0 +1 @@
function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t,n={exports:{}};var r=(t||(t=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function s(e,t,r,s,i){if("function"!=typeof r)throw new TypeError("The listener must be a function");var c=new o(r,s||e,i),f=n?n+t:t;return e._events[f]?e._events[f].fn?e._events[f]=[e._events[f],c]:e._events[f].push(c):(e._events[f]=c,e._eventsCount++),e}function i(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function c(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),c.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},c.prototype.listeners=function(e){var t=n?n+e:e,r=this._events[t];if(!r)return[];if(r.fn)return[r.fn];for(var o=0,s=r.length,i=new Array(s);o<s;o++)i[o]=r[o].fn;return i},c.prototype.listenerCount=function(e){var t=n?n+e:e,r=this._events[t];return r?r.fn?1:r.length:0},c.prototype.emit=function(e,t,r,o,s,i){var c=n?n+e:e;if(!this._events[c])return!1;var f,a,u=this._events[c],l=arguments.length;if(u.fn){switch(u.once&&this.removeListener(e,u.fn,void 0,!0),l){case 1:return u.fn.call(u.context),!0;case 2:return u.fn.call(u.context,t),!0;case 3:return u.fn.call(u.context,t,r),!0;case 4:return u.fn.call(u.context,t,r,o),!0;case 5:return u.fn.call(u.context,t,r,o,s),!0;case 6:return u.fn.call(u.context,t,r,o,s,i),!0}for(a=1,f=new Array(l-1);a<l;a++)f[a-1]=arguments[a];u.fn.apply(u.context,f)}else{var p,v=u.length;for(a=0;a<v;a++)switch(u[a].once&&this.removeListener(e,u[a].fn,void 0,!0),l){case 1:u[a].fn.call(u[a].context);break;case 2:u[a].fn.call(u[a].context,t);break;case 3:u[a].fn.call(u[a].context,t,r);break;case 4:u[a].fn.call(u[a].context,t,r,o);break;default:if(!f)for(p=1,f=new Array(l-1);p<l;p++)f[p-1]=arguments[p];u[a].fn.apply(u[a].context,f)}}return!0},c.prototype.on=function(e,t,n){return s(this,e,t,n,!1)},c.prototype.once=function(e,t,n){return s(this,e,t,n,!0)},c.prototype.removeListener=function(e,t,r,o){var s=n?n+e:e;if(!this._events[s])return this;if(!t)return i(this,s),this;var c=this._events[s];if(c.fn)c.fn!==t||o&&!c.once||r&&c.context!==r||i(this,s);else{for(var f=0,a=[],u=c.length;f<u;f++)(c[f].fn!==t||o&&!c[f].once||r&&c[f].context!==r)&&a.push(c[f]);a.length?this._events[s]=1===a.length?a[0]:a:i(this,s)}return this},c.prototype.removeAllListeners=function(e){var t;return e?(t=n?n+e:e,this._events[t]&&i(this,t)):(this._events=new r,this._eventsCount=0),this},c.prototype.off=c.prototype.removeListener,c.prototype.addListener=c.prototype.on,c.prefixed=n,c.EventEmitter=c,e.exports=c}(n)),n.exports),o=e(r);export{o as EventEmitter,o as default};//# sourceMappingURL=eventemitter3.esm.min.js.map

View File

@@ -0,0 +1,234 @@
/**
* SHA3 (keccak) hash function, based on a new "Sponge function" design.
* Different from older hashes, the internal state is bigger than output size.
*
* Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),
* [Website](https://keccak.team/keccak.html),
* [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).
*
* Check out `sha3-addons` module for cSHAKE, k12, and others.
* @module
*/
import { rotlBH, rotlBL, rotlSH, rotlSL, split } from "./_u64.js";
// prettier-ignore
import { abytes, aexists, anumber, aoutput, clean, createHasher, createXOFer, Hash, swap32IfBE, toBytes, u32 } from "./utils.js";
// No __PURE__ annotations in sha3 header:
// EVERYTHING is in fact used on every export.
// Various per round constants calculations
const _0n = BigInt(0);
const _1n = BigInt(1);
const _2n = BigInt(2);
const _7n = BigInt(7);
const _256n = BigInt(256);
const _0x71n = BigInt(0x71);
const SHA3_PI = [];
const SHA3_ROTL = [];
const _SHA3_IOTA = [];
for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
// Pi
[x, y] = [y, (2 * x + 3 * y) % 5];
SHA3_PI.push(2 * (5 * y + x));
// Rotational
SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
// Iota
let t = _0n;
for (let j = 0; j < 7; j++) {
R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;
if (R & _2n)
t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n);
}
_SHA3_IOTA.push(t);
}
const IOTAS = split(_SHA3_IOTA, true);
const SHA3_IOTA_H = IOTAS[0];
const SHA3_IOTA_L = IOTAS[1];
// Left rotation (without 0, 32, 64)
const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));
const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));
/** `keccakf1600` internal function, additionally allows to adjust round count. */
export function keccakP(s, rounds = 24) {
const B = new Uint32Array(5 * 2);
// NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)
for (let round = 24 - rounds; round < 24; round++) {
// Theta θ
for (let x = 0; x < 10; x++)
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
for (let x = 0; x < 10; x += 2) {
const idx1 = (x + 8) % 10;
const idx0 = (x + 2) % 10;
const B0 = B[idx0];
const B1 = B[idx0 + 1];
const Th = rotlH(B0, B1, 1) ^ B[idx1];
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
for (let y = 0; y < 50; y += 10) {
s[x + y] ^= Th;
s[x + y + 1] ^= Tl;
}
}
// Rho (ρ) and Pi (π)
let curH = s[2];
let curL = s[3];
for (let t = 0; t < 24; t++) {
const shift = SHA3_ROTL[t];
const Th = rotlH(curH, curL, shift);
const Tl = rotlL(curH, curL, shift);
const PI = SHA3_PI[t];
curH = s[PI];
curL = s[PI + 1];
s[PI] = Th;
s[PI + 1] = Tl;
}
// Chi (χ)
for (let y = 0; y < 50; y += 10) {
for (let x = 0; x < 10; x++)
B[x] = s[y + x];
for (let x = 0; x < 10; x++)
s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
}
// Iota (ι)
s[0] ^= SHA3_IOTA_H[round];
s[1] ^= SHA3_IOTA_L[round];
}
clean(B);
}
/** Keccak sponge function. */
export class Keccak extends Hash {
// NOTE: we accept arguments in bytes instead of bits here.
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
super();
this.pos = 0;
this.posOut = 0;
this.finished = false;
this.destroyed = false;
this.enableXOF = false;
this.blockLen = blockLen;
this.suffix = suffix;
this.outputLen = outputLen;
this.enableXOF = enableXOF;
this.rounds = rounds;
// Can be passed from user as dkLen
anumber(outputLen);
// 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes
// 0 < blockLen < 200
if (!(0 < blockLen && blockLen < 200))
throw new Error('only keccak-f1600 function is supported');
this.state = new Uint8Array(200);
this.state32 = u32(this.state);
}
clone() {
return this._cloneInto();
}
keccak() {
swap32IfBE(this.state32);
keccakP(this.state32, this.rounds);
swap32IfBE(this.state32);
this.posOut = 0;
this.pos = 0;
}
update(data) {
aexists(this);
data = toBytes(data);
abytes(data);
const { blockLen, state } = this;
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
for (let i = 0; i < take; i++)
state[this.pos++] ^= data[pos++];
if (this.pos === blockLen)
this.keccak();
}
return this;
}
finish() {
if (this.finished)
return;
this.finished = true;
const { state, suffix, pos, blockLen } = this;
// Do the padding
state[pos] ^= suffix;
if ((suffix & 0x80) !== 0 && pos === blockLen - 1)
this.keccak();
state[blockLen - 1] ^= 0x80;
this.keccak();
}
writeInto(out) {
aexists(this, false);
abytes(out);
this.finish();
const bufferOut = this.state;
const { blockLen } = this;
for (let pos = 0, len = out.length; pos < len;) {
if (this.posOut >= blockLen)
this.keccak();
const take = Math.min(blockLen - this.posOut, len - pos);
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
this.posOut += take;
pos += take;
}
return out;
}
xofInto(out) {
// Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF
if (!this.enableXOF)
throw new Error('XOF is not possible for this instance');
return this.writeInto(out);
}
xof(bytes) {
anumber(bytes);
return this.xofInto(new Uint8Array(bytes));
}
digestInto(out) {
aoutput(out, this);
if (this.finished)
throw new Error('digest() was already called');
this.writeInto(out);
this.destroy();
return out;
}
digest() {
return this.digestInto(new Uint8Array(this.outputLen));
}
destroy() {
this.destroyed = true;
clean(this.state);
}
_cloneInto(to) {
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
to.state32.set(this.state32);
to.pos = this.pos;
to.posOut = this.posOut;
to.finished = this.finished;
to.rounds = rounds;
// Suffix can change in cSHAKE
to.suffix = suffix;
to.outputLen = outputLen;
to.enableXOF = enableXOF;
to.destroyed = this.destroyed;
return to;
}
}
const gen = (suffix, blockLen, outputLen) => createHasher(() => new Keccak(blockLen, suffix, outputLen));
/** SHA3-224 hash function. */
export const sha3_224 = /* @__PURE__ */ (() => gen(0x06, 144, 224 / 8))();
/** SHA3-256 hash function. Different from keccak-256. */
export const sha3_256 = /* @__PURE__ */ (() => gen(0x06, 136, 256 / 8))();
/** SHA3-384 hash function. */
export const sha3_384 = /* @__PURE__ */ (() => gen(0x06, 104, 384 / 8))();
/** SHA3-512 hash function. */
export const sha3_512 = /* @__PURE__ */ (() => gen(0x06, 72, 512 / 8))();
/** keccak-224 hash function. */
export const keccak_224 = /* @__PURE__ */ (() => gen(0x01, 144, 224 / 8))();
/** keccak-256 hash function. Different from SHA3-256. */
export const keccak_256 = /* @__PURE__ */ (() => gen(0x01, 136, 256 / 8))();
/** keccak-384 hash function. */
export const keccak_384 = /* @__PURE__ */ (() => gen(0x01, 104, 384 / 8))();
/** keccak-512 hash function. */
export const keccak_512 = /* @__PURE__ */ (() => gen(0x01, 72, 512 / 8))();
const genShake = (suffix, blockLen, outputLen) => createXOFer((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));
/** SHAKE128 XOF with 128-bit security. */
export const shake128 = /* @__PURE__ */ (() => genShake(0x1f, 168, 128 / 8))();
/** SHAKE256 XOF with 256-bit security. */
export const shake256 = /* @__PURE__ */ (() => genShake(0x1f, 136, 256 / 8))();
//# sourceMappingURL=sha3.js.map

View File

@@ -0,0 +1,548 @@
# ws: a Node.js WebSocket library
[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
[![CI](https://img.shields.io/github/actions/workflow/status/websockets/ws/ci.yml?branch=master&label=CI&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster)
[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws)
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
server implementation.
Passes the quite extensive Autobahn test suite: [server][server-report],
[client][client-report].
**Note**: This module does not work in the browser. The client in the docs is a
reference to a backend with the role of a client in the WebSocket communication.
Browser clients must use the native
[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
object. To make the same code work seamlessly on Node.js and the browser, you
can use one of the many wrappers available on npm, like
[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws).
## Table of Contents
- [Protocol support](#protocol-support)
- [Installing](#installing)
- [Opt-in for performance](#opt-in-for-performance)
- [Legacy opt-in for performance](#legacy-opt-in-for-performance)
- [API docs](#api-docs)
- [WebSocket compression](#websocket-compression)
- [Usage examples](#usage-examples)
- [Sending and receiving text data](#sending-and-receiving-text-data)
- [Sending binary data](#sending-binary-data)
- [Simple server](#simple-server)
- [External HTTP/S server](#external-https-server)
- [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
- [Client authentication](#client-authentication)
- [Server broadcast](#server-broadcast)
- [Round-trip time](#round-trip-time)
- [Use the Node.js streams API](#use-the-nodejs-streams-api)
- [Other examples](#other-examples)
- [FAQ](#faq)
- [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
- [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
- [How to connect via a proxy?](#how-to-connect-via-a-proxy)
- [Changelog](#changelog)
- [License](#license)
## Protocol support
- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
- **HyBi drafts 13-17** (Current default, alternatively option
`protocolVersion: 13`)
## Installing
```
npm install ws
```
### Opt-in for performance
[bufferutil][] is an optional module that can be installed alongside the ws
module:
```
npm install --save-optional bufferutil
```
This is a binary addon that improves the performance of certain operations such
as masking and unmasking the data payload of the WebSocket frames. Prebuilt
binaries are available for the most popular platforms, so you don't necessarily
need to have a C++ compiler installed on your machine.
To force ws to not use bufferutil, use the
[`WS_NO_BUFFER_UTIL`](./doc/ws.md#ws_no_buffer_util) environment variable. This
can be useful to enhance security in systems where a user can put a package in
the package search path of an application of another user, due to how the
Node.js resolver algorithm works.
#### Legacy opt-in for performance
If you are running on an old version of Node.js (prior to v18.14.0), ws also
supports the [utf-8-validate][] module:
```
npm install --save-optional utf-8-validate
```
This contains a binary polyfill for [`buffer.isUtf8()`][].
To force ws not to use utf-8-validate, use the
[`WS_NO_UTF_8_VALIDATE`](./doc/ws.md#ws_no_utf_8_validate) environment variable.
## API docs
See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
utility functions.
## WebSocket compression
ws supports the [permessage-deflate extension][permessage-deflate] which enables
the client and server to negotiate a compression algorithm and its parameters,
and then selectively apply it to the data payloads of each WebSocket message.
The extension is disabled by default on the server and enabled by default on the
client. It adds a significant overhead in terms of performance and memory
consumption so we suggest to enable it only if it is really needed.
Note that Node.js has a variety of issues with high-performance compression,
where increased concurrency, especially on Linux, can lead to [catastrophic
memory fragmentation][node-zlib-bug] and slow performance. If you intend to use
permessage-deflate in production, it is worthwhile to set up a test
representative of your workload and ensure Node.js/zlib will handle it with
acceptable performance and memory usage.
Tuning of permessage-deflate can be done via the options defined below. You can
also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly
into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
See [the docs][ws-server-options] for more options.
```js
import WebSocket, { WebSocketServer } from 'ws';
const wss = new WebSocketServer({
port: 8080,
perMessageDeflate: {
zlibDeflateOptions: {
// See zlib defaults.
chunkSize: 1024,
memLevel: 7,
level: 3
},
zlibInflateOptions: {
chunkSize: 10 * 1024
},
// Other options settable:
clientNoContextTakeover: true, // Defaults to negotiated value.
serverNoContextTakeover: true, // Defaults to negotiated value.
serverMaxWindowBits: 10, // Defaults to negotiated value.
// Below options specified as default values.
concurrencyLimit: 10, // Limits zlib concurrency for perf.
threshold: 1024 // Size (in bytes) below which messages
// should not be compressed if context takeover is disabled.
}
});
```
The client will only use the extension if it is supported and enabled on the
server. To always disable the extension on the client, set the
`perMessageDeflate` option to `false`.
```js
import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path', {
perMessageDeflate: false
});
```
## Usage examples
### Sending and receiving text data
```js
import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path');
ws.on('error', console.error);
ws.on('open', function open() {
ws.send('something');
});
ws.on('message', function message(data) {
console.log('received: %s', data);
});
```
### Sending binary data
```js
import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path');
ws.on('error', console.error);
ws.on('open', function open() {
const array = new Float32Array(5);
for (var i = 0; i < array.length; ++i) {
array[i] = i / 2;
}
ws.send(array);
});
```
### Simple server
```js
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
ws.on('message', function message(data) {
console.log('received: %s', data);
});
ws.send('something');
});
```
### External HTTP/S server
```js
import { createServer } from 'https';
import { readFileSync } from 'fs';
import { WebSocketServer } from 'ws';
const server = createServer({
cert: readFileSync('/path/to/cert.pem'),
key: readFileSync('/path/to/key.pem')
});
const wss = new WebSocketServer({ server });
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
ws.on('message', function message(data) {
console.log('received: %s', data);
});
ws.send('something');
});
server.listen(8080);
```
### Multiple servers sharing a single HTTP/S server
```js
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
const server = createServer();
const wss1 = new WebSocketServer({ noServer: true });
const wss2 = new WebSocketServer({ noServer: true });
wss1.on('connection', function connection(ws) {
ws.on('error', console.error);
// ...
});
wss2.on('connection', function connection(ws) {
ws.on('error', console.error);
// ...
});
server.on('upgrade', function upgrade(request, socket, head) {
const { pathname } = new URL(request.url, 'wss://base.url');
if (pathname === '/foo') {
wss1.handleUpgrade(request, socket, head, function done(ws) {
wss1.emit('connection', ws, request);
});
} else if (pathname === '/bar') {
wss2.handleUpgrade(request, socket, head, function done(ws) {
wss2.emit('connection', ws, request);
});
} else {
socket.destroy();
}
});
server.listen(8080);
```
### Client authentication
```js
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
function onSocketError(err) {
console.error(err);
}
const server = createServer();
const wss = new WebSocketServer({ noServer: true });
wss.on('connection', function connection(ws, request, client) {
ws.on('error', console.error);
ws.on('message', function message(data) {
console.log(`Received message ${data} from user ${client}`);
});
});
server.on('upgrade', function upgrade(request, socket, head) {
socket.on('error', onSocketError);
// This function is not defined on purpose. Implement it with your own logic.
authenticate(request, function next(err, client) {
if (err || !client) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
socket.removeListener('error', onSocketError);
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request, client);
});
});
});
server.listen(8080);
```
Also see the provided [example][session-parse-example] using `express-session`.
### Server broadcast
A client WebSocket broadcasting to all connected WebSocket clients, including
itself.
```js
import WebSocket, { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
ws.on('message', function message(data, isBinary) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data, { binary: isBinary });
}
});
});
});
```
A client WebSocket broadcasting to every other connected WebSocket clients,
excluding itself.
```js
import WebSocket, { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('error', console.error);
ws.on('message', function message(data, isBinary) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data, { binary: isBinary });
}
});
});
});
```
### Round-trip time
```js
import WebSocket from 'ws';
const ws = new WebSocket('wss://websocket-echo.com/');
ws.on('error', console.error);
ws.on('open', function open() {
console.log('connected');
ws.send(Date.now());
});
ws.on('close', function close() {
console.log('disconnected');
});
ws.on('message', function message(data) {
console.log(`Round-trip time: ${Date.now() - data} ms`);
setTimeout(function timeout() {
ws.send(Date.now());
}, 500);
});
```
### Use the Node.js streams API
```js
import WebSocket, { createWebSocketStream } from 'ws';
const ws = new WebSocket('wss://websocket-echo.com/');
const duplex = createWebSocketStream(ws, { encoding: 'utf8' });
duplex.on('error', console.error);
duplex.pipe(process.stdout);
process.stdin.pipe(duplex);
```
### Other examples
For a full example with a browser client communicating with a ws server, see the
examples folder.
Otherwise, see the test cases.
## FAQ
### How to get the IP address of the client?
The remote IP address can be obtained from the raw socket.
```js
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws, req) {
const ip = req.socket.remoteAddress;
ws.on('error', console.error);
});
```
When the server runs behind a proxy like NGINX, the de-facto standard is to use
the `X-Forwarded-For` header.
```js
wss.on('connection', function connection(ws, req) {
const ip = req.headers['x-forwarded-for'].split(',')[0].trim();
ws.on('error', console.error);
});
```
### How to detect and close broken connections?
Sometimes, the link between the server and the client can be interrupted in a
way that keeps both the server and the client unaware of the broken state of the
connection (e.g. when pulling the cord).
In these cases, ping messages can be used as a means to verify that the remote
endpoint is still responsive.
```js
import { WebSocketServer } from 'ws';
function heartbeat() {
this.isAlive = true;
}
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.isAlive = true;
ws.on('error', console.error);
ws.on('pong', heartbeat);
});
const interval = setInterval(function ping() {
wss.clients.forEach(function each(ws) {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
wss.on('close', function close() {
clearInterval(interval);
});
```
Pong messages are automatically sent in response to ping messages as required by
the spec.
Just like the server example above, your clients might as well lose connection
without knowing it. You might want to add a ping listener on your clients to
prevent that. A simple implementation would be:
```js
import WebSocket from 'ws';
function heartbeat() {
clearTimeout(this.pingTimeout);
// Use `WebSocket#terminate()`, which immediately destroys the connection,
// instead of `WebSocket#close()`, which waits for the close timer.
// Delay should be equal to the interval at which your server
// sends out pings plus a conservative assumption of the latency.
this.pingTimeout = setTimeout(() => {
this.terminate();
}, 30000 + 1000);
}
const client = new WebSocket('wss://websocket-echo.com/');
client.on('error', console.error);
client.on('open', heartbeat);
client.on('ping', heartbeat);
client.on('close', function clear() {
clearTimeout(this.pingTimeout);
});
```
### How to connect via a proxy?
Use a custom `http.Agent` implementation like [https-proxy-agent][] or
[socks-proxy-agent][].
## Changelog
We're using the GitHub [releases][changelog] for changelog entries.
## License
[MIT](LICENSE)
[`buffer.isutf8()`]: https://nodejs.org/api/buffer.html#bufferisutf8input
[bufferutil]: https://github.com/websockets/bufferutil
[changelog]: https://github.com/websockets/ws/releases
[client-report]: http://websockets.github.io/ws/autobahn/clients/
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
[node-zlib-deflaterawdocs]:
https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
[permessage-deflate]: https://tools.ietf.org/html/rfc7692
[server-report]: http://websockets.github.io/ws/autobahn/servers/
[session-parse-example]: ./examples/express-session-parse
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
[utf-8-validate]: https://github.com/websockets/utf-8-validate
[ws-server-options]: ./doc/ws.md#new-websocketserveroptions-callback

View File

@@ -0,0 +1,126 @@
/**
* @fileoverview Rule to disallow if as the only statement in an else block
* @author Brandon Mills
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Disallow `if` statements as the only statement in `else` blocks",
recommended: false,
frozen: true,
url: "https://eslint.org/docs/latest/rules/no-lonely-if",
},
schema: [],
fixable: "code",
messages: {
unexpectedLonelyIf:
"Unexpected if as the only statement in an else block.",
},
},
create(context) {
const sourceCode = context.sourceCode;
return {
IfStatement(node) {
const parent = node.parent,
grandparent = parent.parent;
if (
parent &&
parent.type === "BlockStatement" &&
parent.body.length === 1 &&
!astUtils.areBracesNecessary(parent, sourceCode) &&
grandparent &&
grandparent.type === "IfStatement" &&
parent === grandparent.alternate
) {
context.report({
node,
messageId: "unexpectedLonelyIf",
fix(fixer) {
const openingElseCurly =
sourceCode.getFirstToken(parent);
const closingElseCurly =
sourceCode.getLastToken(parent);
const elseKeyword =
sourceCode.getTokenBefore(openingElseCurly);
const tokenAfterElseBlock =
sourceCode.getTokenAfter(closingElseCurly);
const lastIfToken = sourceCode.getLastToken(
node.consequent,
);
const sourceText = sourceCode.getText();
if (
sourceText
.slice(
openingElseCurly.range[1],
node.range[0],
)
.trim() ||
sourceText
.slice(
node.range[1],
closingElseCurly.range[0],
)
.trim()
) {
// Don't fix if there are any non-whitespace characters interfering (e.g. comments)
return null;
}
if (
node.consequent.type !== "BlockStatement" &&
lastIfToken.value !== ";" &&
tokenAfterElseBlock &&
(node.consequent.loc.end.line ===
tokenAfterElseBlock.loc.start.line ||
/^[([/+`-]/u.test(
tokenAfterElseBlock.value,
) ||
lastIfToken.value === "++" ||
lastIfToken.value === "--")
) {
/*
* If the `if` statement has no block, and is not followed by a semicolon, make sure that fixing
* the issue would not change semantics due to ASI. If this would happen, don't do a fix.
*/
return null;
}
return fixer.replaceTextRange(
[
openingElseCurly.range[0],
closingElseCurly.range[1],
],
(elseKeyword.range[1] ===
openingElseCurly.range[0]
? " "
: "") + sourceCode.getText(node),
);
},
});
}
},
};
},
};