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,11 @@
/**
* Blake2b hash function. Focuses on 64-bit platforms, but in JS speed different from Blake2s is negligible.
* @module
* @deprecated
*/
import { BLAKE2b as B2B, blake2b as b2b } from "./blake2.js";
/** @deprecated Use import from `noble/hashes/blake2` module */
export const BLAKE2b = B2B;
/** @deprecated Use import from `noble/hashes/blake2` module */
export const blake2b = b2b;
//# sourceMappingURL=blake2b.js.map

View File

@@ -0,0 +1,35 @@
import { test } from 'node:test'
import assert from 'node:assert'
import { readFile } from 'fs/promises'
import ThreadStream from '../index.js'
import { join } from 'desm'
import { file } from './helper.js'
const nodeVersion = parseInt(process.versions.node.split('.')[0], 10)
// Native TypeScript stripping (--experimental-strip-types) is only available in Node 22.6+
test('typescript module with native type stripping', { skip: nodeVersion < 22 }, async function (t) {
const dest = file()
const stream = new ThreadStream({
filename: join(import.meta.url, 'ts', 'to-file.ts'),
workerData: { dest },
workerOpts: {
execArgv: ['--experimental-strip-types', '--disable-warning=ExperimentalWarning']
},
sync: false
})
t.after(() => stream.end())
assert.ok(stream.write('hello world\n'))
assert.ok(stream.write('something else\n'))
stream.end()
await new Promise((resolve) => {
stream.on('close', resolve)
})
const data = await readFile(dest, 'utf8')
assert.strictEqual(data, 'hello world\nsomething else\n')
})

View File

@@ -0,0 +1,4 @@
var basex = require('base-x')
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
module.exports = basex(ALPHABET)

View File

@@ -0,0 +1,49 @@
'use strict';
var KEYWORDS = [
'multipleOf',
'maximum',
'exclusiveMaximum',
'minimum',
'exclusiveMinimum',
'maxLength',
'minLength',
'pattern',
'additionalItems',
'maxItems',
'minItems',
'uniqueItems',
'maxProperties',
'minProperties',
'required',
'additionalProperties',
'enum',
'format',
'const'
];
module.exports = function (metaSchema, keywordsJsonPointers) {
for (var i=0; i<keywordsJsonPointers.length; i++) {
metaSchema = JSON.parse(JSON.stringify(metaSchema));
var segments = keywordsJsonPointers[i].split('/');
var keywords = metaSchema;
var j;
for (j=1; j<segments.length; j++)
keywords = keywords[segments[j]];
for (j=0; j<KEYWORDS.length; j++) {
var key = KEYWORDS[j];
var schema = keywords[key];
if (schema) {
keywords[key] = {
anyOf: [
schema,
{ $ref: 'https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#' }
]
};
}
}
}
return metaSchema;
};

View File

@@ -0,0 +1,6 @@
parserOptions:
ecmaVersion: 6
globals:
beforeEach: false
describe: false
it: false

View File

@@ -0,0 +1,159 @@
/** The Standard interface. */
export interface StandardTypedV1<Input = unknown, Output = Input> {
/** The Standard properties. */
readonly "~standard": StandardTypedV1.Props<Input, Output>;
}
export declare namespace StandardTypedV1 {
/** The Standard properties interface. */
export interface Props<Input = unknown, Output = Input> {
/** The version number of the standard. */
readonly version: 1;
/** The vendor name of the schema library. */
readonly vendor: string;
/** Inferred types associated with the schema. */
readonly types?: Types<Input, Output> | undefined;
}
/** The Standard types interface. */
export interface Types<Input = unknown, Output = Input> {
/** The input type of the schema. */
readonly input: Input;
/** The output type of the schema. */
readonly output: Output;
}
/** Infers the input type of a Standard. */
export type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
/** Infers the output type of a Standard. */
export type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
}
/** The Standard Schema interface. */
export interface StandardSchemaV1<Input = unknown, Output = Input> {
/** The Standard Schema properties. */
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
}
export declare namespace StandardSchemaV1 {
/** The Standard Schema properties interface. */
export interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
/** Validates unknown input values. */
readonly validate: (
value: unknown,
options?: StandardSchemaV1.Options | undefined
) => Result<Output> | Promise<Result<Output>>;
}
/** The result interface of the validate function. */
export type Result<Output> = SuccessResult<Output> | FailureResult;
/** The result interface if validation succeeds. */
export interface SuccessResult<Output> {
/** The typed output value. */
readonly value: Output;
/** The absence of issues indicates success. */
readonly issues?: undefined;
}
export interface Options {
/** Implicit support for additional vendor-specific parameters, if needed. */
readonly libraryOptions?: Record<string, unknown> | undefined;
}
/** The result interface if validation fails. */
export interface FailureResult {
/** The issues of failed validation. */
readonly issues: ReadonlyArray<Issue>;
}
/** The issue interface of the failure output. */
export interface Issue {
/** The error message of the issue. */
readonly message: string;
/** The path of the issue, if any. */
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
}
/** The path segment interface of the issue. */
export interface PathSegment {
/** The key representing a path segment. */
readonly key: PropertyKey;
}
/** The Standard types interface. */
export interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
/** Infers the input type of a Standard. */
export type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
/** Infers the output type of a Standard. */
export type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
}
/** The Standard JSON Schema interface. */
export interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
/** The Standard JSON Schema properties. */
readonly "~standard": StandardJSONSchemaV1.Props<Input, Output>;
}
export declare namespace StandardJSONSchemaV1 {
/** The Standard JSON Schema properties interface. */
export interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
/** Methods for generating the input/output JSON Schema. */
readonly jsonSchema: Converter;
}
/** The Standard JSON Schema converter interface. */
export interface Converter {
/** Converts the input type to JSON Schema. May throw if conversion is not supported. */
readonly input: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
/** Converts the output type to JSON Schema. May throw if conversion is not supported. */
readonly output: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
}
/** The target version of the generated JSON Schema.
*
* It is *strongly recommended* that implementers support `"draft-2020-12"` and `"draft-07"`, as they are both in wide use.
*
* The `"openapi-3.0"` target is intended as a standardized specifier for OpenAPI 3.0 which is a superset of JSON Schema `"draft-04"`.
*
* All other targets can be implemented on a best-effort basis. Libraries should throw if they don't support a specified target.
*/
export type Target =
| "draft-2020-12"
| "draft-07"
| "openapi-3.0"
// Accepts any string for future targets while preserving autocomplete
| ({} & string);
/** The options for the input/output methods. */
export interface Options {
/** Specifies the target version of the generated JSON Schema. Support for all versions is on a best-effort basis. If a given version is not supported, the library should throw. */
readonly target: Target;
/** Implicit support for additional vendor-specific parameters, if needed. */
readonly libraryOptions?: Record<string, unknown> | undefined;
}
/** The Standard types interface. */
export interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
/** Infers the input type of a Standard. */
export type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
/** Infers the output type of a Standard. */
export type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
}
export interface StandardSchemaWithJSONProps<Input = unknown, Output = Input>
extends StandardSchemaV1.Props<Input, Output>,
StandardJSONSchemaV1.Props<Input, Output> {}
/**
* An interface that combines StandardJSONSchema and StandardSchema.
*/
export interface StandardSchemaWithJSON<Input = unknown, Output = Input> {
"~standard": StandardSchemaWithJSONProps<Input, Output>;
}

View File

@@ -0,0 +1,334 @@
# stream-chain [![NPM version][npm-img]][npm-url]
[npm-img]: https://img.shields.io/npm/v/stream-chain.svg
[npm-url]: https://npmjs.org/package/stream-chain
`stream-chain` creates a chain of streams out of regular functions, asynchronous functions, generator functions, and existing streams, while properly handling [backpressure](https://nodejs.org/en/docs/guides/backpressuring-in-streams/). The resulting chain is represented as a [Duplex](https://nodejs.org/api/stream.html#stream_class_stream_duplex) stream, which can be combined with other streams the usual way. It eliminates a boilerplate helping to concentrate on functionality without losing the performance especially make it easy to build object mode data processing pipelines.
Originally `stream-chain` was used internally with [stream-fork](https://www.npmjs.com/package/stream-fork) and [stream-json](https://www.npmjs.com/package/stream-json) to create flexible data processing pipelines.
`stream-chain` is a lightweight, no-dependencies micro-package. It is distributed under New BSD license.
## Intro
```js
const Chain = require('stream-chain');
const fs = require('fs');
const zlib = require('zlib');
const {Transform} = require('stream');
// the chain will work on a stream of number objects
const chain = new Chain([
// transforms a value
x => x * x,
// returns several values
x => [x - 1, x, x + 1],
// waits for an asynchronous operation
async x => await getTotalFromDatabaseByKey(x),
// returns multiple values with a generator
function* (x) {
for (let i = x; i > 0; --i) {
yield i;
}
return 0;
},
// filters out even values
x => x % 2 ? x : null,
// uses an arbitrary transform stream
new Transform({
writableObjectMode: true,
transform(x, _, callback) {
// transform to text
callback(null, x.toString());
}
}),
// compress
zlib.createGzip()
]);
// log errors
chain.on('error', error => console.log(error));
// use the chain, and save the result to a file
dataSource.pipe(chain).pipe(fs.createWriteStream('output.txt.gz'));
```
Making processing pipelines appears to be easy: just chain functions one after another, and we are done. Real life pipelines filter objects out and/or produce more objects out of a few ones. On top of that we have to deal with asynchronous operations, while processing or producing data: networking, databases, files, user responses, and so on. Unequal number of values per stage, and unequal throughput of stages introduced problems like [backpressure](https://nodejs.org/en/docs/guides/backpressuring-in-streams/), which requires algorithms implemented by [streams](https://nodejs.org/api/stream.html).
While a lot of API improvements were made to make streams easy to use, in reality, a lot of boilerplate is required when creating a pipeline. `stream-chain` eliminates most of it.
## Installation
```bash
npm i --save stream-chain
# or: yarn add stream-chain
```
## Documentation
`Chain`, which is returned by `require('stream-chain')`, is based on [Duplex](https://nodejs.org/api/stream.html#stream_class_stream_duplex). It chains its dependents in a single pipeline optionally binding `error` events.
Many details about this package can be discovered by looking at test files located in `tests/` and in the source code (`index.js`).
### Constructor: `new Chain(fns[, options])`
The constructor accepts the following arguments:
* `fns` is an array of functions arrays or stream instances.
* If a value is a function, a [Transform](https://nodejs.org/api/stream.html#stream_class_stream_transform) stream is created, which calls this function with two parameters: `chunk` (an object), and an optional `encoding`. See [Node's documentation](https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback) for more details on those parameters. The function will be called in the context of the created stream.
* If it is a regular function, it can return:
* Regular value:
* *(deprecated since 2.1.0)* Array of values to pass several or zero values to the next stream as they are.
```js
// produces no values:
x => []
// produces two values:
x => [x, x + 1]
// produces one array value:
x => [[x, x + 1]]
```
* Single value.
* If it is `undefined` or `null`, no value shall be passed.
* Otherwise, the value will be passed to the next stream.
```js
// produces no values:
x => null
x => undefined
// produces one value:
x => x
```
* Special value:
* If it is an instance of [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or "thenable" (an object with a method called `then()`), it will be waited for. Its result should be a regular value.
```js
// delays by 0.5s:
x => new Promise(
resolve => setTimeout(() => resolve(x), 500))
```
* If it is an instance of a generator or "nextable" (an object with a method called `next()`), it will be iterated according to the [generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) protocol. The results should be regular values.
```js
// produces multiple values:
class Nextable {
constructor(x) {
this.x = x;
this.i = -1;
}
next() {
return {
done: this.i <= 1,
value: this.x + this.i++
};
}
}
x => new Nextable(x)
```
`next()` can return a `Promise` according to the [asynchronous generator](https://zaiste.net/nodejs_10_asynchronous_iteration_async_generators/) protocol.
* Any thrown exception will be caught and passed to a callback function effectively generating an error event.
```js
// fails
x => { throw new Error('Bad!'); }
```
* If it is an asynchronous function, it can return a regular value.
* In essence, it is covered under "special values" as a function that returns a promise.
```js
// delays by 0.5s:
async x => {
await new Promise(resolve => setTimeout(() => resolve(), 500));
return x;
}
```
* If it is a generator function, each yield should produce a regular value.
* In essence, it is covered under "special values" as a function that returns a generator object.
```js
// produces multiple values:
function* (x) {
for (let i = -1; i <= 1; ++i) {
if (i) yield x + i;
}
return x;
}
```
* *(since 2.2.0)* If it is an asynchronous generator function, each yield should produce a regular value.
* In essence, it is covered under "special values" as a function that returns a generator object.
```js
// produces multiple values:
async function* (x) {
for (let i = -1; i <= 1; ++i) {
if (i) {
await new Promise(resolve => setTimeout(() => resolve(), 50));
yield x + i;
}
}
return x;
}
```
* *(since 2.1.0)* If a value is an array, it is assumed to be an array of regular functions.
Their values are passed in a chain. All values (including `null`, `undefined`, and arrays) are allowed
and passed without modifications. The last value is a subject to processing defined above for regular functions.
* Empty arrays are ignored.
* If any function returns a value produced by `Chain.final(value)` (see below), it terminates the chain using
`value` as the final value of the chain.
* This feature bypasses streams. It is implemented for performance reasons.
* If a value is a valid stream, it is included as is in the pipeline.
* [Transform](https://nodejs.org/api/stream.html#stream_class_stream_transform).
* [Duplex](https://nodejs.org/api/stream.html#stream_class_stream_duplex).
* The very first stream can be [Readable](https://nodejs.org/api/stream.html#stream_class_stream_readable).
* In this case a `Chain` instance ignores all possible writes to the front, and ends when the first stream ends.
* The very last stream can be [Writable](https://nodejs.org/api/stream.html#stream_class_stream_writable).
* In this case a `Chain` instance does not produce any output, and finishes when the last stream finishes.
* Because `'data'` event is not used in this case, the instance resumes itself automatically. Read about it in Node's documentation:
* [Two modes](https://nodejs.org/api/stream.html#stream_two_modes).
* [readable.resume()](https://nodejs.org/api/stream.html#stream_readable_resume).
* `options` is an optional object detailed in the [Node's documentation](https://nodejs.org/api/stream.html#stream_new_stream_duplex_options).
* If `options` is not specified, or falsy, it is assumed to be:
```js
{writableObjectMode: true, readableObjectMode: true}
```
* Always make sure that `writableObjectMode` is the same as the corresponding object mode of the first stream, and `readableObjectMode` is the same as the corresponding object mode of the last stream.
* Eventually both these modes can be deduced, but Node does not define the standard way to determine it, so currently it cannot be done reliably.
* Additionally the following custom properties are recognized:
* `skipEvents` is an optional flag. If it is falsy (the default), `'error'` events from all streams are forwarded to the created instance. If it is truthy, no event forwarding is made. A user can always do so externally or in a constructor of derived classes.
An instance can be used to attach handlers for stream events.
```js
const chain = new Chain([x => x * x, x => [x - 1, x, x + 1]]);
chain.on('error', error => console.error(error));
dataSource.pipe(chain);
```
### Properties
Following public properties are available:
* `streams` is an array of streams created by a constructor. Its values either [Transform](https://nodejs.org/api/stream.html#stream_class_stream_transform) streams that use corresponding functions from a constructor parameter, or user-provided streams. All streams are piped sequentially starting from the beginning.
* `input` is the beginning of the pipeline. Effectively it is the first item of `streams`.
* `output` is the end of the pipeline. Effectively it is the last item of `streams`.
Generally, a `Chain` instance should be used to represent a chain:
```js
const chain = new Chain([
x => x * x,
x => [x - 1, x, x + 1],
new Transform({
writableObjectMode: true,
transform(chunk, _, callback) {
callback(null, chunk.toString());
}
})
]);
dataSource
.pipe(chain);
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('output.txt.gz'));
```
But in some cases `input` and `output` provide a better control over how a data processing pipeline should be organized:
```js
chain.output
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('output.txt.gz'));
dataSource.pipe(chain.input);
```
Please select what style you want to use, and never mix them together with the same object.
### Static methods
Following static methods are available:
* `chain(fns[, options)` is a helper factory function, which has the same arguments as the constructor and returns a `Chain` instance.
```js
const {chain} = require('stream-chain');
// simple
dataSource
.pipe(chain([x => x * x, x => [x - 1, x, x + 1]]));
// all inclusive
chain([
dataSource,
x => x * x,
x => [x - 1, x, x + 1],
zlib.createGzip(),
fs.createWriteStream('output.txt.gz')
])
```
* *(since 2.1.0)* `final(value)` is a helper factory function, which can be used in by chained functions (see above the array of functions).
It returns a special value, which terminates the chain and uses the passed value as the result of the chain.
```js
const {chain, final} = require('stream-chain');
// simple
dataSource
.pipe(chain([[x => x * x, x => 2 * x + 1]]));
// faster than [x => x * x, x => 2 * x + 1]
// final
dataSource
.pipe(chain([[
x => x * x,
x => final(x),
x => 2 * x + 1
]]));
// the same as [[x => x * x, x => x]]
// the same as [[x => x * x]]
// the same as [x => x * x]
// final as a terminator
dataSource
.pipe(chain([[
x => x * x,
x => final(),
x => 2 * x + 1
]]));
// produces no values, because the final value is undefined,
// which is interpreted as "no value shall be passed"
// see the doc above
// final() as a filter
dataSource
.pipe(chain([[
x => x * x,
x => x % 2 ? final() : x,
x => 2 * x + 1
]]));
// only even values are passed, odd values are ignored
// if you want to be really performant...
const none = final();
dataSource
.pipe(chain([[
x => x * x,
x => x % 2 ? none : x,
x => 2 * x + 1
]]));
```
* *(since 2.1.0)* `many(array)` is a helper factory function, which is used to wrap arrays to be interpreted as multiple values returned from a function.
At the moment it is redundant: you can use a simple array to indicate that, but a naked array is being deprecated and in future versions it will be passed as is.
The thinking is that using `many()` is better indicates the intention. Additionally, in the future versions it will be used by array of functions (see above).
```js
const {chain, many} = require('stream-chain');
dataSource
.pipe(chain([x => many([x, x + 1, x + 2])]));
// currently the same as [x => [x, x + 1, x + 2]]
```
## Release History
- 2.2.5 *Relaxed the definition of a stream (thx [Rich Hodgkins](https://github.com/rhodgkins)).*
- 2.2.4 *Bugfix: wrong `const`-ness in the async generator branch (thx [Patrick Pang](https://github.com/patrickpang)).*
- 2.2.3 *Technical release. No need to upgrade.*
- 2.2.2 *Technical release. No need to upgrade.*
- 2.2.1 *Technical release: new symbols namespace, explicit license (thx [Keen Yee Liau](https://github.com/kyliau)), added Greenkeeper.*
- 2.2.0 *Added utilities: `take`, `takeWhile`, `skip`, `skipWhile`, `fold`, `scan`, `Reduce`, `comp`.*
- 2.1.0 *Added simple transducers, dropped Node 6.*
- 2.0.3 *Added TypeScript typings and the badge.*
- 2.0.2 *Workaround for Node 6: use `'finish'` event instead of `_final()`.*
- 2.0.1 *Improved documentation.*
- 2.0.0 *Upgraded to use Duplex instead of EventEmitter as the base.*
- 1.0.3 *Improved documentation.*
- 1.0.2 *Better README.*
- 1.0.1 *Fixed the README.*
- 1.0.0 *The initial release.*

View File

@@ -0,0 +1,9 @@
import { Parser, Printer } from "../index.js";
export declare const parsers: {
graphql: Parser;
};
export declare const printers: {
graphql: Printer;
};

View File

@@ -0,0 +1,39 @@
/*! *****************************************************************************
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 Atomics {
/**
* A non-blocking, asynchronous version of wait which is usable on the main thread.
* Waits asynchronously on a shared memory location and returns a Promise
* @param typedArray A shared Int32Array or BigInt64Array.
* @param index The position in the typedArray to wait on.
* @param value The expected value to test.
* @param [timeout] The expected value to test.
*/
waitAsync(typedArray: Int32Array, index: number, value: number, timeout?: number): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; };
/**
* A non-blocking, asynchronous version of wait which is usable on the main thread.
* Waits asynchronously on a shared memory location and returns a Promise
* @param typedArray A shared Int32Array or BigInt64Array.
* @param index The position in the typedArray to wait on.
* @param value The expected value to test.
* @param [timeout] The expected value to test.
*/
waitAsync(typedArray: BigInt64Array, index: number, value: bigint, timeout?: number): { async: false; value: "not-equal" | "timed-out"; } | { async: true; value: Promise<"ok" | "timed-out">; };
}

View File

@@ -0,0 +1,497 @@
declare module "node:dns/promises" {
import {
AnyRecord,
CaaRecord,
LookupAddress,
LookupAllOptions,
LookupOneOptions,
LookupOptions,
MxRecord,
NaptrRecord,
RecordWithTtl,
ResolveOptions,
ResolverOptions,
ResolveWithTtlOptions,
SoaRecord,
SrvRecord,
TlsaRecord,
} from "node:dns";
/**
* Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6),
* that are currently configured for DNS resolution. A string will include a port
* section if a custom port is used.
*
* ```js
* [
* '4.4.4.4',
* '2001:4860:4860::8888',
* '4.4.4.4:1053',
* '[2001:4860:4860::8888]:1053',
* ]
* ```
* @since v10.6.0
*/
function getServers(): string[];
/**
* Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or
* AAAA (IPv6) record. All `option` properties are optional. If `options` is an
* integer, then it must be `4` or `6` if `options` is not provided, then IPv4
* and IPv6 addresses are both returned if found.
*
* With the `all` option set to `true`, the `Promise` is resolved with `addresses` being an array of objects with the properties `address` and `family`.
*
* On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is the error code.
* Keep in mind that `err.code` will be set to `'ENOTFOUND'` not only when
* the host name does not exist but also when the lookup fails in other ways
* such as no available file descriptors.
*
* [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options) does not necessarily have anything to do with the DNS
* protocol. The implementation uses an operating system facility that can
* associate names with addresses and vice versa. This implementation can have
* subtle but important consequences on the behavior of any Node.js program. Please
* take some time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations) before
* using `dnsPromises.lookup()`.
*
* Example usage:
*
* ```js
* import dns from 'node:dns';
* const dnsPromises = dns.promises;
* const options = {
* family: 6,
* hints: dns.ADDRCONFIG | dns.V4MAPPED,
* };
*
* dnsPromises.lookup('example.com', options).then((result) => {
* console.log('address: %j family: IPv%s', result.address, result.family);
* // address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6
* });
*
* // When options.all is true, the result will be an Array.
* options.all = true;
* dnsPromises.lookup('example.com', options).then((result) => {
* console.log('addresses: %j', result);
* // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}]
* });
* ```
* @since v10.6.0
*/
function lookup(hostname: string, family: number): Promise<LookupAddress>;
function lookup(hostname: string, options: LookupOneOptions): Promise<LookupAddress>;
function lookup(hostname: string, options: LookupAllOptions): Promise<LookupAddress[]>;
function lookup(hostname: string, options: LookupOptions): Promise<LookupAddress | LookupAddress[]>;
function lookup(hostname: string): Promise<LookupAddress>;
/**
* Resolves the given `address` and `port` into a host name and service using
* the operating system's underlying `getnameinfo` implementation.
*
* If `address` is not a valid IP address, a `TypeError` will be thrown.
* The `port` will be coerced to a number. If it is not a legal port, a `TypeError` will be thrown.
*
* On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is the error code.
*
* ```js
* import dnsPromises from 'node:dns';
* dnsPromises.lookupService('127.0.0.1', 22).then((result) => {
* console.log(result.hostname, result.service);
* // Prints: localhost ssh
* });
* ```
* @since v10.6.0
*/
function lookupService(
address: string,
port: number,
): Promise<{
hostname: string;
service: string;
}>;
/**
* Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array
* of the resource records. When successful, the `Promise` is resolved with an
* array of resource records. The type and structure of individual results vary
* based on `rrtype`:
*
* <omitted>
*
* On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code`
* is one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes).
* @since v10.6.0
* @param hostname Host name to resolve.
* @param [rrtype='A'] Resource record type.
*/
function resolve(hostname: string): Promise<string[]>;
function resolve(hostname: string, rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise<string[]>;
function resolve(hostname: string, rrtype: "ANY"): Promise<AnyRecord[]>;
function resolve(hostname: string, rrtype: "CAA"): Promise<CaaRecord[]>;
function resolve(hostname: string, rrtype: "MX"): Promise<MxRecord[]>;
function resolve(hostname: string, rrtype: "NAPTR"): Promise<NaptrRecord[]>;
function resolve(hostname: string, rrtype: "SOA"): Promise<SoaRecord>;
function resolve(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>;
function resolve(hostname: string, rrtype: "TLSA"): Promise<TlsaRecord[]>;
function resolve(hostname: string, rrtype: "TXT"): Promise<string[][]>;
function resolve(hostname: string, rrtype: string): Promise<
| string[]
| CaaRecord[]
| MxRecord[]
| NaptrRecord[]
| SoaRecord
| SrvRecord[]
| TlsaRecord[]
| string[][]
| AnyRecord[]
>;
/**
* Uses the DNS protocol to resolve IPv4 addresses (`A` records) for the `hostname`. On success, the `Promise` is resolved with an array of IPv4
* addresses (e.g. `['74.125.79.104', '74.125.79.105', '74.125.79.106']`).
* @since v10.6.0
* @param hostname Host name to resolve.
*/
function resolve4(hostname: string): Promise<string[]>;
function resolve4(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
function resolve4(hostname: string, options: ResolveOptions): Promise<string[] | RecordWithTtl[]>;
/**
* Uses the DNS protocol to resolve IPv6 addresses (`AAAA` records) for the `hostname`. On success, the `Promise` is resolved with an array of IPv6
* addresses.
* @since v10.6.0
* @param hostname Host name to resolve.
*/
function resolve6(hostname: string): Promise<string[]>;
function resolve6(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
function resolve6(hostname: string, options: ResolveOptions): Promise<string[] | RecordWithTtl[]>;
/**
* Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query).
* On success, the `Promise` is resolved with an array containing various types of
* records. Each object has a property `type` that indicates the type of the
* current record. And depending on the `type`, additional properties will be
* present on the object:
*
* <omitted>
*
* Here is an example of the result object:
*
* ```js
* [ { type: 'A', address: '127.0.0.1', ttl: 299 },
* { type: 'CNAME', value: 'example.com' },
* { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
* { type: 'NS', value: 'ns1.example.com' },
* { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
* { type: 'SOA',
* nsname: 'ns1.example.com',
* hostmaster: 'admin.example.com',
* serial: 156696742,
* refresh: 900,
* retry: 900,
* expire: 1800,
* minttl: 60 } ];
* ```
* @since v10.6.0
*/
function resolveAny(hostname: string): Promise<AnyRecord[]>;
/**
* Uses the DNS protocol to resolve `CAA` records for the `hostname`. On success,
* the `Promise` is resolved with an array of objects containing available
* certification authority authorization records available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: 'pki.example.com'}]`).
* @since v15.0.0, v14.17.0
*/
function resolveCaa(hostname: string): Promise<CaaRecord[]>;
/**
* Uses the DNS protocol to resolve `CNAME` records for the `hostname`. On success,
* the `Promise` is resolved with an array of canonical name records available for
* the `hostname` (e.g. `['bar.example.com']`).
* @since v10.6.0
*/
function resolveCname(hostname: string): Promise<string[]>;
/**
* Uses the DNS protocol to resolve mail exchange records (`MX` records) for the `hostname`. On success, the `Promise` is resolved with an array of objects
* containing both a `priority` and `exchange` property (e.g.`[{priority: 10, exchange: 'mx.example.com'}, ...]`).
* @since v10.6.0
*/
function resolveMx(hostname: string): Promise<MxRecord[]>;
/**
* Uses the DNS protocol to resolve regular expression-based records (`NAPTR` records) for the `hostname`. On success, the `Promise` is resolved with an array
* of objects with the following properties:
*
* * `flags`
* * `service`
* * `regexp`
* * `replacement`
* * `order`
* * `preference`
*
* ```js
* {
* flags: 's',
* service: 'SIP+D2U',
* regexp: '',
* replacement: '_sip._udp.example.com',
* order: 30,
* preference: 100,
* }
* ```
* @since v10.6.0
*/
function resolveNaptr(hostname: string): Promise<NaptrRecord[]>;
/**
* Uses the DNS protocol to resolve name server records (`NS` records) for the `hostname`. On success, the `Promise` is resolved with an array of name server
* records available for `hostname` (e.g.`['ns1.example.com', 'ns2.example.com']`).
* @since v10.6.0
*/
function resolveNs(hostname: string): Promise<string[]>;
/**
* Uses the DNS protocol to resolve pointer records (`PTR` records) for the `hostname`. On success, the `Promise` is resolved with an array of strings
* containing the reply records.
* @since v10.6.0
*/
function resolvePtr(hostname: string): Promise<string[]>;
/**
* Uses the DNS protocol to resolve a start of authority record (`SOA` record) for
* the `hostname`. On success, the `Promise` is resolved with an object with the
* following properties:
*
* * `nsname`
* * `hostmaster`
* * `serial`
* * `refresh`
* * `retry`
* * `expire`
* * `minttl`
*
* ```js
* {
* nsname: 'ns.example.com',
* hostmaster: 'root.example.com',
* serial: 2013101809,
* refresh: 10000,
* retry: 2400,
* expire: 604800,
* minttl: 3600,
* }
* ```
* @since v10.6.0
*/
function resolveSoa(hostname: string): Promise<SoaRecord>;
/**
* Uses the DNS protocol to resolve service records (`SRV` records) for the `hostname`. On success, the `Promise` is resolved with an array of objects with
* the following properties:
*
* * `priority`
* * `weight`
* * `port`
* * `name`
*
* ```js
* {
* priority: 10,
* weight: 5,
* port: 21223,
* name: 'service.example.com',
* }
* ```
* @since v10.6.0
*/
function resolveSrv(hostname: string): Promise<SrvRecord[]>;
/**
* Uses the DNS protocol to resolve certificate associations (`TLSA` records) for
* the `hostname`. On success, the `Promise` is resolved with an array of objectsAdd commentMore actions
* with these properties:
*
* * `certUsage`
* * `selector`
* * `match`
* * `data`
*
* ```js
* {
* certUsage: 3,
* selector: 1,
* match: 1,
* data: [ArrayBuffer],
* }
* ```
* @since v23.9.0, v22.15.0
*/
function resolveTlsa(hostname: string): Promise<TlsaRecord[]>;
/**
* Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. On success, the `Promise` is resolved with a two-dimensional array
* of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of
* one record. Depending on the use case, these could be either joined together or
* treated separately.
* @since v10.6.0
*/
function resolveTxt(hostname: string): Promise<string[][]>;
/**
* Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an
* array of host names.
*
* On error, the `Promise` is rejected with an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code`
* is one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes).
* @since v10.6.0
*/
function reverse(ip: string): Promise<string[]>;
/**
* Get the default value for `verbatim` in {@link lookup} and [dnsPromises.lookup()](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options).
* The value could be:
*
* * `ipv4first`: for `verbatim` defaulting to `false`.
* * `verbatim`: for `verbatim` defaulting to `true`.
* @since v20.1.0
*/
function getDefaultResultOrder(): "ipv4first" | "verbatim";
/**
* Sets the IP address and port of servers to be used when performing DNS
* resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted
* addresses. If the port is the IANA default DNS port (53) it can be omitted.
*
* ```js
* dnsPromises.setServers([
* '4.4.4.4',
* '[2001:4860:4860::8888]',
* '4.4.4.4:1053',
* '[2001:4860:4860::8888]:1053',
* ]);
* ```
*
* An error will be thrown if an invalid address is provided.
*
* The `dnsPromises.setServers()` method must not be called while a DNS query is in
* progress.
*
* This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html).
* That is, if attempting to resolve with the first server provided results in a `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with
* subsequent servers provided. Fallback DNS servers will only be used if the
* earlier ones time out or result in some other error.
* @since v10.6.0
* @param servers array of `RFC 5952` formatted addresses
*/
function setServers(servers: readonly string[]): void;
/**
* Set the default value of `order` in `dns.lookup()` and `{@link lookup}`. The value could be:
*
* * `ipv4first`: sets default `order` to `ipv4first`.
* * `ipv6first`: sets default `order` to `ipv6first`.
* * `verbatim`: sets default `order` to `verbatim`.
*
* The default is `verbatim` and [dnsPromises.setDefaultResultOrder()](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetdefaultresultorderorder)
* have higher priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder).
* When using [worker threads](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html), [`dnsPromises.setDefaultResultOrder()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetdefaultresultorderorder)
* from the main thread won't affect the default dns orders in workers.
* @since v16.4.0, v14.18.0
* @param order must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.
*/
function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void;
// Error codes
const NODATA: "ENODATA";
const FORMERR: "EFORMERR";
const SERVFAIL: "ESERVFAIL";
const NOTFOUND: "ENOTFOUND";
const NOTIMP: "ENOTIMP";
const REFUSED: "EREFUSED";
const BADQUERY: "EBADQUERY";
const BADNAME: "EBADNAME";
const BADFAMILY: "EBADFAMILY";
const BADRESP: "EBADRESP";
const CONNREFUSED: "ECONNREFUSED";
const TIMEOUT: "ETIMEOUT";
const EOF: "EOF";
const FILE: "EFILE";
const NOMEM: "ENOMEM";
const DESTRUCTION: "EDESTRUCTION";
const BADSTR: "EBADSTR";
const BADFLAGS: "EBADFLAGS";
const NONAME: "ENONAME";
const BADHINTS: "EBADHINTS";
const NOTINITIALIZED: "ENOTINITIALIZED";
const LOADIPHLPAPI: "ELOADIPHLPAPI";
const ADDRGETNETWORKPARAMS: "EADDRGETNETWORKPARAMS";
const CANCELLED: "ECANCELLED";
/**
* An independent resolver for DNS requests.
*
* Creating a new resolver uses the default server settings. Setting
* the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromisessetserversservers) does not affect
* other resolvers:
*
* ```js
* import { promises } from 'node:dns';
* const resolver = new promises.Resolver();
* resolver.setServers(['4.4.4.4']);
*
* // This request will use the server at 4.4.4.4, independent of global settings.
* resolver.resolve4('example.org').then((addresses) => {
* // ...
* });
*
* // Alternatively, the same code can be written using async-await style.
* (async function() {
* const addresses = await resolver.resolve4('example.org');
* })();
* ```
*
* The following methods from the `dnsPromises` API are available:
*
* * `resolver.getServers()`
* * `resolver.resolve()`
* * `resolver.resolve4()`
* * `resolver.resolve6()`
* * `resolver.resolveAny()`
* * `resolver.resolveCaa()`
* * `resolver.resolveCname()`
* * `resolver.resolveMx()`
* * `resolver.resolveNaptr()`
* * `resolver.resolveNs()`
* * `resolver.resolvePtr()`
* * `resolver.resolveSoa()`
* * `resolver.resolveSrv()`
* * `resolver.resolveTxt()`
* * `resolver.reverse()`
* * `resolver.setServers()`
* @since v10.6.0
*/
class Resolver {
constructor(options?: ResolverOptions);
/**
* Cancel all outstanding DNS queries made by this resolver. The corresponding
* callbacks will be called with an error with code `ECANCELLED`.
* @since v8.3.0
*/
cancel(): void;
getServers: typeof getServers;
resolve: typeof resolve;
resolve4: typeof resolve4;
resolve6: typeof resolve6;
resolveAny: typeof resolveAny;
resolveCaa: typeof resolveCaa;
resolveCname: typeof resolveCname;
resolveMx: typeof resolveMx;
resolveNaptr: typeof resolveNaptr;
resolveNs: typeof resolveNs;
resolvePtr: typeof resolvePtr;
resolveSoa: typeof resolveSoa;
resolveSrv: typeof resolveSrv;
resolveTlsa: typeof resolveTlsa;
resolveTxt: typeof resolveTxt;
reverse: typeof reverse;
/**
* The resolver instance will send its requests from the specified IP address.
* This allows programs to specify outbound interfaces when used on multi-homed
* systems.
*
* If a v4 or v6 address is not specified, it is set to the default and the
* operating system will choose a local address automatically.
*
* The resolver will use the v4 local address when making requests to IPv4 DNS
* servers, and the v6 local address when making requests to IPv6 DNS servers.
* The `rrtype` of resolution requests has no impact on the local address used.
* @since v15.1.0, v14.17.0
* @param [ipv4='0.0.0.0'] A string representation of an IPv4 address.
* @param [ipv6='::0'] A string representation of an IPv6 address.
*/
setLocalAddress(ipv4?: string, ipv6?: string): void;
setServers: typeof setServers;
}
}
declare module "dns/promises" {
export * from "node:dns/promises";
}

View File

@@ -0,0 +1,115 @@
import type { $ZodStringFormats } from "../core/checks.js";
import type * as errors from "../core/errors.js";
import * as util from "../core/util.js";
const error: () => errors.$ZodErrorMap = () => {
const Sizable: Record<string, { unit: string; verb: string }> = {
string: { unit: "字元", verb: "擁有" },
file: { unit: "位元組", verb: "擁有" },
array: { unit: "項目", verb: "擁有" },
set: { unit: "項目", verb: "擁有" },
};
function getSizing(origin: string): { unit: string; verb: string } | null {
return Sizable[origin] ?? null;
}
const FormatDictionary: {
[k in $ZodStringFormats | (string & {})]?: string;
} = {
regex: "輸入",
email: "郵件地址",
url: "URL",
emoji: "emoji",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "ISO 日期時間",
date: "ISO 日期",
time: "ISO 時間",
duration: "ISO 期間",
ipv4: "IPv4 位址",
ipv6: "IPv6 位址",
cidrv4: "IPv4 範圍",
cidrv6: "IPv6 範圍",
base64: "base64 編碼字串",
base64url: "base64url 編碼字串",
json_string: "JSON 字串",
e164: "E.164 數值",
jwt: "JWT",
template_literal: "輸入",
};
const TypeDictionary: {
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
} = {
nan: "NaN",
};
return (issue) => {
switch (issue.code) {
case "invalid_type": {
const expected = TypeDictionary[issue.expected] ?? issue.expected;
const receivedType = util.parsedType(issue.input);
const received = TypeDictionary[receivedType] ?? receivedType;
if (/^[A-Z]/.test(issue.expected)) {
return `無效的輸入值:預期為 instanceof ${issue.expected},但收到 ${received}`;
}
return `無效的輸入值:預期為 ${expected},但收到 ${received}`;
}
case "invalid_value":
if (issue.values.length === 1) return `無效的輸入值:預期為 ${util.stringifyPrimitive(issue.values[0])}`;
return `無效的選項:預期為以下其中之一 ${util.joinValues(issue.values, "|")}`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing)
return `數值過大:預期 ${issue.origin ?? "值"} 應為 ${adj}${issue.maximum.toString()} ${sizing.unit ?? "個元素"}`;
return `數值過大:預期 ${issue.origin ?? "值"} 應為 ${adj}${issue.maximum.toString()}`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
return `數值過小:預期 ${issue.origin} 應為 ${adj}${issue.minimum.toString()} ${sizing.unit}`;
}
return `數值過小:預期 ${issue.origin} 應為 ${adj}${issue.minimum.toString()}`;
}
case "invalid_format": {
const _issue = issue as errors.$ZodStringFormatIssues;
if (_issue.format === "starts_with") {
return `無效的字串:必須以 "${_issue.prefix}" 開頭`;
}
if (_issue.format === "ends_with") return `無效的字串:必須以 "${_issue.suffix}" 結尾`;
if (_issue.format === "includes") return `無效的字串:必須包含 "${_issue.includes}"`;
if (_issue.format === "regex") return `無效的字串:必須符合格式 ${_issue.pattern}`;
return `無效的 ${FormatDictionary[_issue.format] ?? issue.format}`;
}
case "not_multiple_of":
return `無效的數字:必須為 ${issue.divisor} 的倍數`;
case "unrecognized_keys":
return `無法識別的鍵值${issue.keys.length > 1 ? "們" : ""}${util.joinValues(issue.keys, "、")}`;
case "invalid_key":
return `${issue.origin} 中有無效的鍵值`;
case "invalid_union":
return "無效的輸入值";
case "invalid_element":
return `${issue.origin} 中有無效的值`;
default:
return `無效的輸入值`;
}
};
};
export default function (): { localeError: errors.$ZodErrorMap } {
return {
localeError: error(),
};
}

View File

@@ -0,0 +1,28 @@
// ../config.js accepts options via environment variables
const options = {}
if (process.env.DOTENV_CONFIG_ENCODING != null) {
options.encoding = process.env.DOTENV_CONFIG_ENCODING
}
if (process.env.DOTENV_CONFIG_PATH != null) {
options.path = process.env.DOTENV_CONFIG_PATH
}
if (process.env.DOTENV_CONFIG_QUIET != null) {
options.quiet = process.env.DOTENV_CONFIG_QUIET
}
if (process.env.DOTENV_CONFIG_DEBUG != null) {
options.debug = process.env.DOTENV_CONFIG_DEBUG
}
if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
options.override = process.env.DOTENV_CONFIG_OVERRIDE
}
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY
}
module.exports = options

View File

@@ -0,0 +1,26 @@
const URL_RE = /^[^:]+:\/\/([^:[]+|\[[^\]]+\])(:\d+)?(.*)/i;
export function makeWebsocketUrl(endpoint: string) {
const matches = endpoint.match(URL_RE);
if (matches == null) {
throw TypeError(`Failed to validate endpoint URL \`${endpoint}\``);
}
const [
_, // eslint-disable-line @typescript-eslint/no-unused-vars
hostish,
portWithColon,
rest,
] = matches;
const protocol = endpoint.startsWith('https:') ? 'wss:' : 'ws:';
const startPort =
portWithColon == null ? null : parseInt(portWithColon.slice(1), 10);
const websocketPort =
// Only shift the port by +1 as a convention for ws(s) only if given endpoint
// is explicitly specifying the endpoint port (HTTP-based RPC), assuming
// we're directly trying to connect to agave-validator's ws listening port.
// When the endpoint omits the port, we're connecting to the protocol
// default ports: http(80) or https(443) and it's assumed we're behind a reverse
// proxy which manages WebSocket upgrade and backend port redirection.
startPort == null ? '' : `:${startPort + 1}`;
return `${protocol}//${hostish}${websocketPort}${rest}`;
}

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.blake2s = exports.BLAKE2s = exports.compress = exports.G2s = exports.G1s = exports.B2S_IV = void 0;
/**
* Blake2s hash function. Focuses on 8-bit to 32-bit platforms. blake2b for 64-bit, but in JS it is slower.
* @module
* @deprecated
*/
const _blake_ts_1 = require("./_blake.js");
const _md_ts_1 = require("./_md.js");
const blake2_ts_1 = require("./blake2.js");
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.B2S_IV = _md_ts_1.SHA256_IV;
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.G1s = _blake_ts_1.G1s;
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.G2s = _blake_ts_1.G2s;
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.compress = blake2_ts_1.compress;
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.BLAKE2s = blake2_ts_1.BLAKE2s;
/** @deprecated Use import from `noble/hashes/blake2` module */
exports.blake2s = blake2_ts_1.blake2s;
//# sourceMappingURL=blake2s.js.map

View File

@@ -0,0 +1,417 @@
'use strict'
const test = require('tape')
const pino = require('../browser')
function noop () {}
test('throws if transmit object does not have send function', ({ end, throws }) => {
throws(() => {
pino({ browser: { transmit: {} } })
})
throws(() => {
pino({ browser: { transmit: { send: 'not a func' } } })
})
end()
})
test('calls send function after write', ({ end, is }) => {
let c = 0
const logger = pino({
browser: {
write: () => {
c++
},
transmit: {
send () { is(c, 1) }
}
}
})
logger.fatal({ test: 'test' })
end()
})
test('passes send function the logged level', ({ end, is }) => {
const logger = pino({
browser: {
write () {},
transmit: {
send (level) {
is(level, 'fatal')
}
}
}
})
logger.fatal({ test: 'test' })
end()
})
test('passes send function message strings in logEvent object when asObject is not set', ({ end, same, is }) => {
const logger = pino({
browser: {
write: noop,
transmit: {
send (level, { messages }) {
is(messages[0], 'test')
is(messages[1], 'another test')
}
}
}
})
logger.fatal('test', 'another test')
end()
})
test('passes send function message objects in logEvent object when asObject is not set', ({ end, same, is }) => {
const logger = pino({
browser: {
write: noop,
transmit: {
send (level, { messages }) {
same(messages[0], { test: 'test' })
is(messages[1], 'another test')
}
}
}
})
logger.fatal({ test: 'test' }, 'another test')
end()
})
test('passes send function message strings in logEvent object when asObject is set', ({ end, same, is }) => {
const logger = pino({
browser: {
asObject: true,
write: noop,
transmit: {
send (level, { messages }) {
is(messages[0], 'test')
is(messages[1], 'another test')
}
}
}
})
logger.fatal('test', 'another test')
end()
})
test('passes send function message objects in logEvent object when asObject is set', ({ end, same, is }) => {
const logger = pino({
browser: {
asObject: true,
write: noop,
transmit: {
send (level, { messages }) {
same(messages[0], { test: 'test' })
is(messages[1], 'another test')
}
}
}
})
logger.fatal({ test: 'test' }, 'another test')
end()
})
test('supplies a timestamp (ts) in logEvent object which is exactly the same as the `time` property in asObject mode', ({ end, is }) => {
let expected
const logger = pino({
browser: {
asObject: true, // implicit because `write`, but just to be explicit
write (o) {
expected = o.time
},
transmit: {
send (level, logEvent) {
is(logEvent.ts, expected)
}
}
}
})
logger.fatal('test')
end()
})
test('passes send function child bindings via logEvent object', ({ end, same, is }) => {
const logger = pino({
browser: {
write: noop,
transmit: {
send (level, logEvent) {
const messages = logEvent.messages
const bindings = logEvent.bindings
same(bindings[0], { first: 'binding' })
same(bindings[1], { second: 'binding2' })
same(messages[0], { test: 'test' })
is(messages[1], 'another test')
}
}
}
})
logger
.child({ first: 'binding' })
.child({ second: 'binding2' })
.fatal({ test: 'test' }, 'another test')
end()
})
test('passes send function level:{label, value} via logEvent object', ({ end, is }) => {
const logger = pino({
browser: {
write: noop,
transmit: {
send (level, logEvent) {
const label = logEvent.level.label
const value = logEvent.level.value
is(label, 'fatal')
is(value, 60)
}
}
}
})
logger.fatal({ test: 'test' }, 'another test')
end()
})
test('calls send function according to transmit.level', ({ end, is }) => {
let c = 0
const logger = pino({
browser: {
write: noop,
transmit: {
level: 'error',
send (level) {
c++
if (c === 1) is(level, 'error')
if (c === 2) is(level, 'fatal')
}
}
}
})
logger.warn('ignored')
logger.error('test')
logger.fatal('test')
end()
})
test('transmit.level defaults to logger level', ({ end, is }) => {
let c = 0
const logger = pino({
level: 'error',
browser: {
write: noop,
transmit: {
send (level) {
c++
if (c === 1) is(level, 'error')
if (c === 2) is(level, 'fatal')
}
}
}
})
logger.warn('ignored')
logger.error('test')
logger.fatal('test')
end()
})
test('transmit.level is effective even if lower than logger level', ({ end, is }) => {
let c = 0
const logger = pino({
level: 'error',
browser: {
write: noop,
transmit: {
level: 'info',
send (level) {
c++
if (c === 1) is(level, 'warn')
if (c === 2) is(level, 'error')
if (c === 3) is(level, 'fatal')
}
}
}
})
logger.warn('ignored')
logger.error('test')
logger.fatal('test')
end()
})
test('applies all serializers to messages and bindings (serialize:false - default)', ({ end, same, is }) => {
const logger = pino({
serializers: {
first: () => 'first',
second: () => 'second',
test: () => 'serialize it'
},
browser: {
write: noop,
transmit: {
send (level, logEvent) {
const messages = logEvent.messages
const bindings = logEvent.bindings
same(bindings[0], { first: 'first' })
same(bindings[1], { second: 'second' })
same(messages[0], { test: 'serialize it' })
is(messages[1].type, 'Error')
}
}
}
})
logger
.child({ first: 'binding' })
.child({ second: 'binding2' })
.fatal({ test: 'test' }, Error())
end()
})
test('applies all serializers to messages and bindings (serialize:true)', ({ end, same, is }) => {
const logger = pino({
serializers: {
first: () => 'first',
second: () => 'second',
test: () => 'serialize it'
},
browser: {
serialize: true,
write: noop,
transmit: {
send (level, logEvent) {
const messages = logEvent.messages
const bindings = logEvent.bindings
same(bindings[0], { first: 'first' })
same(bindings[1], { second: 'second' })
same(messages[0], { test: 'serialize it' })
is(messages[1].type, 'Error')
}
}
}
})
logger
.child({ first: 'binding' })
.child({ second: 'binding2' })
.fatal({ test: 'test' }, Error())
end()
})
test('extracts correct bindings and raw messages over multiple transmits', ({ end, same, is }) => {
let messages = null
let bindings = null
const logger = pino({
browser: {
write: noop,
transmit: {
send (level, logEvent) {
messages = logEvent.messages
bindings = logEvent.bindings
}
}
}
})
const child = logger.child({ child: true })
const grandchild = child.child({ grandchild: true })
logger.fatal({ test: 'parent:test1' })
logger.fatal({ test: 'parent:test2' })
same([], bindings)
same([{ test: 'parent:test2' }], messages)
child.fatal({ test: 'child:test1' })
child.fatal({ test: 'child:test2' })
same([{ child: true }], bindings)
same([{ test: 'child:test2' }], messages)
grandchild.fatal({ test: 'grandchild:test1' })
grandchild.fatal({ test: 'grandchild:test2' })
same([{ child: true }, { grandchild: true }], bindings)
same([{ test: 'grandchild:test2' }], messages)
end()
})
test('does not log below configured level', ({ end, is }) => {
let message = null
const logger = pino({
level: 'info',
browser: {
write (o) {
message = o.msg
},
transmit: {
send () { }
}
}
})
logger.debug('this message is silent')
is(message, null)
end()
})
test('silent level prevents logging even with transmit', ({ end, fail }) => {
const logger = pino({
level: 'silent',
browser: {
write () {
fail('no data should be logged by the write method')
},
transmit: {
send () {
fail('no data should be logged by the send method')
}
}
}
})
Object.keys(pino.levels.values).forEach((level) => {
logger[level]('ignored')
})
end()
})
test('does not call send when transmit.level is set to silent', ({ end, fail, is }) => {
let c = 0
const logger = pino({
level: 'trace',
browser: {
write () {
c++
},
transmit: {
level: 'silent',
send () {
fail('no data should be logged by the transmit method')
}
}
}
})
const levels = Object.keys(pino.levels.values)
levels.forEach((level) => {
logger[level]('message')
})
is(c, levels.length, 'write must be called exactly once per level')
end()
})

View File

@@ -0,0 +1,169 @@
/**
* Builds a composite ref key from a snapshot ID and project ID.
*/
function refKey(snapshotId, projectId) {
return `${snapshotId}:${projectId}`;
}
/**
* Client-side cache for source files keyed by (path, parseOptionsKey, contentHash).
*
* Supports multiple versions of the same file at the same path (e.g., from
* different snapshots with different file contents). Each version is identified
* by its content hash and parse options key.
*
* Entries are ref-counted by (snapshot, project) pairs. When a snapshot is
* disposed, all refs for that snapshot across all projects are released,
* and entries with no remaining references are evicted.
*
* When a new snapshot is created, unchanged cache entries from the previous
* snapshot are retained per-project. Only files within changed or removed
* projects are invalidated.
*/
export class SourceFileCache {
/** Map from path to all cached versions of that file */
cache = new Map();
/** Map from snapshotId to (projectId → Set of paths fetched through that project) */
snapshotProjectPaths = new Map();
/**
* Get a cached source file already retained for the given (snapshot, project) pair.
* This does not require a content hash or parse options key — it returns the entry
* if one exists with a matching ref. Used to skip the server request entirely when
* retainForSnapshot has already carried over the ref.
*
* A given (snapshot, project) pair always parses a file the same way, so there is
* at most one matching entry per ref.
*/
getRetained(path, snapshotId, projectId) {
const entries = this.cache.get(path);
if (!entries)
return undefined;
const key = refKey(snapshotId, projectId);
const entry = entries.find(e => e.refs.has(key));
return entry?.file;
}
/**
* Store a source file in the cache and retain it for the given (snapshot, project) pair.
* Returns the cached file — which may be an existing entry if the hash matches.
*/
set(path, file, parseOptionsKey, contentHash, snapshotId, projectId) {
let entries = this.cache.get(path);
if (!entries) {
entries = [];
this.cache.set(path, entries);
}
const ref = refKey(snapshotId, projectId);
// Check if we already have this exact version
const existing = entries.find(e => e.parseOptionsKey === parseOptionsKey && e.contentHash === contentHash);
if (existing) {
existing.refs.add(ref);
this.trackPath(snapshotId, projectId, path);
return existing.file;
}
entries.push({ file, contentHash, parseOptionsKey, refs: new Set([ref]) });
this.trackPath(snapshotId, projectId, path);
return file;
}
/**
* Retain cache entries from a previous snapshot for a new snapshot.
* For each project in the previous snapshot:
* - Removed projects: skip (don't retain any refs).
* - Changed projects: retain refs for files not listed in changedFiles/deletedFiles.
* - Unchanged projects: retain all refs.
*/
retainForSnapshot(newSnapshotId, previousSnapshotId, changes) {
const prevProjectMap = this.snapshotProjectPaths.get(previousSnapshotId);
if (!prevProjectMap)
return;
const removedProjects = new Set(changes?.removedProjects ?? []);
const changedProjects = changes?.changedProjects ?? {};
for (const [projectId, paths] of prevProjectMap) {
if (removedProjects.has(projectId))
continue;
const projectChanges = changedProjects[projectId];
let invalidPaths;
if (projectChanges) {
invalidPaths = new Set();
for (const p of projectChanges.changedFiles ?? [])
invalidPaths.add(p);
for (const p of projectChanges.deletedFiles ?? [])
invalidPaths.add(p);
}
const prevRef = refKey(previousSnapshotId, projectId);
const newRef = refKey(newSnapshotId, projectId);
for (const path of paths) {
if (invalidPaths?.has(path))
continue;
const entries = this.cache.get(path);
if (!entries)
continue;
for (const entry of entries) {
if (entry.refs.has(prevRef)) {
entry.refs.add(newRef);
this.trackPath(newSnapshotId, projectId, path);
}
}
}
}
}
/**
* Release all entries retained by the given snapshot across all projects.
* Only visits paths that the snapshot actually referenced.
* Entries with no remaining refs are evicted.
*/
releaseSnapshot(snapshotId) {
const projectMap = this.snapshotProjectPaths.get(snapshotId);
if (!projectMap)
return;
for (const [projectId, paths] of projectMap) {
const key = refKey(snapshotId, projectId);
for (const path of paths) {
const entries = this.cache.get(path);
if (!entries)
continue;
for (let i = entries.length - 1; i >= 0; i--) {
entries[i].refs.delete(key);
if (entries[i].refs.size === 0) {
entries.splice(i, 1);
}
}
if (entries.length === 0) {
this.cache.delete(path);
}
}
}
this.snapshotProjectPaths.delete(snapshotId);
}
trackPath(snapshotId, projectId, path) {
let projectMap = this.snapshotProjectPaths.get(snapshotId);
if (!projectMap) {
projectMap = new Map();
this.snapshotProjectPaths.set(snapshotId, projectMap);
}
let paths = projectMap.get(projectId);
if (!paths) {
paths = new Set();
projectMap.set(projectId, paths);
}
paths.add(path);
}
/**
* Clear all entries from the cache.
*/
clear() {
this.cache.clear();
this.snapshotProjectPaths.clear();
}
/**
* Get the number of unique paths in the cache.
*/
get size() {
return this.cache.size;
}
/**
* Check if a path is in the cache.
*/
has(path) {
return this.cache.has(path);
}
}
//# sourceMappingURL=sourceFileCache.js.map

View File

@@ -0,0 +1,82 @@
module.exports = function (obj, opts) {
if (!opts) opts = {};
if (typeof opts === 'function') opts = { cmp: opts };
var space = opts.space || '';
if (typeof space === 'number') space = Array(space+1).join(' ');
var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
var replacer = opts.replacer || function(key, value) { return value; };
var cmp = opts.cmp && (function (f) {
return function (node) {
return function (a, b) {
var aobj = { key: a, value: node[a] };
var bobj = { key: b, value: node[b] };
return f(aobj, bobj);
};
};
})(opts.cmp);
var seen = [];
return (function stringify (parent, key, node, level) {
var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
var colonSeparator = space ? ': ' : ':';
if (node && node.toJSON && typeof node.toJSON === 'function') {
node = node.toJSON();
}
node = replacer.call(parent, key, node);
if (node === undefined) {
return;
}
if (typeof node !== 'object' || node === null) {
return JSON.stringify(node);
}
if (isArray(node)) {
var out = [];
for (var i = 0; i < node.length; i++) {
var item = stringify(node, i, node[i], level+1) || JSON.stringify(null);
out.push(indent + space + item);
}
return '[' + out.join(',') + indent + ']';
}
else {
if (seen.indexOf(node) !== -1) {
if (cycles) return JSON.stringify('__cycle__');
throw new TypeError('Converting circular structure to JSON');
}
else seen.push(node);
var keys = objectKeys(node).sort(cmp && cmp(node));
var out = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = stringify(node, key, node[key], level+1);
if(!value) continue;
var keyValue = JSON.stringify(key)
+ colonSeparator
+ value;
;
out.push(indent + space + keyValue);
}
seen.splice(seen.indexOf(node), 1);
return '{' + out.join(',') + indent + '}';
}
})({ '': obj }, '', obj, 0);
};
var isArray = Array.isArray || function (x) {
return {}.toString.call(x) === '[object Array]';
};
var objectKeys = Object.keys || function (obj) {
var has = Object.prototype.hasOwnProperty || function () { return true };
var keys = [];
for (var key in obj) {
if (has.call(obj, key)) keys.push(key);
}
return keys;
};

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Matteo Collina
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,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'prefer-ts-expect-error',
meta: {
type: 'problem',
deprecated: {
deprecatedSince: '7.11.0',
replacedBy: [
{
rule: {
name: '@typescript-eslint/ban-ts-comment',
url: 'https://typescript-eslint.io/rules/ban-ts-comment',
},
},
],
url: 'https://github.com/typescript-eslint/typescript-eslint/pull/9081',
},
docs: {
description: 'Enforce using `@ts-expect-error` over `@ts-ignore`',
},
fixable: 'code',
messages: {
preferExpectErrorComment: 'Use "@ts-expect-error" to ensure an error is actually being suppressed.',
},
replacedBy: ['@typescript-eslint/ban-ts-comment'],
schema: [],
},
defaultOptions: [],
create(context) {
const tsIgnoreRegExpSingleLine = /^\s*\/?\s*@ts-ignore/;
const tsIgnoreRegExpMultiLine = /^\s*(?:\/|\*)*\s*@ts-ignore/;
function isLineComment(comment) {
return comment.type === utils_1.AST_TOKEN_TYPES.Line;
}
function getLastCommentLine(comment) {
if (isLineComment(comment)) {
return comment.value;
}
// For multiline comments - we look at only the last line.
const commentlines = comment.value.split(utils_1.ASTUtils.LINEBREAK_MATCHER);
return commentlines[commentlines.length - 1];
}
function isValidTsIgnorePresent(comment) {
const line = getLastCommentLine(comment);
return isLineComment(comment)
? tsIgnoreRegExpSingleLine.test(line)
: tsIgnoreRegExpMultiLine.test(line);
}
return {
Program() {
const comments = context.sourceCode.getAllComments();
comments.forEach(comment => {
if (isValidTsIgnorePresent(comment)) {
const lineCommentRuleFixer = (fixer) => fixer.replaceText(comment, `//${comment.value.replace('@ts-ignore', '@ts-expect-error')}`);
const blockCommentRuleFixer = (fixer) => fixer.replaceText(comment, `/*${comment.value.replace('@ts-ignore', '@ts-expect-error')}*/`);
context.report({
node: comment,
messageId: 'preferExpectErrorComment',
fix: isLineComment(comment)
? lineCommentRuleFixer
: blockCommentRuleFixer,
});
}
});
},
};
},
});

View File

@@ -0,0 +1 @@
{"version":3,"file":"astnav.d.ts","sourceRoot":"","sources":["../../src/ast/astnav.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,IAAI,EAEJ,UAAU,EACb,MAAM,UAAU,CAAC;AAclB,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEtF;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE/E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAiEzG;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE7F;AAkMD,gBAAgB;AAChB,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAapG"}

View File

@@ -0,0 +1,73 @@
{
"name": "obug",
"type": "module",
"version": "2.1.4",
"description": "A lightweight JavaScript debugging utility, forked from debug, featuring TypeScript and ESM support.",
"author": "Kevin Deng <sxzz@sxzz.moe>",
"license": "MIT",
"funding": [
"https://github.com/sponsors/sxzz",
"https://opencollective.com/debug"
],
"homepage": "https://github.com/sxzz/obug#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/sxzz/obug.git"
},
"bugs": {
"url": "https://github.com/sxzz/obug/issues"
},
"sideEffects": false,
"exports": {
".": {
"browser": "./dist/browser.js",
"default": "./dist/node.js"
},
"./package.json": "./package.json"
},
"main": "./dist/node.js",
"module": "./dist/node.js",
"unpkg": "./dist/browser.min.js",
"jsdelivr": "./dist/browser.min.js",
"types": "./dist/browser.d.ts",
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=12.20.0"
},
"devDependencies": {
"@sxzz/eslint-config": "^8.2.1",
"@sxzz/prettier-config": "^2.3.1",
"@types/debug": "^4.1.13",
"@types/node": "^26.1.1",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"@vitest/browser-playwright": "^4.1.10",
"@vitest/coverage-v8": "^4.1.10",
"bumpp": "^11.1.0",
"debug": "^4.4.3",
"eslint": "^10.7.0",
"playwright": "^1.61.1",
"prettier": "^3.9.5",
"tsdown": "^0.22.9",
"typescript": "^6.0.3",
"vite": "^8.1.5",
"vitest": "^4.1.10"
},
"prettier": "@sxzz/prettier-config",
"scripts": {
"lint": "eslint --cache .",
"lint:fix": "pnpm run lint --fix",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"test:coverage": "vitest --project node --coverage",
"play": "vite playground",
"typecheck": "tsgo --noEmit",
"format": "prettier --cache --write .",
"release": "bumpp"
}
}

View File

@@ -0,0 +1,6 @@
export var LanguageVariant;
(function (LanguageVariant) {
LanguageVariant[LanguageVariant["Standard"] = 0] = "Standard";
LanguageVariant[LanguageVariant["JSX"] = 1] = "JSX";
})(LanguageVariant || (LanguageVariant = {}));
//# sourceMappingURL=languageVariant.enum.js.map

View File

@@ -0,0 +1,360 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.notImplemented = exports.bitMask = exports.utf8ToBytes = exports.randomBytes = exports.isBytes = exports.hexToBytes = exports.concatBytes = exports.bytesToUtf8 = exports.bytesToHex = exports.anumber = exports.abytes = void 0;
exports.abool = abool;
exports._abool2 = _abool2;
exports._abytes2 = _abytes2;
exports.numberToHexUnpadded = numberToHexUnpadded;
exports.hexToNumber = hexToNumber;
exports.bytesToNumberBE = bytesToNumberBE;
exports.bytesToNumberLE = bytesToNumberLE;
exports.numberToBytesBE = numberToBytesBE;
exports.numberToBytesLE = numberToBytesLE;
exports.numberToVarBytesBE = numberToVarBytesBE;
exports.ensureBytes = ensureBytes;
exports.equalBytes = equalBytes;
exports.copyBytes = copyBytes;
exports.asciiToBytes = asciiToBytes;
exports.inRange = inRange;
exports.aInRange = aInRange;
exports.bitLen = bitLen;
exports.bitGet = bitGet;
exports.bitSet = bitSet;
exports.createHmacDrbg = createHmacDrbg;
exports.validateObject = validateObject;
exports.isHash = isHash;
exports._validateObject = _validateObject;
exports.memoized = memoized;
/**
* Hex, bytes and number utilities.
* @module
*/
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const utils_js_1 = require("@noble/hashes/utils.js");
var utils_js_2 = require("@noble/hashes/utils.js");
Object.defineProperty(exports, "abytes", { enumerable: true, get: function () { return utils_js_2.abytes; } });
Object.defineProperty(exports, "anumber", { enumerable: true, get: function () { return utils_js_2.anumber; } });
Object.defineProperty(exports, "bytesToHex", { enumerable: true, get: function () { return utils_js_2.bytesToHex; } });
Object.defineProperty(exports, "bytesToUtf8", { enumerable: true, get: function () { return utils_js_2.bytesToUtf8; } });
Object.defineProperty(exports, "concatBytes", { enumerable: true, get: function () { return utils_js_2.concatBytes; } });
Object.defineProperty(exports, "hexToBytes", { enumerable: true, get: function () { return utils_js_2.hexToBytes; } });
Object.defineProperty(exports, "isBytes", { enumerable: true, get: function () { return utils_js_2.isBytes; } });
Object.defineProperty(exports, "randomBytes", { enumerable: true, get: function () { return utils_js_2.randomBytes; } });
Object.defineProperty(exports, "utf8ToBytes", { enumerable: true, get: function () { return utils_js_2.utf8ToBytes; } });
const _0n = /* @__PURE__ */ BigInt(0);
const _1n = /* @__PURE__ */ BigInt(1);
function abool(title, value) {
if (typeof value !== 'boolean')
throw new Error(title + ' boolean expected, got ' + value);
}
// tmp name until v2
function _abool2(value, title = '') {
if (typeof value !== 'boolean') {
const prefix = title && `"${title}"`;
throw new Error(prefix + 'expected boolean, got type=' + typeof value);
}
return value;
}
// tmp name until v2
/** Asserts something is Uint8Array. */
function _abytes2(value, length, title = '') {
const bytes = (0, utils_js_1.isBytes)(value);
const len = value?.length;
const needsLen = length !== undefined;
if (!bytes || (needsLen && len !== length)) {
const prefix = title && `"${title}" `;
const ofLen = needsLen ? ` of length ${length}` : '';
const got = bytes ? `length=${len}` : `type=${typeof value}`;
throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
}
return value;
}
// Used in weierstrass, der
function numberToHexUnpadded(num) {
const hex = num.toString(16);
return hex.length & 1 ? '0' + hex : hex;
}
function hexToNumber(hex) {
if (typeof hex !== 'string')
throw new Error('hex string expected, got ' + typeof hex);
return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian
}
// BE: Big Endian, LE: Little Endian
function bytesToNumberBE(bytes) {
return hexToNumber((0, utils_js_1.bytesToHex)(bytes));
}
function bytesToNumberLE(bytes) {
(0, utils_js_1.abytes)(bytes);
return hexToNumber((0, utils_js_1.bytesToHex)(Uint8Array.from(bytes).reverse()));
}
function numberToBytesBE(n, len) {
return (0, utils_js_1.hexToBytes)(n.toString(16).padStart(len * 2, '0'));
}
function numberToBytesLE(n, len) {
return numberToBytesBE(n, len).reverse();
}
// Unpadded, rarely used
function numberToVarBytesBE(n) {
return (0, utils_js_1.hexToBytes)(numberToHexUnpadded(n));
}
/**
* Takes hex string or Uint8Array, converts to Uint8Array.
* Validates output length.
* Will throw error for other types.
* @param title descriptive title for an error e.g. 'secret key'
* @param hex hex string or Uint8Array
* @param expectedLength optional, will compare to result array's length
* @returns
*/
function ensureBytes(title, hex, expectedLength) {
let res;
if (typeof hex === 'string') {
try {
res = (0, utils_js_1.hexToBytes)(hex);
}
catch (e) {
throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
}
}
else if ((0, utils_js_1.isBytes)(hex)) {
// Uint8Array.from() instead of hash.slice() because node.js Buffer
// is instance of Uint8Array, and its slice() creates **mutable** copy
res = Uint8Array.from(hex);
}
else {
throw new Error(title + ' must be hex string or Uint8Array');
}
const len = res.length;
if (typeof expectedLength === 'number' && len !== expectedLength)
throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
return res;
}
// Compares 2 u8a-s in kinda constant time
function equalBytes(a, b) {
if (a.length !== b.length)
return false;
let diff = 0;
for (let i = 0; i < a.length; i++)
diff |= a[i] ^ b[i];
return diff === 0;
}
/**
* Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
* and Buffer#slice creates mutable copy. Never use Buffers!
*/
function copyBytes(bytes) {
return Uint8Array.from(bytes);
}
/**
* Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
* Should be safe to use for things expected to be ASCII.
* Returns exact same result as utf8ToBytes for ASCII or throws.
*/
function asciiToBytes(ascii) {
return Uint8Array.from(ascii, (c, i) => {
const charCode = c.charCodeAt(0);
if (c.length !== 1 || charCode > 127) {
throw new Error(`string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`);
}
return charCode;
});
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
// export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
/**
* Converts bytes to string using UTF8 encoding.
* @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
*/
// export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
// Is positive bigint
const isPosBig = (n) => typeof n === 'bigint' && _0n <= n;
function inRange(n, min, max) {
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
}
/**
* Asserts min <= n < max. NOTE: It's < max and not <= max.
* @example
* aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n)
*/
function aInRange(title, n, min, max) {
// Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)?
// consider P=256n, min=0n, max=P
// - a for min=0 would require -1: `inRange('x', x, -1n, P)`
// - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
// - our way is the cleanest: `inRange('x', x, 0n, P)
if (!inRange(n, min, max))
throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
}
// Bit operations
/**
* Calculates amount of bits in a bigint.
* Same as `n.toString(2).length`
* TODO: merge with nLength in modular
*/
function bitLen(n) {
let len;
for (len = 0; n > _0n; n >>= _1n, len += 1)
;
return len;
}
/**
* Gets single bit at position.
* NOTE: first bit position is 0 (same as arrays)
* Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
*/
function bitGet(n, pos) {
return (n >> BigInt(pos)) & _1n;
}
/**
* Sets single bit at position.
*/
function bitSet(n, pos, value) {
return n | ((value ? _1n : _0n) << BigInt(pos));
}
/**
* Calculate mask for N bits. Not using ** operator with bigints because of old engines.
* Same as BigInt(`0b${Array(i).fill('1').join('')}`)
*/
const bitMask = (n) => (_1n << BigInt(n)) - _1n;
exports.bitMask = bitMask;
/**
* Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
* @returns function that will call DRBG until 2nd arg returns something meaningful
* @example
* const drbg = createHmacDRBG<Key>(32, 32, hmac);
* drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
*/
function createHmacDrbg(hashLen, qByteLen, hmacFn) {
if (typeof hashLen !== 'number' || hashLen < 2)
throw new Error('hashLen must be a number');
if (typeof qByteLen !== 'number' || qByteLen < 2)
throw new Error('qByteLen must be a number');
if (typeof hmacFn !== 'function')
throw new Error('hmacFn must be a function');
// Step B, Step C: set hashLen to 8*ceil(hlen/8)
const u8n = (len) => new Uint8Array(len); // creates Uint8Array
const u8of = (byte) => Uint8Array.of(byte); // another shortcut
let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
let i = 0; // Iterations counter, will throw when over 1000
const reset = () => {
v.fill(1);
k.fill(0);
i = 0;
};
const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
const reseed = (seed = u8n(0)) => {
// HMAC-DRBG reseed() function. Steps D-G
k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
v = h(); // v = hmac(k || v)
if (seed.length === 0)
return;
k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
v = h(); // v = hmac(k || v)
};
const gen = () => {
// HMAC-DRBG generate() function
if (i++ >= 1000)
throw new Error('drbg: tried 1000 values');
let len = 0;
const out = [];
while (len < qByteLen) {
v = h();
const sl = v.slice();
out.push(sl);
len += v.length;
}
return (0, utils_js_1.concatBytes)(...out);
};
const genUntil = (seed, pred) => {
reset();
reseed(seed); // Steps D-G
let res = undefined; // Step H: grind until k is in [1..n-1]
while (!(res = pred(gen())))
reseed();
reset();
return res;
};
return genUntil;
}
// Validating curves and fields
const validatorFns = {
bigint: (val) => typeof val === 'bigint',
function: (val) => typeof val === 'function',
boolean: (val) => typeof val === 'boolean',
string: (val) => typeof val === 'string',
stringOrUint8Array: (val) => typeof val === 'string' || (0, utils_js_1.isBytes)(val),
isSafeInteger: (val) => Number.isSafeInteger(val),
array: (val) => Array.isArray(val),
field: (val, object) => object.Fp.isValid(val),
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
};
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
function validateObject(object, validators, optValidators = {}) {
const checkField = (fieldName, type, isOptional) => {
const checkVal = validatorFns[type];
if (typeof checkVal !== 'function')
throw new Error('invalid validator function');
const val = object[fieldName];
if (isOptional && val === undefined)
return;
if (!checkVal(val, object)) {
throw new Error('param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val);
}
};
for (const [fieldName, type] of Object.entries(validators))
checkField(fieldName, type, false);
for (const [fieldName, type] of Object.entries(optValidators))
checkField(fieldName, type, true);
return object;
}
// validate type tests
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
// // Should fail type-check
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
function isHash(val) {
return typeof val === 'function' && Number.isSafeInteger(val.outputLen);
}
function _validateObject(object, fields, optFields = {}) {
if (!object || typeof object !== 'object')
throw new Error('expected valid options object');
function checkField(fieldName, expectedType, isOpt) {
const val = object[fieldName];
if (isOpt && val === undefined)
return;
const current = typeof val;
if (current !== expectedType || val === null)
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
}
Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
}
/**
* throws not implemented error
*/
const notImplemented = () => {
throw new Error('not implemented');
};
exports.notImplemented = notImplemented;
/**
* Memoizes (caches) computation result.
* Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
*/
function memoized(fn) {
const map = new WeakMap();
return (arg, ...args) => {
const val = map.get(arg);
if (val !== undefined)
return val;
const computed = fn(arg, ...args);
map.set(arg, computed);
return computed;
};
}
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1,87 @@
[![npm][npm-image]][npm-url]
[![npm-downloads][npm-downloads-image]][npm-url]
<br />
[![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]
[code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
[code-style-prettier-url]: https://github.com/prettier/prettier
[npm-downloads-image]: https://img.shields.io/npm/dm/@solana/errors?style=flat
[npm-image]: https://img.shields.io/npm/v/@solana/errors?style=flat
[npm-url]: https://www.npmjs.com/package/@solana/errors
# @solana/errors
This package brings together every error message across all Solana JavaScript modules.
## Reading error messages
### In development mode
When your bundler sets the constant `__DEV__` to `true`, every error message will be included in the bundle. As such, you will be able to read them in plain language wherever they appear.
> [!WARNING]
> The size of your JavaScript bundle will increase significantly with the inclusion of every error message in development mode. Be sure to build your bundle with `__DEV__` set to `false` when you go to production.
### In production mode
When your bundler sets the constant `__DEV__` to `false`, error messages will be stripped from the bundle to save space. Only the error code will appear when an error is encountered. Follow the instructions in the error message to convert the error code back to the human-readable error message.
For instance, to recover the error text for the error with code `123`:
```shell
npx @solana/errors decode -- 123
```
## Adding a new error
1. Add a new exported error code constant to `src/codes.ts`.
2. Add that new constant to the `SolanaErrorCode` union in `src/codes.ts`.
3. If you would like the new error to encapsulate context about the error itself (eg. the public keys for which a transaction is missing signatures) define the shape of that context in `src/context.ts`.
4. Add the error's message to `src/messages.ts`. Any context values that you defined above will be interpolated into the message wherever you write `$key`, where `key` is the index of a value in the context (eg. ``'Missing a signature for account `$address`'``).
5. Publish a new version of `@solana/errors`.
6. Bump the version of `@solana/errors` in the package from which the error is thrown.
## Removing an error message
- Don't remove errors.
- Don't change the meaning of an error message.
- Don't change or reorder error codes.
- Don't change or remove members of an error's context.
When an older client throws an error, we want to make sure that they can always decode the error. If you make any of the changes above, old clients will, by definition, not have received your changes. This could make the errors that they throw impossible to decode going forward.
## Catching errors
When you catch a `SolanaError` and assert its error code using `isSolanaError()`, TypeScript will refine the error's context to the type associated with that error code. You can use that context to render useful error messages, or to make context-aware decisions that help your application to recover from the error.
```ts
import {
SOLANA_ERROR__TRANSACTION__MISSING_SIGNATURE,
SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING,
isSolanaError,
} from '@solana/errors';
import { assertIsFullySignedTransaction, getSignatureFromTransaction } from '@solana/transactions';
try {
const transactionSignature = getSignatureFromTransaction(tx);
assertIsFullySignedTransaction(tx);
/* ... */
} catch (e) {
if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING)) {
displayError(
"We can't send this transaction without signatures for these addresses:\n- %s",
// The type of the `context` object is now refined to contain `addresses`.
e.context.addresses.join('\n- '),
);
return;
} else if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING)) {
if (!tx.feePayer) {
displayError('Choose a fee payer for this transaction before sending it');
} else {
displayError('The fee payer still needs to sign for this transaction');
}
return;
}
throw e;
}
```

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.crypto = void 0;
exports.crypto = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
//# sourceMappingURL=crypto.js.map

View File

@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.range = exports.balanced = void 0;
const balanced = (a, b, str) => {
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
const r = ma !== null && mb != null && (0, exports.range)(ma, mb, str);
return (r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + ma.length, r[1]),
post: str.slice(r[1] + mb.length),
});
};
exports.balanced = balanced;
const maybeMatch = (reg, str) => {
const m = str.match(reg);
return m ? m[0] : null;
};
const range = (a, b, str) => {
let begs, beg, left, right = undefined, result;
let ai = str.indexOf(a);
let bi = str.indexOf(b, ai + 1);
let i = ai;
if (ai >= 0 && bi > 0) {
if (a === b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i === ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
}
else if (begs.length === 1) {
const r = begs.pop();
if (r !== undefined)
result = [r, bi];
}
else {
beg = begs.pop();
if (beg !== undefined && beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length && right !== undefined) {
result = [left, right];
}
}
return result;
};
exports.range = range;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"_blake.d.ts","sourceRoot":"","sources":["../src/_blake.ts"],"names":[],"mappings":"AAMA;;;GAGG;AAEH,eAAO,MAAM,MAAM,EAAE,UAkBnB,CAAC;AAGH,MAAM,MAAM,IAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;CAAE,CAAC;AAGnE,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAM/E;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAM/E"}

View File

@@ -0,0 +1,78 @@
/**
* @fileoverview Rule to disallow a duplicate case label.
* @author Dieter Oberkofler
* @author Burak Yigit Kaya
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "problem",
docs: {
description: "Disallow duplicate case labels",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-duplicate-case",
},
schema: [],
messages: {
unexpected: "Duplicate case label.",
},
},
create(context) {
const sourceCode = context.sourceCode;
/**
* Determines whether the two given nodes are considered to be equal.
* @param {ASTNode} a First node.
* @param {ASTNode} b Second node.
* @returns {boolean} `true` if the nodes are considered to be equal.
*/
function equal(a, b) {
if (a.type !== b.type) {
return false;
}
return astUtils.equalTokens(a, b, sourceCode);
}
return {
SwitchStatement(node) {
const previousTests = [];
for (const switchCase of node.cases) {
if (switchCase.test) {
const test = switchCase.test;
if (
previousTests.some(previousTest =>
equal(previousTest, test),
)
) {
context.report({
node: switchCase,
messageId: "unexpected",
});
} else {
previousTests.push(test);
}
}
}
},
};
},
};