refactor: move brother_node development artifact to dev/test-nodes subdirectory

Development Artifact Cleanup:
 BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location
- dev/test-nodes/brother_node/: Moved from root directory for better organization
- Contains development configuration, test logs, and test chain data
- No impact on production systems - purely development/testing artifact

 DEVELOPMENT ARTIFACTS IDENTIFIED:
- Chain ID: aitbc-brother-chain (test/development chain)
- Ports: 8010 (P2P) and 8011 (RPC) - different from production
- Environment: .env file with test configuration
- Logs: rpc.log and node.log from development testing session (March 15, 2026)

 ROOT DIRECTORY CLEANUP: Removed development clutter from production directory
- brother_node/ moved to dev/test-nodes/brother_node/
- Root directory now contains only production-ready components
- Development artifacts properly organized in dev/ subdirectory

DIRECTORY STRUCTURE IMPROVEMENT:
📁 dev/test-nodes/: Development and testing node configurations
🏗️ Root Directory: Clean production structure with only essential components
🧪 Development Isolation: Test environments separated from production

BENEFITS:
 Clean Production Directory: No development artifacts in root
 Better Organization: Development nodes grouped in dev/ subdirectory
 Clear Separation: Production vs development environments clearly distinguished
 Maintainability: Easier to identify and manage development components

RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
This commit is contained in:
2026-03-30 17:09:06 +02:00
parent bf730dcb4a
commit 816e258d4c
11734 changed files with 2001707 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# @nomicfoundation/hardhat-utils
## 4.0.0
### Major Changes
- 87623db: Introduce new inter-process mutex implementation ([7942](https://github.com/NomicFoundation/hardhat/pull/7942)).
- 726ff37: Update the `--coverage` table output to match the style used by `--gas-stats`. Thanks @jose-blockchain! ([#7733](https://github.com/NomicFoundation/hardhat/issues/7733))
### Patch Changes
- 87623db: Fix two issues in the `download` function ([7942](https://github.com/NomicFoundation/hardhat/pull/7942)).
## 3.0.6
### Patch Changes
- 2bc18b2: Bumped `viem` version across all packages [7861](https://github.com/NomicFoundation/hardhat/pull/7861).
## 3.0.5
### Patch Changes
- d45234d: Fixed Etherscan verification failures by removing hardcoded v1 API URLs from chain descriptors ([#7623](https://github.com/NomicFoundation/hardhat/issues/7623)). Also enhanced config resolution to support partial overrides in block explorer configurations for future extensibility.
## 3.0.4
### Patch Changes
- d1969e7: Added support for showing gas statistics after running nodejs tests ([#7472](https://github.com/NomicFoundation/hardhat/issues/7428)).
## 3.0.3
### Patch Changes
- d821a0a: Fix npm artifact cleanup on windows ([#7459](https://github.com/NomicFoundation/hardhat/issues/7459))
- b13620a: Add compilation progress spinner to show build progress ([#7460](https://github.com/NomicFoundation/hardhat/pull/7460))
## 3.0.2
### Patch Changes
- 8c1cb1e: Fixed peer dependencies for Hardhat so `rpc` utils can be loaded ([#7415](https://github.com/NomicFoundation/hardhat/issues/7415))
## 3.0.1
### Patch Changes
- 49cc9ba: Load resolved global options into environment variables during tests ([#7305](https://github.com/NomicFoundation/hardhat/pull/7305))
- 8d3b16c: Support for custom compilers ([#7130](https://github.com/NomicFoundation/hardhat/issues/7130))
- a475780: Added automatic proxy detection for `hardhat-verify` and fixed case-insensitive proxy environment variables for network requests ([#7407](https://github.com/NomicFoundation/hardhat/pull/7407))
## 3.0.0
### Major Changes
- 29cc141: First release of Hardhat 3!

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2024 Nomic Foundation
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,5 @@
# hardhat-utils
> ⚠️ This package is an internal Hardhat component and it's not meant to be used directly.
This package contains utilities used by Hardhat 3 and its plugins.

View File

@@ -0,0 +1,32 @@
/**
* Returns the minimum of two bigints.
*
* @param x The first number to compare.
* @param y The second number to compare.
* @returns The smaller of the two numbers.
*/
export declare function min(x: bigint, y: bigint): bigint;
/**
* Returns the maximum of two bigints.
*
* @param x The first number to compare.
* @param y The second number to compare.
* @returns The larger of the two numbers.
*/
export declare function max(x: bigint, y: bigint): bigint;
/**
* Converts a value to a bigint.
*
* This function supports several types of input:
* - `number`: Must be an integer and a safe integer. If it's not, an error is thrown.
* - `bigint`: Returned as is.
* - `string`: Converted to a bigint using the BigInt constructor.
*
* If the input is of an unsupported type, an error is thrown.
*
* @param value The value to convert to a bigint.
* @returns The input value converted to a bigint.
* @throws InvalidParameterError If the input value cannot be converted to a bigint.
*/
export declare function toBigInt(value: number | string | bigint): bigint;
//# sourceMappingURL=bigint.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bigint.d.ts","sourceRoot":"","sources":["../../src/bigint.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAsBhE"}

View File

@@ -0,0 +1,55 @@
import { InvalidParameterError } from "./common-errors.js";
import { unreachable } from "./error.js";
/**
* Returns the minimum of two bigints.
*
* @param x The first number to compare.
* @param y The second number to compare.
* @returns The smaller of the two numbers.
*/
export function min(x, y) {
return x < y ? x : y;
}
/**
* Returns the maximum of two bigints.
*
* @param x The first number to compare.
* @param y The second number to compare.
* @returns The larger of the two numbers.
*/
export function max(x, y) {
return x > y ? x : y;
}
/**
* Converts a value to a bigint.
*
* This function supports several types of input:
* - `number`: Must be an integer and a safe integer. If it's not, an error is thrown.
* - `bigint`: Returned as is.
* - `string`: Converted to a bigint using the BigInt constructor.
*
* If the input is of an unsupported type, an error is thrown.
*
* @param value The value to convert to a bigint.
* @returns The input value converted to a bigint.
* @throws InvalidParameterError If the input value cannot be converted to a bigint.
*/
export function toBigInt(value) {
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- The other types will throw an error
switch (typeof value) {
case "number":
if (!Number.isInteger(value)) {
throw new InvalidParameterError(`${value} is not an integer`);
}
if (!Number.isSafeInteger(value)) {
throw new InvalidParameterError(`Integer ${value} is unsafe. Consider using ${value}n instead. For more details, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger`);
}
// `break;` intentionally omitted. fallthrough desired.
case "string":
case "bigint":
return BigInt(value);
default:
unreachable(value, new InvalidParameterError(`Unsupported type: ${typeof value}`));
}
}
//# sourceMappingURL=bigint.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bigint.js","sourceRoot":"","sources":["../../src/bigint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS;IACtC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,QAAQ,CAAC,KAA+B;IACtD,iHAAiH;IACjH,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,qBAAqB,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;YAChE,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,qBAAqB,CAC7B,WAAW,KAAK,8BAA8B,KAAK,wIAAwI,CAC5L,CAAC;YACJ,CAAC;QACH,uDAAuD;QACvD,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB;YACE,WAAW,CACT,KAAK,EACL,IAAI,qBAAqB,CAAC,qBAAqB,OAAO,KAAK,EAAE,CAAC,CAC/D,CAAC;IACN,CAAC;AACH,CAAC"}

View File

@@ -0,0 +1,27 @@
import type { PrefixedHexString } from "./hex.js";
import type { Artifact, LibraryAddresses, LibraryLink } from "./internal/bytecode.js";
/**
* Resolves the linked bytecode for a given contract artifact by substituting
* the required library placeholders within the bytecode with the provided
* library addresses.
*
* @param artifact The contract artifact containing the bytecode and link references.
* @param providedLibraries An object containing library names as keys and their addresses as values.
* @returns The linked bytecode with all required libraries correctly linked.
* @throws InvalidLibraryAddressError If any provided library address is invalid.
* @throws AmbiguousLibraryNameError If any provided library name matches multiple needed libraries.
* @throws UnnecessaryLibraryError If any provided library name is not needed by the contract.
* @throws OverlappingLibrariesError If any library is provided more than once.
* @throws MissingLibrariesError If any needed library address is missing.
*/
export declare function resolveLinkedBytecode(artifact: Artifact, providedLibraries: LibraryAddresses): PrefixedHexString;
/**
* Links the bytecode of a contract artifact with the provided library addresses.
* This function does not perform any validation on the provided libraries.
*
* @param artifact The contract artifact containing the bytecode and link references.
* @param libraries An array of LibraryLink objects representing the libraries to be linked.
* @returns The linked bytecode with all provided libraries correctly linked.
*/
export declare function linkBytecode(artifact: Artifact, libraries: LibraryLink[]): PrefixedHexString;
//# sourceMappingURL=bytecode.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.d.ts","sourceRoot":"","sources":["../../src/bytecode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAUhC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,EAAE,gBAAgB,GAClC,iBAAiB,CA0BnB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,WAAW,EAAE,GACvB,iBAAiB,CAkBnB"}

View File

@@ -0,0 +1,60 @@
import { getPrefixedHexString, getUnprefixedHexString } from "./hex.js";
import { checkAmbiguousOrUnnecessaryLinks, checkMissingLibraryAddresses, checkOverlappingLibraryNames, checkProvidedLibraryAddresses, } from "./internal/bytecode.js";
/**
* Resolves the linked bytecode for a given contract artifact by substituting
* the required library placeholders within the bytecode with the provided
* library addresses.
*
* @param artifact The contract artifact containing the bytecode and link references.
* @param providedLibraries An object containing library names as keys and their addresses as values.
* @returns The linked bytecode with all required libraries correctly linked.
* @throws InvalidLibraryAddressError If any provided library address is invalid.
* @throws AmbiguousLibraryNameError If any provided library name matches multiple needed libraries.
* @throws UnnecessaryLibraryError If any provided library name is not needed by the contract.
* @throws OverlappingLibrariesError If any library is provided more than once.
* @throws MissingLibrariesError If any needed library address is missing.
*/
export function resolveLinkedBytecode(artifact, providedLibraries) {
checkProvidedLibraryAddresses(providedLibraries);
const neededLibraries = [];
for (const [sourceName, sourceLibraries] of Object.entries(artifact.linkReferences)) {
for (const libraryName of Object.keys(sourceLibraries)) {
const libraryFqn = `${sourceName}:${libraryName}`;
const address = providedLibraries[libraryFqn] ?? providedLibraries[libraryName];
neededLibraries.push({
sourceName,
libraryName,
libraryFqn,
address,
});
}
}
checkAmbiguousOrUnnecessaryLinks(providedLibraries, neededLibraries);
checkOverlappingLibraryNames(providedLibraries, neededLibraries);
checkMissingLibraryAddresses(neededLibraries);
return linkBytecode(artifact, neededLibraries);
}
/**
* Links the bytecode of a contract artifact with the provided library addresses.
* This function does not perform any validation on the provided libraries.
*
* @param artifact The contract artifact containing the bytecode and link references.
* @param libraries An array of LibraryLink objects representing the libraries to be linked.
* @returns The linked bytecode with all provided libraries correctly linked.
*/
export function linkBytecode(artifact, libraries) {
const { bytecode, linkReferences } = artifact;
let linkedBytecode = bytecode;
for (const { sourceName, libraryName, address } of libraries) {
const contractLinkReferences = linkReferences[sourceName]?.[libraryName] ?? [];
const unprefixedAddress = getUnprefixedHexString(address);
for (const { start, length } of contractLinkReferences) {
linkedBytecode =
linkedBytecode.substring(0, 2 + start * 2) +
unprefixedAddress +
linkedBytecode.substring(2 + (start + length) * 2);
}
}
return getPrefixedHexString(linkedBytecode);
}
//# sourceMappingURL=bytecode.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.js","sourceRoot":"","sources":["../../src/bytecode.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,gCAAgC,EAChC,4BAA4B,EAC5B,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkB,EAClB,iBAAmC;IAEnC,6BAA6B,CAAC,iBAAiB,CAAC,CAAC;IAEjD,MAAM,eAAe,GAAkB,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACxD,QAAQ,CAAC,cAAc,CACxB,EAAE,CAAC;QACF,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YACvD,MAAM,UAAU,GAAG,GAAG,UAAU,IAAI,WAAW,EAAE,CAAC;YAClD,MAAM,OAAO,GACX,iBAAiB,CAAC,UAAU,CAAC,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAElE,eAAe,CAAC,IAAI,CAAC;gBACnB,UAAU;gBACV,WAAW;gBACX,UAAU;gBACV,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,gCAAgC,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IACrE,4BAA4B,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IACjE,4BAA4B,CAAC,eAAe,CAAC,CAAC;IAE9C,OAAO,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAkB,EAClB,SAAwB;IAExB,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;IAC9C,IAAI,cAAc,GAAG,QAAQ,CAAC;IAE9B,KAAK,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;QAC7D,MAAM,sBAAsB,GAC1B,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAE1D,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,sBAAsB,EAAE,CAAC;YACvD,cAAc;gBACZ,cAAc,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;oBAC1C,iBAAiB;oBACjB,cAAc,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,OAAO,oBAAoB,CAAC,cAAc,CAAC,CAAC;AAC9C,CAAC"}

View File

@@ -0,0 +1,34 @@
/**
* Checks if a value is an instance of Uint8Array.
*
* @param value The value to check.
* @returns True if the value is a Uint8Array, false otherwise.
*/
export declare function isBytes(value: unknown): value is Uint8Array;
/**
* Pads a Uint8Array with zeros on the left to a specified length, or truncates
* it from the left if it's too long.
*
* @param bytes The Uint8Array to pad or truncate.
* @param length The desired length of the Uint8Array.
* @returns The padded or truncated Uint8Array.
*/
export declare function setLengthLeft(bytes: Uint8Array, length: number): Uint8Array;
/**
* Checks if two Uint8Arrays are equal.
*
* @param x The first Uint8Array to compare.
* @param y The second Uint8Array to compare.
* @returns True if the Uint8Arrays are equal, false otherwise.
*/
export declare function equalsBytes(x: Uint8Array, y: Uint8Array): boolean;
/**
* Converts a UTF-8 encoded string into a byte array.
*
* @param utf8String The UTF-8 encoded string to convert to bytes.
* @returns A Uint8Array representing the byte sequence of the input UTF-8 string.
*/
export declare function utf8StringToBytes(utf8String: string): Uint8Array;
export { bytesToBigInt, bytesToNumber, numberToBytes } from "./number.js";
export { bytesToHexString, hexStringToBytes } from "./hex.js";
//# sourceMappingURL=bytes.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/bytes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAQ3E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAEhE;AAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}

View File

@@ -0,0 +1,47 @@
/**
* Checks if a value is an instance of Uint8Array.
*
* @param value The value to check.
* @returns True if the value is a Uint8Array, false otherwise.
*/
export function isBytes(value) {
return value instanceof Uint8Array;
}
/**
* Pads a Uint8Array with zeros on the left to a specified length, or truncates
* it from the left if it's too long.
*
* @param bytes The Uint8Array to pad or truncate.
* @param length The desired length of the Uint8Array.
* @returns The padded or truncated Uint8Array.
*/
export function setLengthLeft(bytes, length) {
if (bytes.length < length) {
const padded = new Uint8Array(length);
padded.set(bytes, length - bytes.length);
return padded;
}
return bytes.subarray(-length);
}
/**
* Checks if two Uint8Arrays are equal.
*
* @param x The first Uint8Array to compare.
* @param y The second Uint8Array to compare.
* @returns True if the Uint8Arrays are equal, false otherwise.
*/
export function equalsBytes(x, y) {
return x.length === y.length && x.every((xVal, i) => xVal === y[i]);
}
/**
* Converts a UTF-8 encoded string into a byte array.
*
* @param utf8String The UTF-8 encoded string to convert to bytes.
* @returns A Uint8Array representing the byte sequence of the input UTF-8 string.
*/
export function utf8StringToBytes(utf8String) {
return new TextEncoder().encode(utf8String);
}
export { bytesToBigInt, bytesToNumber, numberToBytes } from "./number.js";
export { bytesToHexString, hexStringToBytes } from "./hex.js";
//# sourceMappingURL=bytes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/bytes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,YAAY,UAAU,CAAC;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB,EAAE,MAAc;IAC7D,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,CAAa,EAAE,CAAa;IACtD,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC9C,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}

View File

@@ -0,0 +1,11 @@
/**
* IMPORTANT: A copy of this function exists in `v-next/hardhat-node-test-reporter/src/ci.ts`.
* If you change this function, you must also change the copy.
*/
/**
* Checks whether the current process is running in a CI environment.
*
* @returns True if the current process is running in a CI environment.
*/
export declare function isCi(): boolean;
//# sourceMappingURL=ci.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/ci.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,IAAI,IAAI,OAAO,CAa9B"}

View File

@@ -0,0 +1,22 @@
/**
* IMPORTANT: A copy of this function exists in `v-next/hardhat-node-test-reporter/src/ci.ts`.
* If you change this function, you must also change the copy.
*/
/**
* Checks whether the current process is running in a CI environment.
*
* @returns True if the current process is running in a CI environment.
*/
export function isCi() {
const env = process.env;
return (env.GITHUB_ACTIONS !== undefined || // GitHub Actions
env.NOW !== undefined || // Vercel Now
env.DEPLOYMENT_ID !== undefined || // Vercel Now
env.CODEBUILD_BUILD_NUMBER !== undefined || // AWS CodeBuild
env.CI !== undefined || // Travis CI, CircleCI, Cirrus CI, GitLab CI, Appveyor, CodeShip, dsari
env.CONTINUOUS_INTEGRATION !== undefined || // Travis CI, Cirrus CI
env.BUILD_NUMBER !== undefined || // Jenkins, TeamCity
env.RUN_ID !== undefined // TaskCluster, dsari
);
}
//# sourceMappingURL=ci.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/ci.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,UAAU,IAAI;IAClB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAExB,OAAO,CACL,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,iBAAiB;QACrD,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,aAAa;QACtC,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,aAAa;QAChD,GAAG,CAAC,sBAAsB,KAAK,SAAS,IAAI,gBAAgB;QAC5D,GAAG,CAAC,EAAE,KAAK,SAAS,IAAI,uEAAuE;QAC/F,GAAG,CAAC,sBAAsB,KAAK,SAAS,IAAI,uBAAuB;QACnE,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,oBAAoB;QACtD,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,qBAAqB;KAC/C,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,5 @@
import { CustomError } from "./error.js";
export declare class InvalidParameterError extends CustomError {
constructor(message: string, cause?: Error);
}
//# sourceMappingURL=common-errors.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"common-errors.d.ts","sourceRoot":"","sources":["../../src/common-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C"}

View File

@@ -0,0 +1,7 @@
import { CustomError } from "./error.js";
export class InvalidParameterError extends CustomError {
constructor(message, cause) {
super(message, cause);
}
}
//# sourceMappingURL=common-errors.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"common-errors.js","sourceRoot":"","sources":["../../src/common-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;CACF"}

View File

@@ -0,0 +1,32 @@
/**
* Computes the Keccak-256 hash of the input bytes.
*
* @param bytes The input bytes to hash.
* @returns The Keccak-256 hash of the input bytes.
*/
export declare function keccak256(bytes: Uint8Array): Promise<Uint8Array>;
/**
* Computes the SHA-256 hash of the input bytes.
*
* @param bytes The input bytes to hash.
* @returns The SHA-256 hash of the input bytes.
*/
export declare function sha256(bytes: Uint8Array): Promise<Uint8Array>;
/**
* Creates a non-cryptographic hash-based identifier for the given input.
*
* This function is primarily intended for generating unique identifiers from
* a given input string.
* It uses the SHA-1 hash algorithm, which is not cryptographically secure, but
* is sufficient for this use case as long as the input is not generated by an
* attacker.
*
* Note: The exact algorithm used (SHA-1) is not crucial for the function's
* purpose of generating unique identifiers, and could be replaced if needed.
*
* @param data The input string to be hashed.
* @returns The SHA-1 hash of the input string, represented as a
* hexadecimal string.
*/
export declare function createNonCryptographicHashId(data: string): Promise<string>;
//# sourceMappingURL=crypto.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAEtE;AAED;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAEnE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAIjB"}

View File

@@ -0,0 +1,42 @@
import { keccak256 as keccak256Impl } from "ethereum-cryptography/keccak";
import { sha256 as sha256Impl } from "ethereum-cryptography/sha256";
/**
* Computes the Keccak-256 hash of the input bytes.
*
* @param bytes The input bytes to hash.
* @returns The Keccak-256 hash of the input bytes.
*/
export async function keccak256(bytes) {
return keccak256Impl(bytes);
}
/**
* Computes the SHA-256 hash of the input bytes.
*
* @param bytes The input bytes to hash.
* @returns The SHA-256 hash of the input bytes.
*/
export async function sha256(bytes) {
return sha256Impl(bytes);
}
/**
* Creates a non-cryptographic hash-based identifier for the given input.
*
* This function is primarily intended for generating unique identifiers from
* a given input string.
* It uses the SHA-1 hash algorithm, which is not cryptographically secure, but
* is sufficient for this use case as long as the input is not generated by an
* attacker.
*
* Note: The exact algorithm used (SHA-1) is not crucial for the function's
* purpose of generating unique identifiers, and could be replaced if needed.
*
* @param data The input string to be hashed.
* @returns The SHA-1 hash of the input string, represented as a
* hexadecimal string.
*/
export async function createNonCryptographicHashId(data) {
const message = new TextEncoder().encode(data);
const buffer = await crypto.subtle.digest("SHA-1", message);
return Buffer.from(buffer).toString("hex");
}
//# sourceMappingURL=crypto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAiB;IAC/C,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAiB;IAC5C,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,IAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC"}

View File

@@ -0,0 +1,21 @@
/**
* Converts a string, number, or Date object to a Unix timestamp (seconds since the Unix Epoch).
*
* @param value The string to convert.
* @returns The Unix timestamp.
*/
export declare function toSeconds(value: string | number | Date): number;
/**
* Converts a Unix timestamp to a Date object.
*
* @param timestamp The Unix timestamp to convert.
* @returns The Date object.
*/
export declare function secondsToDate(timestamp: number): Date;
/**
* Gets the current Unix timestamp (seconds since the Unix Epoch).
*
* @returns The current Unix timestamp.
*/
export declare function now(): number;
//# sourceMappingURL=date.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/date.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;;;GAIG;AACH,wBAAgB,GAAG,IAAI,MAAM,CAE5B"}

View File

@@ -0,0 +1,27 @@
/**
* Converts a string, number, or Date object to a Unix timestamp (seconds since the Unix Epoch).
*
* @param value The string to convert.
* @returns The Unix timestamp.
*/
export function toSeconds(value) {
return Math.floor(new Date(value).getTime() / 1000);
}
/**
* Converts a Unix timestamp to a Date object.
*
* @param timestamp The Unix timestamp to convert.
* @returns The Date object.
*/
export function secondsToDate(timestamp) {
return new Date(timestamp * 1000);
}
/**
* Gets the current Unix timestamp (seconds since the Unix Epoch).
*
* @returns The current Unix timestamp.
*/
export function now() {
return Math.floor(Date.now() / 1000);
}
//# sourceMappingURL=date.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/date.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAA6B;IACrD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,OAAO,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,GAAG;IACjB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC"}

View File

@@ -0,0 +1,16 @@
/**
* A simple decorator that adds debug logging for when a method is entered and exited.
*
* This decorator is meant to be used for debugging purposes only. It should not be committed in runtime code.
*
* Example usage:
*
* ```
* class MyClass {
* @withDebugLogs("MyClass:exampleClassMethod")
* public function exampleClassMethod(...)
* }
* ```
*/
export declare function withDebugLogs<This, Args extends any[], Return>(tag?: string): (originalMethod: (this: This, ...args: Args) => Return, _context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>) => (this: This, ...args: Args) => Return;
//# sourceMappingURL=debug.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,SAAS,GAAG,EAAE,EAAE,MAAM,EAC5D,GAAG,GAAE,MAAW,IAGd,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,EACrD,UAAU,2BAA2B,CACnC,IAAI,EACJ,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CACtC,KACA,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,CAYzC"}

View File

@@ -0,0 +1,28 @@
import debugLib from "debug";
/**
* A simple decorator that adds debug logging for when a method is entered and exited.
*
* This decorator is meant to be used for debugging purposes only. It should not be committed in runtime code.
*
* Example usage:
*
* ```
* class MyClass {
* @withDebugLogs("MyClass:exampleClassMethod")
* public function exampleClassMethod(...)
* }
* ```
*/
export function withDebugLogs(tag = "") {
return function actualDecorator(originalMethod, _context) {
const log = debugLib(`hardhat:dev:core${tag === "" ? "" : `:${tag}`}`);
function replacementMethod(...args) {
log(`Entering method with args:`, args);
const result = originalMethod.call(this, ...args);
log(`Exiting method.`);
return result;
}
return replacementMethod;
};
}
//# sourceMappingURL=debug.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,OAAO,CAAC;AAE7B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EAAE;IAEhB,OAAO,SAAS,eAAe,CAC7B,cAAqD,EACrD,QAGC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,mBAAmB,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAEvE,SAAS,iBAAiB,CAAa,GAAG,IAAU;YAClD,GAAG,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAC;YACxC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;YAClD,GAAG,CAAC,iBAAiB,CAAC,CAAC;YACvB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,19 @@
/**
* Sets the resolved global options as environment variables.
*
* @param globalOptions An object containing the resolved global options,
* with each option adhering to its definition in the globalOptionDefinitions.
*/
export declare function setGlobalOptionsAsEnvVariables<T extends Record<keyof T, string | boolean>>(globalOptions: T): void;
/**
* Converts a global option name to its corresponding environment variable name.
* The conversion involves transforming the option name from camelCase to
* SNAKE_CASE and prefixing it with "HARDHAT_".
*
* @param globalOptionName The name of the global option in camelCase.
*
* @returns The corresponding environment variable name in the format
* "HARDHAT_<OPTION_NAME_IN_SNAKE_CASE>".
*/
export declare function getEnvVariableNameFromGlobalOption(globalOptionName: string): string;
//# sourceMappingURL=env.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/env.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAC3C,aAAa,EAAE,CAAC,GAAG,IAAI,CAQxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAAC,gBAAgB,EAAE,MAAM,UAE1E"}

View File

@@ -0,0 +1,29 @@
import { camelToSnakeCase } from "./string.js";
/**
* Sets the resolved global options as environment variables.
*
* @param globalOptions An object containing the resolved global options,
* with each option adhering to its definition in the globalOptionDefinitions.
*/
export function setGlobalOptionsAsEnvVariables(globalOptions) {
for (const [name, value] of Object.entries(globalOptions)) {
const envName = getEnvVariableNameFromGlobalOption(name);
if (value !== undefined) {
process.env[envName] = String(value);
}
}
}
/**
* Converts a global option name to its corresponding environment variable name.
* The conversion involves transforming the option name from camelCase to
* SNAKE_CASE and prefixing it with "HARDHAT_".
*
* @param globalOptionName The name of the global option in camelCase.
*
* @returns The corresponding environment variable name in the format
* "HARDHAT_<OPTION_NAME_IN_SNAKE_CASE>".
*/
export function getEnvVariableNameFromGlobalOption(globalOptionName) {
return `HARDHAT_${camelToSnakeCase(globalOptionName).toUpperCase()}`;
}
//# sourceMappingURL=env.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,8BAA8B,CAE5C,aAAgB;IAChB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,kCAAkC,CAAC,IAAI,CAAC,CAAC;QAEzD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kCAAkC,CAAC,gBAAwB;IACzE,OAAO,WAAW,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;AACvE,CAAC"}

View File

@@ -0,0 +1,97 @@
/**
* Abstract custom error class, which inherits from the built-in Error class,
* making sure that the standard error properties are set, and the stack trace
* is not polluted with the custom error class' code.
*
* This class supports the `cause` property, which can be used to pass the
* original error that caused the custom error to be thrown. Note that it needs
* to be an instance of the built-in Error class, or a subclass of it. See `ensureError`
* for a convenient way of using it.
*
* @example
* ```ts
* class MyCustomError extends CustomError {
* }
*
* try {
* mayThrow();
* } catch (error) {
* ensureError(error);
* throw new MyCustomError('Something went wrong', error);
* }
* ```
*/
export declare abstract class CustomError extends Error {
stack: string;
constructor(message: string, cause?: Error);
}
/**
* Ensures that the provided value is an instance of an error.
*
* @example
* This function is meant to be used in a catch block to ensure that you caught the right error.
*
* ```ts
* // Ensuring that you got an Error
* try {
* mayThrow();
* } catch (error) {
* ensureError(error);
* console.err(error.message);
* }
*
* // Ensuring that you got a specific error
* try {
* mayThrow();
* } catch (error) {
* ensureError(error, MyError);
* console.err(error.myMessage());
* }
* ```
*
* @param thrown The value to check.
* @param ErrorType The error type to check against.
* @throws The value if its not an instance of the specified error type.
*/
export declare function ensureError<ErrorT extends Error>(thrown: unknown, ErrorType?: new (...args: any[]) => ErrorT): asserts thrown is ErrorT;
/**
* Ensures that the provided value is a NodeJS.ErrnoException with a string 'code'.
* @param thrown The value to check.
* @throws The value if its not an error or if it doesn't have a code property.
* @example
* ```ts
* try {
* await fs.promises.readFile("non-existing-file.txt");
* } catch (error) {
* ensureNodeErrnoExceptionError(error);
* console.error(error.code);
* }
* ```
*/
export declare function ensureNodeErrnoExceptionError(thrown: unknown): asserts thrown is NodeJS.ErrnoException & Error & {
code: string;
};
/**
* Throws an error for an unreachable code path. This function is typically
* used in a default case of a switch statement where all possible values of
* the switched variable should be handled in other cases. If the default case
* is reached, it means that an unexpected value was encountered, so an error
* is thrown.
*
* Note: The `@typescript-eslint/switch-exhaustiveness-check` rule checks for
* exhaustiveness in switch statements by comparing the types of the switch
* expression and the case clauses. However, it only works with union types and
* enum types. If you're switching on the result of the `typeof` operator or
* any other expression that doesn't return a union type or an enum type, this
* rule cannot enforce exhaustiveness. In such cases, you can use this function
* in the default case to ensure that an error is thrown if an unexpected value
* is encountered.
*
* @param _value The unexpected value. This parameter is unused and is only for
* the purpose of type checking.
* @param error The error to throw.
* @returns This function never returns normally. It always throws an error.
* @throws Will throw an error when called.
*/
export declare function unreachable(_value: never, error: Error): never;
//# sourceMappingURL=error.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,8BAAsB,WAAY,SAAQ,KAAK;IAC7B,KAAK,EAAG,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAK3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CAAC,MAAM,SAAS,KAAK,EAC9C,MAAM,EAAE,OAAO,EACf,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,GACzC,OAAO,CAAC,MAAM,IAAI,MAAM,CAc1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,cAAc,GAAG,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAMpE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAE9D"}

View File

@@ -0,0 +1,117 @@
/**
* Abstract custom error class, which inherits from the built-in Error class,
* making sure that the standard error properties are set, and the stack trace
* is not polluted with the custom error class' code.
*
* This class supports the `cause` property, which can be used to pass the
* original error that caused the custom error to be thrown. Note that it needs
* to be an instance of the built-in Error class, or a subclass of it. See `ensureError`
* for a convenient way of using it.
*
* @example
* ```ts
* class MyCustomError extends CustomError {
* }
*
* try {
* mayThrow();
* } catch (error) {
* ensureError(error);
* throw new MyCustomError('Something went wrong', error);
* }
* ```
*/
export class CustomError extends Error {
stack;
constructor(message, cause) {
super(message, cause !== undefined ? { cause } : undefined);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Ensures that the provided value is an instance of an error.
*
* @example
* This function is meant to be used in a catch block to ensure that you caught the right error.
*
* ```ts
* // Ensuring that you got an Error
* try {
* mayThrow();
* } catch (error) {
* ensureError(error);
* console.err(error.message);
* }
*
* // Ensuring that you got a specific error
* try {
* mayThrow();
* } catch (error) {
* ensureError(error, MyError);
* console.err(error.myMessage());
* }
* ```
*
* @param thrown The value to check.
* @param ErrorType The error type to check against.
* @throws The value if its not an instance of the specified error type.
*/
export function ensureError(thrown, ErrorType) {
if (ErrorType === undefined) {
if (thrown instanceof Error) {
return;
}
throw thrown;
}
if (thrown instanceof ErrorType) {
return;
}
throw thrown;
}
/**
* Ensures that the provided value is a NodeJS.ErrnoException with a string 'code'.
* @param thrown The value to check.
* @throws The value if its not an error or if it doesn't have a code property.
* @example
* ```ts
* try {
* await fs.promises.readFile("non-existing-file.txt");
* } catch (error) {
* ensureNodeErrnoExceptionError(error);
* console.error(error.code);
* }
* ```
*/
export function ensureNodeErrnoExceptionError(thrown) {
ensureError(thrown);
if (!("code" in thrown) || typeof thrown.code !== "string") {
throw thrown;
}
}
/**
* Throws an error for an unreachable code path. This function is typically
* used in a default case of a switch statement where all possible values of
* the switched variable should be handled in other cases. If the default case
* is reached, it means that an unexpected value was encountered, so an error
* is thrown.
*
* Note: The `@typescript-eslint/switch-exhaustiveness-check` rule checks for
* exhaustiveness in switch statements by comparing the types of the switch
* expression and the case clauses. However, it only works with union types and
* enum types. If you're switching on the result of the `typeof` operator or
* any other expression that doesn't return a union type or an enum type, this
* rule cannot enforce exhaustiveness. In such cases, you can use this function
* in the default case to ensure that an error is thrown if an unexpected value
* is encountered.
*
* @param _value The unexpected value. This parameter is unused and is only for
* the purpose of type checking.
* @param error The error to throw.
* @returns This function never returns normally. It always throws an error.
* @throws Will throw an error when called.
*/
export function unreachable(_value, error) {
throw error;
}
//# sourceMappingURL=error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAgB,WAAY,SAAQ,KAAK;IAC7B,KAAK,CAAU;IAE/B,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,WAAW,CACzB,MAAe,EACf,SAA0C;IAE1C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,CAAC;IACf,CAAC;IAED,IAAI,MAAM,YAAY,SAAS,EAAE,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,6BAA6B,CAC3C,MAAe;IAEf,WAAW,CAAC,MAAM,CAAC,CAAC;IAEpB,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3D,MAAM,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,WAAW,CAAC,MAAa,EAAE,KAAY;IACrD,MAAM,KAAK,CAAC;AACd,CAAC"}

View File

@@ -0,0 +1,18 @@
import type { LibraryAddresses, LibraryLink } from "../internal/bytecode.js";
import { CustomError } from "../error.js";
export declare class InvalidLibraryAddressError extends CustomError {
constructor(libraries: LibraryAddresses);
}
export declare class AmbiguousLibraryNameError extends CustomError {
constructor(libraries: Record<string, LibraryLink[]>);
}
export declare class UnnecessaryLibraryError extends CustomError {
constructor(libraries: string[]);
}
export declare class OverlappingLibrariesError extends CustomError {
constructor(libraries: string[]);
}
export declare class MissingLibrariesError extends CustomError {
constructor(libraries: string[]);
}
//# sourceMappingURL=bytecode.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.d.ts","sourceRoot":"","sources":["../../../src/errors/bytecode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,0BAA2B,SAAQ,WAAW;gBAC7C,SAAS,EAAE,gBAAgB;CAUxC;AAED,qBAAa,yBAA0B,SAAQ,WAAW;gBAC5C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;CAerD;AAED,qBAAa,uBAAwB,SAAQ,WAAW;gBAC1C,SAAS,EAAE,MAAM,EAAE;CAUhC;AAED,qBAAa,yBAA0B,SAAQ,WAAW;gBAC5C,SAAS,EAAE,MAAM,EAAE;CAUhC;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,SAAS,EAAE,MAAM,EAAE;CAYhC"}

View File

@@ -0,0 +1,59 @@
import { CustomError } from "../error.js";
export class InvalidLibraryAddressError extends CustomError {
constructor(libraries) {
const formattedLibraries = Object.entries(libraries)
.map(([libraryName, address]) => `\t* "${libraryName}": "${address}"`)
.join("\n");
super(`The following libraries have invalid addresses:
${formattedLibraries}
Please provide valid Ethereum addresses for these libraries.`);
}
}
export class AmbiguousLibraryNameError extends CustomError {
constructor(libraries) {
const formattedLibraries = Object.entries(libraries)
.map(([providedLibraryName, matchingLibraries]) => `\t* "${providedLibraryName}":\n${matchingLibraries
.map(({ libraryFqn }) => `\t\t* "${libraryFqn}"`)
.join("\n")}`)
.join("\n");
super(`The following libraries may resolve to multiple libraries:
${formattedLibraries}
Please provide the fully qualified name for these libraries.`);
}
}
export class UnnecessaryLibraryError extends CustomError {
constructor(libraries) {
const formattedLibraries = libraries
.map((libraryName) => `\t* "${libraryName}"`)
.join("\n");
super(`The following libraries are not referenced by the contract:
${formattedLibraries}
Please provide only the libraries that are needed.`);
}
}
export class OverlappingLibrariesError extends CustomError {
constructor(libraries) {
const formattedLibraries = libraries
.map((libraryFqn) => `\t* "${libraryFqn}"`)
.join("\n");
super(`The following libraries are provided more than once:
${formattedLibraries}
Please ensure that each library is provided only once, either by its name or its fully qualified name.`);
}
}
export class MissingLibrariesError extends CustomError {
constructor(libraries) {
const formattedLibraries = libraries
.map((libraryFqn) => `\t* "${libraryFqn}"`)
.join("\n");
super(`The following libraries are missing:
${formattedLibraries}
Please provide all the required libraries.`);
}
}
//# sourceMappingURL=bytecode.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.js","sourceRoot":"","sources":["../../../src/errors/bytecode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,0BAA2B,SAAQ,WAAW;IACzD,YAAY,SAA2B;QACrC,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;aACjD,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,QAAQ,WAAW,OAAO,OAAO,GAAG,CAAC;aACrE,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,KAAK,CAAC;EACR,kBAAkB;;6DAEyC,CAAC,CAAC;IAC7D,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,WAAW;IACxD,YAAY,SAAwC;QAClD,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;aACjD,GAAG,CACF,CAAC,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAC3C,QAAQ,mBAAmB,OAAO,iBAAiB;aAChD,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,UAAU,GAAG,CAAC;aAChD,IAAI,CAAC,IAAI,CAAC,EAAE,CAClB;aACA,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,KAAK,CAAC;EACR,kBAAkB;;6DAEyC,CAAC,CAAC;IAC7D,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,WAAW;IACtD,YAAY,SAAmB;QAC7B,MAAM,kBAAkB,GAAG,SAAS;aACjC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,QAAQ,WAAW,GAAG,CAAC;aAC5C,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,KAAK,CAAC;EACR,kBAAkB;;mDAE+B,CAAC,CAAC;IACnD,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,WAAW;IACxD,YAAY,SAAmB;QAC7B,MAAM,kBAAkB,GAAG,SAAS;aACjC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,UAAU,GAAG,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,KAAK,CAAC;EACR,kBAAkB;;uGAEmF,CAAC,CAAC;IACvG,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,YAAY,SAAmB;QAC7B,MAAM,kBAAkB,GAAG,SAAS;aACjC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,QAAQ,UAAU,GAAG,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,KAAK,CACH;EACJ,kBAAkB;;2CAEuB,CACtC,CAAC;IACJ,CAAC;CACF"}

View File

@@ -0,0 +1,25 @@
import { CustomError } from "../error.js";
export declare class FileSystemAccessError extends CustomError {
}
export declare class FileNotFoundError extends CustomError {
constructor(filePath: string, cause?: Error);
}
export declare class FileAlreadyExistsError extends CustomError {
constructor(filePath: string, cause?: Error);
}
export declare class InvalidFileFormatError extends CustomError {
constructor(filePath: string, cause: Error);
}
export declare class JsonSerializationError extends CustomError {
constructor(filePath: string, cause: Error);
}
export declare class NotADirectoryError extends CustomError {
constructor(filePath: string, cause: Error);
}
export declare class IsDirectoryError extends CustomError {
constructor(filePath: string, cause: Error | undefined);
}
export declare class DirectoryNotEmptyError extends CustomError {
constructor(filePath: string, cause: Error);
}
//# sourceMappingURL=fs.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../src/errors/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,qBAAa,qBAAsB,SAAQ,WAAW;CAAG;AAEzD,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG5C;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG5C;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAG3C;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAG3C;AAED,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAG3C;AAED,qBAAa,gBAAiB,SAAQ,WAAW;gBACnC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS;CAGvD;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAG3C"}

View File

@@ -0,0 +1,41 @@
import { CustomError } from "../error.js";
// We use this error to encapsulate any other error possibly thrown by node's
// fs apis, as sometimes their errors don't have stack traces.
export class FileSystemAccessError extends CustomError {
}
export class FileNotFoundError extends CustomError {
constructor(filePath, cause) {
super(`File ${filePath} not found`, cause);
}
}
export class FileAlreadyExistsError extends CustomError {
constructor(filePath, cause) {
super(`File ${filePath} already exists`, cause);
}
}
export class InvalidFileFormatError extends CustomError {
constructor(filePath, cause) {
super(`Invalid file format: ${filePath}`, cause);
}
}
export class JsonSerializationError extends CustomError {
constructor(filePath, cause) {
super(`Error serializing JSON file ${filePath}`, cause);
}
}
export class NotADirectoryError extends CustomError {
constructor(filePath, cause) {
super(`Path ${filePath} is not a directory`, cause);
}
}
export class IsDirectoryError extends CustomError {
constructor(filePath, cause) {
super(`Path ${filePath} is a directory`, cause);
}
}
export class DirectoryNotEmptyError extends CustomError {
constructor(filePath, cause) {
super(`Directory ${filePath} is not empty`, cause);
}
}
//# sourceMappingURL=fs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../../src/errors/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,6EAA6E;AAC7E,8DAA8D;AAC9D,MAAM,OAAO,qBAAsB,SAAQ,WAAW;CAAG;AAEzD,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,YAAY,QAAgB,EAAE,KAAa;QACzC,KAAK,CAAC,QAAQ,QAAQ,YAAY,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,WAAW;IACrD,YAAY,QAAgB,EAAE,KAAa;QACzC,KAAK,CAAC,QAAQ,QAAQ,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,WAAW;IACrD,YAAY,QAAgB,EAAE,KAAY;QACxC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,WAAW;IACrD,YAAY,QAAgB,EAAE,KAAY;QACxC,KAAK,CAAC,+BAA+B,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACjD,YAAY,QAAgB,EAAE,KAAY;QACxC,KAAK,CAAC,QAAQ,QAAQ,qBAAqB,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IAC/C,YAAY,QAAgB,EAAE,KAAwB;QACpD,KAAK,CAAC,QAAQ,QAAQ,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,WAAW;IACrD,YAAY,QAAgB,EAAE,KAAY;QACxC,KAAK,CAAC,aAAa,QAAQ,eAAe,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;CACF"}

View File

@@ -0,0 +1,8 @@
import { CustomError } from "../error.js";
export declare class PackageJsonNotFoundError extends CustomError {
constructor(filePathOrUrl: string, cause?: Error);
}
export declare class PackageJsonReadError extends CustomError {
constructor(packageJsonPath: string, cause?: Error);
}
//# sourceMappingURL=package.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../src/errors/package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,wBAAyB,SAAQ,WAAW;gBAC3C,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGjD;AAED,qBAAa,oBAAqB,SAAQ,WAAW;gBACvC,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGnD"}

View File

@@ -0,0 +1,12 @@
import { CustomError } from "../error.js";
export class PackageJsonNotFoundError extends CustomError {
constructor(filePathOrUrl, cause) {
super(`No package.json found for ${filePathOrUrl}`, cause);
}
}
export class PackageJsonReadError extends CustomError {
constructor(packageJsonPath, cause) {
super(`Failed to read package.json at ${packageJsonPath}`, cause);
}
}
//# sourceMappingURL=package.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../../src/errors/package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACvD,YAAY,aAAqB,EAAE,KAAa;QAC9C,KAAK,CAAC,6BAA6B,aAAa,EAAE,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IACnD,YAAY,eAAuB,EAAE,KAAa;QAChD,KAAK,CAAC,kCAAkC,eAAe,EAAE,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC;CACF"}

View File

@@ -0,0 +1,25 @@
import type UndiciT from "undici";
import { CustomError } from "../error.js";
export declare class RequestError extends CustomError {
constructor(url: string, type: UndiciT.Dispatcher.HttpMethod, cause?: Error);
}
export declare class DownloadError extends CustomError {
constructor(url: string, cause?: Error);
}
export declare class DispatcherError extends CustomError {
constructor(message: string, cause?: Error);
}
export declare class RequestTimeoutError extends CustomError {
constructor(url: string, cause?: Error);
}
export declare class ConnectionRefusedError extends CustomError {
constructor(url: string, cause?: Error);
}
export declare class ResponseStatusCodeError extends CustomError {
#private;
readonly statusCode: number;
readonly headers: string[] | Record<string, string | string[] | undefined> | null;
readonly body: null | Record<string, any> | string;
constructor(url: string, cause: Error);
}
//# sourceMappingURL=request.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/errors/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,qBAAa,YAAa,SAAQ,WAAW;gBAC/B,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,KAAK;CAG5E;AAED,qBAAa,aAAc,SAAQ,WAAW;gBAChC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGvC;AAED,qBAAa,eAAgB,SAAQ,WAAW;gBAClC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,qBAAa,mBAAoB,SAAQ,WAAW;gBACtC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGvC;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGvC;AAED,qBAAa,uBAAwB,SAAQ,WAAW;;IACtD,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,OAAO,EACnB,MAAM,EAAE,GACR,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAC7C,IAAI,CAAC;IACT,SAAgB,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC;gBAE9C,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAuCtC"}

View File

@@ -0,0 +1,64 @@
import { CustomError } from "../error.js";
import { sanitizeUrl } from "../internal/request.js";
import { isObject } from "../lang.js";
export class RequestError extends CustomError {
constructor(url, type, cause) {
super(`Failed to make ${type} request to ${sanitizeUrl(url)}`, cause);
}
}
export class DownloadError extends CustomError {
constructor(url, cause) {
super(`Failed to download file from ${sanitizeUrl(url)}`, cause);
}
}
export class DispatcherError extends CustomError {
constructor(message, cause) {
super(`Failed to create dispatcher: ${message}`, cause);
}
}
export class RequestTimeoutError extends CustomError {
constructor(url, cause) {
super(`Request to ${sanitizeUrl(url)} timed out`, cause);
}
}
export class ConnectionRefusedError extends CustomError {
constructor(url, cause) {
super(`Connection to ${sanitizeUrl(url)} was refused`, cause);
}
}
export class ResponseStatusCodeError extends CustomError {
statusCode;
headers;
body;
constructor(url, cause) {
super(`Received an unexpected status code from ${sanitizeUrl(url)}`, cause);
this.statusCode =
"statusCode" in cause && typeof cause.statusCode === "number"
? cause.statusCode
: -1;
this.headers = this.#extractHeaders(cause);
this.body = "body" in cause && isObject(cause.body) ? cause.body : null;
}
#extractHeaders(cause) {
if ("headers" in cause) {
const headers = cause.headers;
if (Array.isArray(headers)) {
return headers;
}
else if (this.#isValidHeaders(headers)) {
return headers;
}
}
return null;
}
#isValidHeaders(headers) {
if (!isObject(headers)) {
return false;
}
return Object.values(headers).every((header) => typeof header === "string" ||
(Array.isArray(header) &&
header.every((item) => typeof item === "string")) ||
header === undefined);
}
}
//# sourceMappingURL=request.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/errors/request.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,8 @@
import { CustomError } from "../error.js";
export declare class SubprocessFileNotFoundError extends CustomError {
constructor(filePath: string);
}
export declare class SubprocessPathIsDirectoryError extends CustomError {
constructor(path: string);
}
//# sourceMappingURL=subprocess.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../../src/errors/subprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,2BAA4B,SAAQ,WAAW;gBAC9C,QAAQ,EAAE,MAAM;CAK7B;AAED,qBAAa,8BAA+B,SAAQ,WAAW;gBACjD,IAAI,EAAE,MAAM;CAKzB"}

View File

@@ -0,0 +1,12 @@
import { CustomError } from "../error.js";
export class SubprocessFileNotFoundError extends CustomError {
constructor(filePath) {
super(`Cannot find the subprocess file to execute, invalid file path: ${filePath}`);
}
}
export class SubprocessPathIsDirectoryError extends CustomError {
constructor(path) {
super(`The provided path is a directory, only files are accepted. Path: ${path}`);
}
}
//# sourceMappingURL=subprocess.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"subprocess.js","sourceRoot":"","sources":["../../../src/errors/subprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,2BAA4B,SAAQ,WAAW;IAC1D,YAAY,QAAgB;QAC1B,KAAK,CACH,kEAAkE,QAAQ,EAAE,CAC7E,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,8BAA+B,SAAQ,WAAW;IAC7D,YAAY,IAAY;QACtB,KAAK,CACH,oEAAoE,IAAI,EAAE,CAC3E,CAAC;IACJ,CAAC;CACF"}

View File

@@ -0,0 +1,29 @@
import { CustomError } from "../error.js";
export declare class BaseMultiProcessMutexError extends CustomError {
constructor(message: string, cause?: Error);
}
export declare class InvalidMultiProcessMutexPathError extends BaseMultiProcessMutexError {
constructor(mutexPath: string);
}
export declare class MultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(lockPath: string, cause: Error);
}
export declare class MultiProcessMutexTimeoutError extends BaseMultiProcessMutexError {
constructor(lockPath: string, timeoutMs: number);
}
export declare class StaleMultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(lockPath: string, ownerUid: number | undefined, cause: Error);
}
export declare class IncompatibleMultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(message: string);
}
export declare class IncompatibleHostnameMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath: string, foreignHostname: string, currentHostname: string);
}
export declare class IncompatiblePlatformMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath: string, foreignPlatform: string, currentPlatform: string);
}
export declare class IncompatibleUidMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath: string, foreignUid: number, currentUid: number);
}
//# sourceMappingURL=synchronization.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"synchronization.d.ts","sourceRoot":"","sources":["../../../src/errors/synchronization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,0BAA2B,SAAQ,WAAW;gBAC7C,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,qBAAa,iCAAkC,SAAQ,0BAA0B;gBACnE,SAAS,EAAE,MAAM;CAG9B;AAED,qBAAa,sBAAuB,SAAQ,0BAA0B;gBACxD,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAG3C;AAED,qBAAa,6BAA8B,SAAQ,0BAA0B;gBAC/D,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAKhD;AAED,qBAAa,2BAA4B,SAAQ,0BAA0B;gBAC7D,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK;CAOzE;AAED,qBAAa,kCAAmC,SAAQ,0BAA0B;gBACpE,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,0CAA2C,SAAQ,kCAAkC;gBAE9F,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM;CAM1B;AAED,qBAAa,0CAA2C,SAAQ,kCAAkC;gBAE9F,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM;CAM1B;AAED,qBAAa,qCAAsC,SAAQ,kCAAkC;gBAC/E,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAKrE"}

View File

@@ -0,0 +1,48 @@
import { CustomError } from "../error.js";
export class BaseMultiProcessMutexError extends CustomError {
constructor(message, cause) {
super(message, cause);
}
}
export class InvalidMultiProcessMutexPathError extends BaseMultiProcessMutexError {
constructor(mutexPath) {
super(`The path ${mutexPath} is not a valid absolute path.`);
}
}
export class MultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(lockPath, cause) {
super(`Unexpected error with lock at ${lockPath}: ${cause.message}`, cause);
}
}
export class MultiProcessMutexTimeoutError extends BaseMultiProcessMutexError {
constructor(lockPath, timeoutMs) {
super(`Timed out waiting to acquire lock at ${lockPath} after ${timeoutMs}ms`);
}
}
export class StaleMultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(lockPath, ownerUid, cause) {
const uidInfo = ownerUid !== undefined ? ` (uid: ${ownerUid})` : "";
super(`Lock at ${lockPath} appears stale but cannot be removed due to insufficient permissions${uidInfo}. Please remove it manually: ${lockPath}`, cause);
}
}
export class IncompatibleMultiProcessMutexError extends BaseMultiProcessMutexError {
constructor(message) {
super(message);
}
}
export class IncompatibleHostnameMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath, foreignHostname, currentHostname) {
super(`Lock at ${lockPath} was created by a different host (${foreignHostname}, current: ${currentHostname}). It cannot be verified or removed automatically. Please remove it manually: ${lockPath}`);
}
}
export class IncompatiblePlatformMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath, foreignPlatform, currentPlatform) {
super(`Lock at ${lockPath} was created on a different platform (${foreignPlatform}, current: ${currentPlatform}). It cannot be verified or removed automatically. Please remove it manually: ${lockPath}`);
}
}
export class IncompatibleUidMultiProcessMutexError extends IncompatibleMultiProcessMutexError {
constructor(lockPath, foreignUid, currentUid) {
super(`Lock at ${lockPath} is owned by a different user (uid: ${foreignUid}, current: ${currentUid}). It cannot be removed automatically. Please remove it manually: ${lockPath}`);
}
}
//# sourceMappingURL=synchronization.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"synchronization.js","sourceRoot":"","sources":["../../../src/errors/synchronization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,0BAA2B,SAAQ,WAAW;IACzD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;CACF;AAED,MAAM,OAAO,iCAAkC,SAAQ,0BAA0B;IAC/E,YAAY,SAAiB;QAC3B,KAAK,CAAC,YAAY,SAAS,gCAAgC,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,0BAA0B;IACpE,YAAY,QAAgB,EAAE,KAAY;QACxC,KAAK,CAAC,iCAAiC,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IAC9E,CAAC;CACF;AAED,MAAM,OAAO,6BAA8B,SAAQ,0BAA0B;IAC3E,YAAY,QAAgB,EAAE,SAAiB;QAC7C,KAAK,CACH,wCAAwC,QAAQ,UAAU,SAAS,IAAI,CACxE,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,0BAA0B;IACzE,YAAY,QAAgB,EAAE,QAA4B,EAAE,KAAY;QACtE,MAAM,OAAO,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,KAAK,CACH,WAAW,QAAQ,uEAAuE,OAAO,gCAAgC,QAAQ,EAAE,EAC3I,KAAK,CACN,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,kCAAmC,SAAQ,0BAA0B;IAChF,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,MAAM,OAAO,0CAA2C,SAAQ,kCAAkC;IAChG,YACE,QAAgB,EAChB,eAAuB,EACvB,eAAuB;QAEvB,KAAK,CACH,WAAW,QAAQ,qCAAqC,eAAe,cAAc,eAAe,iFAAiF,QAAQ,EAAE,CAChM,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,0CAA2C,SAAQ,kCAAkC;IAChG,YACE,QAAgB,EAChB,eAAuB,EACvB,eAAuB;QAEvB,KAAK,CACH,WAAW,QAAQ,yCAAyC,eAAe,cAAc,eAAe,iFAAiF,QAAQ,EAAE,CACpM,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,qCAAsC,SAAQ,kCAAkC;IAC3F,YAAY,QAAgB,EAAE,UAAkB,EAAE,UAAkB;QAClE,KAAK,CACH,WAAW,QAAQ,uCAAuC,UAAU,cAAc,UAAU,qEAAqE,QAAQ,EAAE,CAC5K,CAAC;IACJ,CAAC;CACF"}

View File

@@ -0,0 +1,56 @@
import type { PrefixedHexString } from "./hex.js";
/**
* Checks if a value is an Ethereum address.
*
* @param value The value to check.
* @returns True if the value is an Ethereum address, false otherwise.
*/
export declare function isAddress(value: unknown): value is PrefixedHexString;
/**
* Checks if a value is an Ethereum address and if the checksum is valid.
*
* @param value The value to check.
* @returns True if the value is an Ethereum address with a valid checksum, false otherwise.
*/
export declare function isValidChecksumAddress(value: unknown): Promise<boolean>;
/**
* Checks if a value is an Ethereum hash.
*
* @param value The value to check.
* @returns True if the value is an Ethereum hash, false otherwise.
*/
export declare function isHash(value: unknown): value is PrefixedHexString;
/**
* Converts a number to a hexadecimal string with a length of 32 bytes.
*
* @param value The number to convert.
* @returns The hexadecimal representation of the number padded to 32 bytes.
* @throws InvalidParameterError If the input is not a safe integer or is negative.
*/
export declare function toEvmWord(value: bigint | number): PrefixedHexString;
/**
* Generates a pseudo-random sequence of hash bytes.
*
* @returns A pseudo-random sequence of hash bytes.
*/
export declare function generateHashBytes(): Promise<Uint8Array>;
/**
* Generates a pseudo-random hash.
*
* @returns A pseudo-random hash.
*/
export declare function randomHash(): Promise<PrefixedHexString>;
/**
* Generates a pseudo-random sequence of hash bytes that can be used as an
* address.
*
* @returns A pseudo-random sequence of hash bytes.
*/
export declare function generateAddressBytes(): Promise<Uint8Array>;
/**
* Generates a pseudo-random address.
*
* @returns A pseudo-random address.
*/
export declare function randomAddress(): Promise<PrefixedHexString>;
//# sourceMappingURL=eth.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"eth.d.ts","sourceRoot":"","sources":["../../src/eth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AASlD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAEpE;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAEnE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAG7D;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAG7D;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CAIhE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAGhE"}

View File

@@ -0,0 +1,78 @@
import { bytesToHexString, numberToHexString, setLengthLeft } from "./hex.js";
import { getAddressGenerator, getHashGenerator, isValidChecksum, } from "./internal/eth.js";
/**
* Checks if a value is an Ethereum address.
*
* @param value The value to check.
* @returns True if the value is an Ethereum address, false otherwise.
*/
export function isAddress(value) {
return typeof value === "string" && /^0x[0-9a-f]{40}$/i.test(value);
}
/**
* Checks if a value is an Ethereum address and if the checksum is valid.
*
* @param value The value to check.
* @returns True if the value is an Ethereum address with a valid checksum, false otherwise.
*/
export async function isValidChecksumAddress(value) {
return isAddress(value) && isValidChecksum(value);
}
/**
* Checks if a value is an Ethereum hash.
*
* @param value The value to check.
* @returns True if the value is an Ethereum hash, false otherwise.
*/
export function isHash(value) {
return typeof value === "string" && /^0x[0-9a-f]{64}$/i.test(value);
}
/**
* Converts a number to a hexadecimal string with a length of 32 bytes.
*
* @param value The number to convert.
* @returns The hexadecimal representation of the number padded to 32 bytes.
* @throws InvalidParameterError If the input is not a safe integer or is negative.
*/
export function toEvmWord(value) {
return setLengthLeft(numberToHexString(value), 64);
}
/**
* Generates a pseudo-random sequence of hash bytes.
*
* @returns A pseudo-random sequence of hash bytes.
*/
export async function generateHashBytes() {
const hashGenerator = await getHashGenerator();
return hashGenerator.next();
}
/**
* Generates a pseudo-random hash.
*
* @returns A pseudo-random hash.
*/
export async function randomHash() {
const hashBytes = await generateHashBytes();
return bytesToHexString(hashBytes);
}
/**
* Generates a pseudo-random sequence of hash bytes that can be used as an
* address.
*
* @returns A pseudo-random sequence of hash bytes.
*/
export async function generateAddressBytes() {
const addressGenerator = await getAddressGenerator();
const hashBytes = await addressGenerator.next();
return hashBytes.slice(0, 20);
}
/**
* Generates a pseudo-random address.
*
* @returns A pseudo-random address.
*/
export async function randomAddress() {
const addressBytes = await generateAddressBytes();
return bytesToHexString(addressBytes);
}
//# sourceMappingURL=eth.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"eth.js","sourceRoot":"","sources":["../../src/eth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAAc;IACzD,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,OAAO,aAAa,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,aAAa,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC/C,OAAO,aAAa,CAAC,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,SAAS,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAC5C,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,gBAAgB,GAAG,MAAM,mBAAmB,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;IAChD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,YAAY,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAClD,OAAO,gBAAgB,CAAC,YAAY,CAAC,CAAC;AACxC,CAAC"}

View File

@@ -0,0 +1,69 @@
export interface TableTitle {
type: "title";
text: string;
}
export interface TableSectionHeader {
type: "section-header";
text: string;
}
export interface TableHeader {
type: "header";
cells: string[];
}
export interface TableRow {
type: "row";
cells: string[];
}
export type TableItem = TableTitle | TableSectionHeader | TableHeader | TableRow;
/**
* Formats an array of titles, section headers, headers, and rows into a table
* string with box-drawing characters.
*
* Features:
* - Titles are centered in a standalone box with double borders (╔═╗)
* - Section headers group related content with automatic closing
* - Headers and rows can have different numbers of cells
* - Rows with fewer cells than max columns are handled with special rendering
*
* @param items An array of table items (titles, section headers, headers, and rows).
* Sections are automatically closed when a new section-header or title appears, or
* at the end of the table.
* @returns The formatted table as a string, ready to be rendered.
*
* @example
* ```ts
* formatTable([
* { type: "title", text: "My Table" },
* { type: "section-header", text: "User Data" },
* { type: "header", cells: ["Name", "Age", "City"] },
* { type: "row", cells: ["Alice", "30", "NYC"] },
* { type: "row", cells: ["Bob", "25", "LA"] },
* { type: "section-header", text: "Summary" },
* { type: "header", cells: ["Total", "Count"] },
* { type: "row", cells: ["55", "2"] }
* ]);
*
* // =>
* // ╔═══════════════════╗
* // ║ My Table ║
* // ╚═══════════════════╝
* // ╔═══════════════════╗
* // ║ User Data ║
* // ╟───────┬─────┬─────╢
* // ║ Name │ Age │ City║
* // ╟───────┼─────┼─────╢
* // ║ Alice │ 30 │ NYC ║
* // ╟───────┼─────┼─────╢
* // ║ Bob │ 25 │ LA ║
* // ╚═══════╧═════╧═════╝
* // ╔═══════════════════╗
* // ║ Summary ║
* // ╟───────┬───────────╢
* // ║ Total │ Count ║
* // ╟───────┼───────────╢
* // ║ 55 │ 2 ║
* // ╚═══════╧═══════════╝
* ```
*/
export declare function formatTable(items: TableItem[]): string;
//# sourceMappingURL=format.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GACjB,UAAU,GACV,kBAAkB,GAClB,WAAW,GACX,QAAQ,CAAC;AAEb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAgGtD"}

View File

@@ -0,0 +1,123 @@
import { getColumnWidths, getContentWidth, getHeadingWidth, getStringWidth, renderContentLine, renderHeaderOpen, renderRowSeparator, renderSectionClose, } from "./internal/format.js";
/**
* Formats an array of titles, section headers, headers, and rows into a table
* string with box-drawing characters.
*
* Features:
* - Titles are centered in a standalone box with double borders (╔═╗)
* - Section headers group related content with automatic closing
* - Headers and rows can have different numbers of cells
* - Rows with fewer cells than max columns are handled with special rendering
*
* @param items An array of table items (titles, section headers, headers, and rows).
* Sections are automatically closed when a new section-header or title appears, or
* at the end of the table.
* @returns The formatted table as a string, ready to be rendered.
*
* @example
* ```ts
* formatTable([
* { type: "title", text: "My Table" },
* { type: "section-header", text: "User Data" },
* { type: "header", cells: ["Name", "Age", "City"] },
* { type: "row", cells: ["Alice", "30", "NYC"] },
* { type: "row", cells: ["Bob", "25", "LA"] },
* { type: "section-header", text: "Summary" },
* { type: "header", cells: ["Total", "Count"] },
* { type: "row", cells: ["55", "2"] }
* ]);
*
* // =>
* // ╔═══════════════════╗
* // ║ My Table ║
* // ╚═══════════════════╝
* // ╔═══════════════════╗
* // ║ User Data ║
* // ╟───────┬─────┬─────╢
* // ║ Name │ Age │ City║
* // ╟───────┼─────┼─────╢
* // ║ Alice │ 30 │ NYC ║
* // ╟───────┼─────┼─────╢
* // ║ Bob │ 25 │ LA ║
* // ╚═══════╧═════╧═════╝
* // ╔═══════════════════╗
* // ║ Summary ║
* // ╟───────┬───────────╢
* // ║ Total │ Count ║
* // ╟───────┼───────────╢
* // ║ 55 │ 2 ║
* // ╚═══════╧═══════════╝
* ```
*/
export function formatTable(items) {
if (items.length === 0) {
return "";
}
const columnWidths = getColumnWidths(items);
const contentWidth = getContentWidth(columnWidths);
const headingWidth = getHeadingWidth(items);
// If heading is wider than content, expand last column to fit
if (headingWidth > contentWidth && columnWidths.length > 0) {
const extraSpace = headingWidth - contentWidth;
columnWidths[columnWidths.length - 1] += extraSpace;
}
const tableWidth = Math.max(contentWidth, headingWidth);
const lines = [];
let previousCellCount = 0; // Keep track of previous row/header cell count
let inSection = false;
for (let i = 0; i < items.length; i++) {
const [previous, current] = [items[i - 1], items[i]];
if (current.type === "title") {
if (inSection) {
lines.push(renderSectionClose(columnWidths, previousCellCount));
inSection = false;
}
lines.push("╔" + "═".repeat(tableWidth) + "╗");
const titleDisplayWidth = getStringWidth(current.text);
const titleActualLength = current.text.length;
const centeredTitle = current.text
.padStart((tableWidth + titleDisplayWidth) / 2 +
(titleActualLength - titleDisplayWidth))
.padEnd(tableWidth + (titleActualLength - titleDisplayWidth));
lines.push("║" + centeredTitle + "║");
lines.push("╚" + "═".repeat(tableWidth) + "╝");
}
else if (current.type === "section-header") {
if (inSection) {
lines.push(renderSectionClose(columnWidths, previousCellCount));
}
lines.push("╔" + "═".repeat(tableWidth) + "╗");
const headerDisplayWidth = getStringWidth(current.text);
const headerActualLength = current.text.length;
const paddedHeader = current.text.padEnd(tableWidth - 2 + (headerActualLength - headerDisplayWidth));
lines.push("║ " + paddedHeader + " ║");
inSection = true;
}
else if (current.type === "header") {
const currentCellCount = current.cells.length;
const innerJoiner = previous !== undefined && previous.type === "section-header"
? "┬"
: "┼";
const needsTransition = previous !== undefined &&
previous.type !== "section-header" &&
currentCellCount < previousCellCount;
lines.push(renderHeaderOpen(columnWidths, currentCellCount, innerJoiner, needsTransition));
lines.push(renderContentLine(current.cells, columnWidths, currentCellCount));
previousCellCount = currentCellCount;
}
else if (current.type === "row") {
const currentCellCount = current.cells.length;
// Only add separator if previous wasn't a row
if (previous === undefined || previous.type !== "row") {
lines.push(renderRowSeparator(columnWidths, currentCellCount));
}
lines.push(renderContentLine(current.cells, columnWidths, currentCellCount));
previousCellCount = currentCellCount;
}
}
if (inSection) {
lines.push(renderSectionClose(columnWidths, previousCellCount));
}
return lines.join("\n");
}
//# sourceMappingURL=format.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,277 @@
/**
* Determines the canonical pathname for a given path, resolving any symbolic
* links, and returns it.
*
* @throws FileNotFoundError if absolutePath doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function getRealPath(absolutePath: string): Promise<string>;
/**
* Recursively searches a directory and its subdirectories for files that
* satisfy the specified condition, returning their absolute paths.
*
* @param dirFrom The absolute path of the directory to start the search from.
* @param matches A function to filter files (not directories).
* @param directoryFilter A function to filter which directories to recurse into
* @returns An array of absolute paths. Each file has its true case, except
* for the initial dirFrom part, which preserves the given casing.
* No order is guaranteed. If dirFrom doesn't exist `[]` is returned.
* @throws NotADirectoryError if dirFrom is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function getAllFilesMatching(dirFrom: string, matches?: (absolutePathToFile: string) => Promise<boolean> | boolean, directoryFilter?: (absolutePathToDir: string) => Promise<boolean> | boolean): Promise<string[]>;
/**
* Recursively searches a directory and its subdirectories for directories that
* satisfy the specified condition, returning their absolute paths. Once a
* directory is found, its subdirectories are not searched.
*
* Note: dirFrom is never returned, nor is `matches` called on it.
*
* @param dirFrom The absolute path of the directory to start the search from.
* @param matches A function to filter directories (not files).
* @returns An array of absolute paths. Each path has its true case, except
* for the initial dirFrom part, which preserves the given casing.
* No order is guaranteed. If dirFrom doesn't exist `[]` is returned.
* @throws NotADirectoryError if dirFrom is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function getAllDirectoriesMatching(dirFrom: string, matches?: (absolutePathToDir: string) => Promise<boolean> | boolean): Promise<string[]>;
/**
* Determines the true case path of a given relative path from a specified
* directory, without resolving symbolic links, and returns it.
*
* @param from The absolute path of the directory to start the search from.
* @param relativePath The relative path to get the true case of.
* @returns The true case of the relative path.
* @throws FileNotFoundError if the starting directory or the relative path doesn't exist.
* @throws NotADirectoryError if the starting directory is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function getFileTrueCase(from: string, relativePath: string): Promise<string>;
/**
* Checks if a given path is a directory.
*
* @param absolutePath The path to check.
* @returns `true` if the path is a directory, `false` otherwise.
* @throws FileNotFoundError if the path doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function isDirectory(absolutePath: string): Promise<boolean>;
/**
* Reads a JSON file and parses it. The encoding used is "utf8".
*
* @param absolutePathToFile The path to the file.
* @returns The parsed JSON object.
* @throws FileNotFoundError if the file doesn't exist.
* @throws InvalidFileFormatError if the file is not a valid JSON file.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export declare function readJsonFile<T>(absolutePathToFile: string): Promise<T>;
/**
* Reads a JSON file as a stream and parses it. The encoding used is "utf8".
* This function should be used when parsing very large JSON files.
*
* @param absolutePathToFile The path to the file.
* @returns The parsed JSON object.
* @throws FileNotFoundError if the file doesn't exist.
* @throws InvalidFileFormatError if the file is not a valid JSON file.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export declare function readJsonFileAsStream<T>(absolutePathToFile: string): Promise<T>;
/**
* Writes an object to a JSON file. The encoding used is "utf8" and the file is overwritten.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePathToFile The path to the file. If the file exists, it will be overwritten.
* @param object The object to write.
* @throws JsonSerializationError if the object can't be serialized to JSON.
* @throws FileSystemAccessError for any other error.
*/
export declare function writeJsonFile<T>(absolutePathToFile: string, object: T): Promise<void>;
/**
* Writes an object to a JSON file as stream. The encoding used is "utf8" and the file is overwritten.
* If part of the path doesn't exist, it will be created.
* This function should be used when stringifying very large JSON objects.
*
* @param absolutePathToFile The path to the file. If the file exists, it will be overwritten.
* @param object The object to write.
* @throws JsonSerializationError if the object can't be serialized to JSON.
* @throws FileSystemAccessError for any other error.
*/
export declare function writeJsonFileAsStream<T>(absolutePathToFile: string, object: T): Promise<void>;
/**
* Reads a file and returns its content as a string. The encoding used is "utf8".
*
* @param absolutePathToFile The path to the file.
* @returns The content of the file as a string.
* @throws FileNotFoundError if the file doesn't exist.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export declare function readUtf8File(absolutePathToFile: string): Promise<string>;
/**
* Writes a string to a file. The encoding used is "utf8" and the file is overwritten by default.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePathToFile The path to the file.
* @param data The data to write.
* @param flag The flag to use when writing the file. If not provided, the file will be overwritten.
* See https://nodejs.org/docs/latest-v20.x/api/fs.html#file-system-flags for more information.
* @throws FileAlreadyExistsError if the file already exists and the flag "x" is used.
* @throws FileSystemAccessError for any other error.
*/
export declare function writeUtf8File(absolutePathToFile: string, data: string, flag?: string): Promise<void>;
/**
* Reads a file and returns its content as a Uint8Array.
*
* @param absolutePathToFile The path to the file.
* @returns The content of the file as a Uint8Array.
* @throws FileNotFoundError if the file doesn't exist.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export declare function readBinaryFile(absolutePathToFile: string): Promise<Uint8Array>;
/**
* Reads a directory and returns its content as an array of strings.
*
* @param absolutePathToDir The path to the directory.
* @returns An array of strings with the names of the files and directories in the directory.
* @throws FileNotFoundError if the directory doesn't exist.
* @throws NotADirectoryError if the path is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function readdir(absolutePathToDir: string): Promise<string[]>;
/**
* Creates a directory and any necessary directories along the way. If the directory already exists,
* nothing is done.
*
* @param absolutePath The path to the directory to create.
* @throws FileSystemAccessError for any error.
*/
export declare function mkdir(absolutePath: string): Promise<void>;
/**
* Alias for `mkdir`.
* @see mkdir
*/
export declare const ensureDir: typeof mkdir;
/**
* Creates a temporary directory with the specified prefix.
*
* @param prefix The prefix to use for the temporary directory.
* @returns The absolute path to the created temporary directory.
* @throws FileSystemAccessError for any error.
*/
export declare function mkdtemp(prefix: string): Promise<string>;
/**
* Retrieves the last change time of a file or directory's properties.
* This includes changes to the file's metadata or contents.
*
* @param absolutePath The absolute path to the file or directory.
* @returns The time of the last change as a Date object.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function getChangeTime(absolutePath: string): Promise<Date>;
/**
* Retrieves the last access time of a file or directory's properties.
*
* @param absolutePath The absolute path to the file or directory.
* @returns The time of the last access as a Date object.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function getAccessTime(absolutePath: string): Promise<Date>;
/**
* Retrieves the size of a file.
*
* @param absolutePath The absolute path to the file.
* @returns The size of the file in bytes.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function getFileSize(absolutePath: string): Promise<number>;
/**
* Checks if a file or directory exists.
*
* @param absolutePath The absolute path to the file or directory.
* @returns A boolean indicating whether the file or directory exists.
*/
export declare function exists(absolutePath: string): Promise<boolean>;
/**
* Copies a file from a source to a destination.
* If the destination file already exists, it will be overwritten.
*
* @param source The path to the source file. It can't be a directory.
* @param destination The path to the destination file. It can't be a directory.
* @throws FileNotFoundError if the source path or the destination path doesn't exist.
* @throws IsDirectoryError if the source path or the destination path is a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function copy(source: string, destination: string): Promise<void>;
/**
* Moves a file or directory from a source to a destination. If the source is a
* file and the destination is a file that already exists, it will be overwritten.
* If the source is a directory and the destination is a directory, it needs to be empty.
*
* Note: This method may not work when moving files between different mount points
* or file systems, as the underlying `fsPromises.rename` method may not support it.
*
* @param source The path to the source file or directory.
* @param destination The path to the destination file or directory.
* @throws FileNotFoundError if the source path or the destination path doesn't exist.
* @throws DirectoryNotEmptyError if the source path is a directory and the destination
* path is a directory that is not empty.
* @throws FileSystemAccessError for any other error.
*/
export declare function move(source: string, destination: string): Promise<void>;
/**
* Removes a file or directory recursively.
* Exceptions are ignored for non-existent paths.
*
* @param absolutePath The path to the file or directory to remove.
* @throws FileSystemAccessError for any error, except for non-existent path errors.
*/
export declare function remove(absolutePath: string): Promise<void>;
/**
* Changes the permissions of a file or directory.
*
* @param absolutePath The path to the file or directory.
* @param mode The permissions to set. It can be a string or a number representing the octal mode.
* @throws FileNotFoundError if the path doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export declare function chmod(absolutePath: string, mode: string | number): Promise<void>;
/**
* Creates a file with an empty content. If the file already exists, it will be overwritten.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePath The path to the file to create.
* @throws FileSystemAccessError for any other error.
*/
export declare function createFile(absolutePath: string): Promise<void>;
/**
* Empties a directory by recursively removing all its content. If the
* directory doesn't exist, it will be created. The directory itself is
* not removed.
*
* @param absolutePath The path to the directory to empty.
* @throws NotADirectoryError if the path is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export declare function emptyDir(absolutePath: string): Promise<void>;
/**
* Looks for a file in the current directory and its parents.
*
* @param fileName The name of the file to look for.
* @param from The directory to start the search from. Defaults to the current working directory.
* @returns The absolute path to the file, or `undefined` if it wasn't found.
*/
export declare function findUp(fileName: string, from?: string): Promise<string | undefined>;
/**
* This function uses some heuristics to check if a file is binary by reading the first bytesToCheck bytes from the file.
*/
export declare function isBinaryFile(filePath: string, bytesToCheck?: number): Promise<boolean>;
export { FileNotFoundError, FileSystemAccessError, InvalidFileFormatError, JsonSerializationError, FileAlreadyExistsError, NotADirectoryError, IsDirectoryError, DirectoryNotEmptyError, } from "./errors/fs.js";
//# sourceMappingURL=fs.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/fs.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,742 @@
import fsPromises from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { pipeline } from "node:stream/promises";
import { JSONParser } from "@streamparser/json-node";
import { JsonStreamStringify } from "json-stream-stringify";
import { ensureError, ensureNodeErrnoExceptionError } from "./error.js";
import { FileNotFoundError, FileSystemAccessError, InvalidFileFormatError, JsonSerializationError, FileAlreadyExistsError, NotADirectoryError, IsDirectoryError, DirectoryNotEmptyError, } from "./errors/fs.js";
/**
* Determines the canonical pathname for a given path, resolving any symbolic
* links, and returns it.
*
* @throws FileNotFoundError if absolutePath doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export async function getRealPath(absolutePath) {
try {
return await fsPromises.realpath(path.normalize(absolutePath));
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Recursively searches a directory and its subdirectories for files that
* satisfy the specified condition, returning their absolute paths.
*
* @param dirFrom The absolute path of the directory to start the search from.
* @param matches A function to filter files (not directories).
* @param directoryFilter A function to filter which directories to recurse into
* @returns An array of absolute paths. Each file has its true case, except
* for the initial dirFrom part, which preserves the given casing.
* No order is guaranteed. If dirFrom doesn't exist `[]` is returned.
* @throws NotADirectoryError if dirFrom is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function getAllFilesMatching(dirFrom, matches, directoryFilter) {
const dirContent = await readdirOrEmpty(dirFrom);
const results = await Promise.all(dirContent.map(async (file) => {
const absolutePathToFile = path.join(dirFrom, file);
if (await isDirectory(absolutePathToFile)) {
if (directoryFilter === undefined ||
(await directoryFilter(absolutePathToFile))) {
return getAllFilesMatching(absolutePathToFile, matches, directoryFilter);
}
return [];
}
else if (matches === undefined || (await matches(absolutePathToFile))) {
return absolutePathToFile;
}
else {
return [];
}
}));
return results.flat();
}
/**
* Recursively searches a directory and its subdirectories for directories that
* satisfy the specified condition, returning their absolute paths. Once a
* directory is found, its subdirectories are not searched.
*
* Note: dirFrom is never returned, nor is `matches` called on it.
*
* @param dirFrom The absolute path of the directory to start the search from.
* @param matches A function to filter directories (not files).
* @returns An array of absolute paths. Each path has its true case, except
* for the initial dirFrom part, which preserves the given casing.
* No order is guaranteed. If dirFrom doesn't exist `[]` is returned.
* @throws NotADirectoryError if dirFrom is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function getAllDirectoriesMatching(dirFrom, matches) {
const dirContent = await readdirOrEmpty(dirFrom);
const results = await Promise.all(dirContent.map(async (file) => {
const absolutePathToFile = path.join(dirFrom, file);
if (!(await isDirectory(absolutePathToFile))) {
return [];
}
if (matches === undefined || (await matches(absolutePathToFile))) {
return absolutePathToFile;
}
return getAllDirectoriesMatching(absolutePathToFile, matches);
}));
return results.flat();
}
/**
* Determines the true case path of a given relative path from a specified
* directory, without resolving symbolic links, and returns it.
*
* @param from The absolute path of the directory to start the search from.
* @param relativePath The relative path to get the true case of.
* @returns The true case of the relative path.
* @throws FileNotFoundError if the starting directory or the relative path doesn't exist.
* @throws NotADirectoryError if the starting directory is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function getFileTrueCase(from, relativePath) {
const dirEntries = await readdirOrEmpty(from);
const segments = relativePath.split(path.sep);
const nextDir = segments[0];
const nextDirLowerCase = nextDir.toLowerCase();
for (const dirEntry of dirEntries) {
if (dirEntry.toLowerCase() === nextDirLowerCase) {
if (segments.length === 1) {
return dirEntry;
}
return path.join(dirEntry, await getFileTrueCase(path.join(from, dirEntry), path.relative(nextDir, relativePath)));
}
}
throw new FileNotFoundError(path.join(from, relativePath));
}
/**
* Checks if a given path is a directory.
*
* @param absolutePath The path to check.
* @returns `true` if the path is a directory, `false` otherwise.
* @throws FileNotFoundError if the path doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export async function isDirectory(absolutePath) {
try {
return (await fsPromises.lstat(absolutePath)).isDirectory();
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Reads a JSON file and parses it. The encoding used is "utf8".
*
* @param absolutePathToFile The path to the file.
* @returns The parsed JSON object.
* @throws FileNotFoundError if the file doesn't exist.
* @throws InvalidFileFormatError if the file is not a valid JSON file.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export async function readJsonFile(absolutePathToFile) {
const content = await readUtf8File(absolutePathToFile);
try {
return JSON.parse(content.toString());
}
catch (e) {
ensureError(e);
throw new InvalidFileFormatError(absolutePathToFile, e);
}
}
/**
* Reads a JSON file as a stream and parses it. The encoding used is "utf8".
* This function should be used when parsing very large JSON files.
*
* @param absolutePathToFile The path to the file.
* @returns The parsed JSON object.
* @throws FileNotFoundError if the file doesn't exist.
* @throws InvalidFileFormatError if the file is not a valid JSON file.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export async function readJsonFileAsStream(absolutePathToFile) {
let fileHandle;
try {
fileHandle = await fsPromises.open(absolutePathToFile, "r");
const fileReadStream = fileHandle.createReadStream();
// NOTE: We set a separator to disable self-closing to be able to use the parser
// in the stream.pipeline context; see https://github.com/juanjoDiaz/streamparser-json/issues/47
const jsonParser = new JSONParser({
separator: "",
});
const result = await pipeline(fileReadStream, jsonParser, async (elements) => {
let value;
for await (const element of elements) {
value = element.value;
}
return value;
});
if (result === undefined) {
throw new Error("No data");
}
return result;
}
catch (e) {
ensureError(e);
// If the code is defined, we assume the error to be related to the file system
if ("code" in e) {
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePathToFile, e);
}
if (e.code === "EISDIR") {
throw new IsDirectoryError(absolutePathToFile, e);
}
// If the code is defined, we assume the error to be related to the file system
if (e.code !== undefined) {
throw new FileSystemAccessError(absolutePathToFile, e);
}
}
// Otherwise, we assume the error to be related to the file formatting
throw new InvalidFileFormatError(absolutePathToFile, e);
}
finally {
// Explicitly closing the file handle to fully release the underlying resources
await fileHandle?.close();
}
}
/**
* Writes an object to a JSON file. The encoding used is "utf8" and the file is overwritten.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePathToFile The path to the file. If the file exists, it will be overwritten.
* @param object The object to write.
* @throws JsonSerializationError if the object can't be serialized to JSON.
* @throws FileSystemAccessError for any other error.
*/
export async function writeJsonFile(absolutePathToFile, object) {
let content;
try {
content = JSON.stringify(object, null, 2);
}
catch (e) {
ensureError(e);
throw new JsonSerializationError(absolutePathToFile, e);
}
await writeUtf8File(absolutePathToFile, content);
}
/**
* Writes an object to a JSON file as stream. The encoding used is "utf8" and the file is overwritten.
* If part of the path doesn't exist, it will be created.
* This function should be used when stringifying very large JSON objects.
*
* @param absolutePathToFile The path to the file. If the file exists, it will be overwritten.
* @param object The object to write.
* @throws JsonSerializationError if the object can't be serialized to JSON.
* @throws FileSystemAccessError for any other error.
*/
export async function writeJsonFileAsStream(absolutePathToFile, object) {
const dirPath = path.dirname(absolutePathToFile);
const dirExists = await exists(dirPath);
if (!dirExists) {
await mkdir(dirPath);
}
let fileHandle;
try {
fileHandle = await fsPromises.open(absolutePathToFile, "w");
const jsonStream = new JsonStreamStringify(object);
const fileWriteStream = fileHandle.createWriteStream();
await pipeline(jsonStream, fileWriteStream);
}
catch (e) {
ensureError(e);
// if the directory was created, we should remove it
if (dirExists === false) {
try {
await remove(dirPath);
// we don't want to override the original error
}
catch (_error) { }
}
// If the code is defined, we assume the error to be related to the file system
if ("code" in e && e.code !== undefined) {
throw new FileSystemAccessError(e.message, e);
}
// Otherwise, we assume the error to be related to the file formatting
throw new JsonSerializationError(absolutePathToFile, e);
}
finally {
// NOTE: Historically, not closing the file handle caused issues on Windows,
// for example, when trying to move the file previously written to by this function
await fileHandle?.close();
}
}
/**
* Reads a file and returns its content as a string. The encoding used is "utf8".
*
* @param absolutePathToFile The path to the file.
* @returns The content of the file as a string.
* @throws FileNotFoundError if the file doesn't exist.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export async function readUtf8File(absolutePathToFile) {
try {
return await fsPromises.readFile(absolutePathToFile, { encoding: "utf8" });
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePathToFile, e);
}
if (e.code === "EISDIR") {
throw new IsDirectoryError(absolutePathToFile, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Writes a string to a file. The encoding used is "utf8" and the file is overwritten by default.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePathToFile The path to the file.
* @param data The data to write.
* @param flag The flag to use when writing the file. If not provided, the file will be overwritten.
* See https://nodejs.org/docs/latest-v20.x/api/fs.html#file-system-flags for more information.
* @throws FileAlreadyExistsError if the file already exists and the flag "x" is used.
* @throws FileSystemAccessError for any other error.
*/
export async function writeUtf8File(absolutePathToFile, data, flag) {
const dirPath = path.dirname(absolutePathToFile);
const dirExists = await exists(dirPath);
if (!dirExists) {
await mkdir(dirPath);
}
try {
await fsPromises.writeFile(absolutePathToFile, data, {
encoding: "utf8",
flag,
});
}
catch (e) {
ensureNodeErrnoExceptionError(e);
// if the directory was created, we should remove it
if (dirExists === false) {
try {
await remove(dirPath);
// we don't want to override the original error
}
catch (_error) { }
}
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePathToFile, e);
}
// flag "x" has been used and the file already exists
if (e.code === "EEXIST") {
throw new FileAlreadyExistsError(absolutePathToFile, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Reads a file and returns its content as a Uint8Array.
*
* @param absolutePathToFile The path to the file.
* @returns The content of the file as a Uint8Array.
* @throws FileNotFoundError if the file doesn't exist.
* @throws IsDirectoryError if the path is a directory instead of a file.
* @throws FileSystemAccessError for any other error.
*/
export async function readBinaryFile(absolutePathToFile) {
try {
const buffer = await fsPromises.readFile(absolutePathToFile);
return new Uint8Array(buffer);
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePathToFile, e);
}
if (e.code === "EISDIR") {
throw new IsDirectoryError(absolutePathToFile, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Reads a directory and returns its content as an array of strings.
*
* @param absolutePathToDir The path to the directory.
* @returns An array of strings with the names of the files and directories in the directory.
* @throws FileNotFoundError if the directory doesn't exist.
* @throws NotADirectoryError if the path is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function readdir(absolutePathToDir) {
try {
return await fsPromises.readdir(absolutePathToDir);
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePathToDir, e);
}
if (e.code === "ENOTDIR") {
throw new NotADirectoryError(absolutePathToDir, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Wrapper around `readdir` that returns an empty array if the directory doesn't exist.
*
* @see readdir
*/
async function readdirOrEmpty(dirFrom) {
try {
return await readdir(dirFrom);
}
catch (error) {
if (error instanceof FileNotFoundError) {
return [];
}
throw error;
}
}
/**
* Creates a directory and any necessary directories along the way. If the directory already exists,
* nothing is done.
*
* @param absolutePath The path to the directory to create.
* @throws FileSystemAccessError for any error.
*/
export async function mkdir(absolutePath) {
try {
await fsPromises.mkdir(absolutePath, { recursive: true });
}
catch (e) {
ensureNodeErrnoExceptionError(e);
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Alias for `mkdir`.
* @see mkdir
*/
export const ensureDir = mkdir;
/**
* Creates a temporary directory with the specified prefix.
*
* @param prefix The prefix to use for the temporary directory.
* @returns The absolute path to the created temporary directory.
* @throws FileSystemAccessError for any error.
*/
export async function mkdtemp(prefix) {
try {
return await getRealPath(await fsPromises.mkdtemp(path.join(tmpdir(), prefix)));
}
catch (e) {
ensureNodeErrnoExceptionError(e);
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Retrieves the last change time of a file or directory's properties.
* This includes changes to the file's metadata or contents.
*
* @param absolutePath The absolute path to the file or directory.
* @returns The time of the last change as a Date object.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export async function getChangeTime(absolutePath) {
try {
const stats = await fsPromises.stat(absolutePath);
return stats.ctime;
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Retrieves the last access time of a file or directory's properties.
*
* @param absolutePath The absolute path to the file or directory.
* @returns The time of the last access as a Date object.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export async function getAccessTime(absolutePath) {
try {
const stats = await fsPromises.stat(absolutePath);
return stats.atime;
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Retrieves the size of a file.
*
* @param absolutePath The absolute path to the file.
* @returns The size of the file in bytes.
* @throws FileNotFoundError if the path does not exist.
* @throws FileSystemAccessError for any other error.
*/
export async function getFileSize(absolutePath) {
try {
const stats = await fsPromises.stat(absolutePath);
return stats.size;
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Checks if a file or directory exists.
*
* @param absolutePath The absolute path to the file or directory.
* @returns A boolean indicating whether the file or directory exists.
*/
export async function exists(absolutePath) {
try {
await fsPromises.access(absolutePath);
return true;
}
catch (_error) {
return false;
}
}
/**
* Copies a file from a source to a destination.
* If the destination file already exists, it will be overwritten.
*
* @param source The path to the source file. It can't be a directory.
* @param destination The path to the destination file. It can't be a directory.
* @throws FileNotFoundError if the source path or the destination path doesn't exist.
* @throws IsDirectoryError if the source path or the destination path is a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function copy(source, destination) {
// We must proactively check if the source is a directory.
// On modern Linux kernels (6.x+), the `copy_file_range` system call used by
// Node.js may return success (0 bytes copied) when the source is a directory
// instead of throwing EISDIR. Node.js interprets this 0-byte success as a
// completed operation, resulting in no error being thrown.
if (await isDirectory(source)) {
throw new IsDirectoryError(source, undefined);
}
try {
await fsPromises.copyFile(source, destination);
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
if (!(await exists(source))) {
throw new FileNotFoundError(source, e);
}
if (!(await exists(destination))) {
throw new FileNotFoundError(destination, e);
}
}
// On linux, trying to copy a directory will throw EISDIR,
// on Windows it will throw EPERM, and on macOS it will throw ENOTSUP.
if (e.code === "EISDIR" || e.code === "EPERM" || e.code === "ENOTSUP") {
if (await isDirectory(source)) {
throw new IsDirectoryError(source, e);
}
if (await isDirectory(destination)) {
throw new IsDirectoryError(destination, e);
}
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Moves a file or directory from a source to a destination. If the source is a
* file and the destination is a file that already exists, it will be overwritten.
* If the source is a directory and the destination is a directory, it needs to be empty.
*
* Note: This method may not work when moving files between different mount points
* or file systems, as the underlying `fsPromises.rename` method may not support it.
*
* @param source The path to the source file or directory.
* @param destination The path to the destination file or directory.
* @throws FileNotFoundError if the source path or the destination path doesn't exist.
* @throws DirectoryNotEmptyError if the source path is a directory and the destination
* path is a directory that is not empty.
* @throws FileSystemAccessError for any other error.
*/
export async function move(source, destination) {
try {
await fsPromises.rename(source, destination);
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
if (!(await exists(source))) {
throw new FileNotFoundError(source, e);
}
if (!(await exists(path.dirname(destination)))) {
throw new FileNotFoundError(destination, e);
}
}
// On linux, trying to move a non-empty directory will throw ENOTEMPTY,
// while on Windows it will throw EPERM.
if (e.code === "ENOTEMPTY" || e.code === "EPERM") {
if (await isDirectory(source)) {
throw new DirectoryNotEmptyError(destination, e);
}
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Removes a file or directory recursively.
* Exceptions are ignored for non-existent paths.
*
* @param absolutePath The path to the file or directory to remove.
* @throws FileSystemAccessError for any error, except for non-existent path errors.
*/
export async function remove(absolutePath) {
try {
await fsPromises.rm(absolutePath, {
recursive: true,
force: true,
maxRetries: 3,
retryDelay: 300,
});
}
catch (e) {
ensureNodeErrnoExceptionError(e);
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Changes the permissions of a file or directory.
*
* @param absolutePath The path to the file or directory.
* @param mode The permissions to set. It can be a string or a number representing the octal mode.
* @throws FileNotFoundError if the path doesn't exist.
* @throws FileSystemAccessError for any other error.
*/
export async function chmod(absolutePath, mode) {
try {
await fsPromises.chmod(absolutePath, mode);
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
throw new FileNotFoundError(absolutePath, e);
}
throw new FileSystemAccessError(e.message, e);
}
}
/**
* Creates a file with an empty content. If the file already exists, it will be overwritten.
* If part of the path doesn't exist, it will be created.
*
* @param absolutePath The path to the file to create.
* @throws FileSystemAccessError for any other error.
*/
export async function createFile(absolutePath) {
await writeUtf8File(absolutePath, "");
}
/**
* Empties a directory by recursively removing all its content. If the
* directory doesn't exist, it will be created. The directory itself is
* not removed.
*
* @param absolutePath The path to the directory to empty.
* @throws NotADirectoryError if the path is not a directory.
* @throws FileSystemAccessError for any other error.
*/
export async function emptyDir(absolutePath) {
let isDir;
let mode;
try {
const stats = await fsPromises.stat(absolutePath);
isDir = stats.isDirectory();
mode = stats.mode;
}
catch (e) {
ensureNodeErrnoExceptionError(e);
if (e.code === "ENOENT") {
await mkdir(absolutePath);
return;
}
throw new FileSystemAccessError(e.message, e);
}
if (!isDir) {
throw new NotADirectoryError(absolutePath, new Error());
}
await remove(absolutePath);
await mkdir(absolutePath);
// eslint-disable-next-line no-bitwise -- Bitwise is common in fs permissions
await chmod(absolutePath, mode & 0o777);
}
/**
* Looks for a file in the current directory and its parents.
*
* @param fileName The name of the file to look for.
* @param from The directory to start the search from. Defaults to the current working directory.
* @returns The absolute path to the file, or `undefined` if it wasn't found.
*/
export async function findUp(fileName, from) {
if (from === undefined) {
from = process.cwd();
}
let currentDir = from;
while (true) {
const absolutePath = path.join(currentDir, fileName);
if (await exists(absolutePath)) {
return absolutePath;
}
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
return undefined;
}
currentDir = parentDir;
}
}
/**
* This function uses some heuristics to check if a file is binary by reading the first bytesToCheck bytes from the file.
*/
export async function isBinaryFile(filePath, bytesToCheck = 8000) {
const fd = await fsPromises.open(filePath, "r");
const buffer = Buffer.alloc(bytesToCheck);
const { bytesRead } = await fd.read(buffer, 0, bytesToCheck, 0);
await fd.close();
let nonPrintable = 0;
for (let i = 0; i < bytesRead; i++) {
const byte = buffer[i];
// Allow common text ranges: tab, newline, carriage return, and printable ASCII
if (byte === 9 || // tab
byte === 10 || // newline
byte === 13 || // carriage return
(byte >= 32 && byte <= 126)) {
continue;
}
nonPrintable++;
}
// Heuristic: if more than ~30% of bytes are non-printable, assume binary
return nonPrintable / bytesRead > 0.3;
}
export { FileNotFoundError, FileSystemAccessError, InvalidFileFormatError, JsonSerializationError, FileAlreadyExistsError, NotADirectoryError, IsDirectoryError, DirectoryNotEmptyError, } from "./errors/fs.js";
//# sourceMappingURL=fs.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
/**
* Sets a mock cache directory for getCacheDir. This is intended for testing
* purposes only, to isolate tests from the real global cache.
*
* @param dir The directory path to use as the mock cache directory.
*/
export declare function setMockCacheDir(dir: string): void;
/**
* Resets the mock cache directory set by setMockCacheDir.
* Call this in test cleanup to restore normal behavior.
*/
export declare function resetMockCacheDir(): void;
/**
* Returns the configuration directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns The path to the hardhat configuration directory.
* @throws FileSystemAccessError for any error.
*/
export declare function getConfigDir(packageName?: string): Promise<string>;
/**
* Returns the cache directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* For testing purposes, the cache directory can be overridden using
* setMockCacheDir(). This is intended to isolate tests from the real
* global cache.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns The path to the hardhat cache directory.
* @throws FileSystemAccessError for any error.
*/
export declare function getCacheDir(packageName?: string): Promise<string>;
/**
* Returns the telemetry directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns A promise that resolves to the path of the telemetry directory.
* @throws FileSystemAccessError for any error.
*/
export declare function getTelemetryDir(packageName?: string): Promise<string>;
//# sourceMappingURL=global-dir.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"global-dir.d.ts","sourceRoot":"","sources":["../../src/global-dir.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAIjB"}

View File

@@ -0,0 +1,69 @@
import { ensureDir } from "./fs.js";
import { generatePaths, HARDHAT_PACKAGE_NAME } from "./internal/global-dir.js";
// Internal override for testing purposes
let _cacheDirOverride;
/**
* Sets a mock cache directory for getCacheDir. This is intended for testing
* purposes only, to isolate tests from the real global cache.
*
* @param dir The directory path to use as the mock cache directory.
*/
export function setMockCacheDir(dir) {
_cacheDirOverride = dir;
}
/**
* Resets the mock cache directory set by setMockCacheDir.
* Call this in test cleanup to restore normal behavior.
*/
export function resetMockCacheDir() {
_cacheDirOverride = undefined;
}
/**
* Returns the configuration directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns The path to the hardhat configuration directory.
* @throws FileSystemAccessError for any error.
*/
export async function getConfigDir(packageName = HARDHAT_PACKAGE_NAME) {
const { config } = await generatePaths(packageName);
await ensureDir(config);
return config;
}
/**
* Returns the cache directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* For testing purposes, the cache directory can be overridden using
* setMockCacheDir(). This is intended to isolate tests from the real
* global cache.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns The path to the hardhat cache directory.
* @throws FileSystemAccessError for any error.
*/
export async function getCacheDir(packageName = HARDHAT_PACKAGE_NAME) {
// Allow override for testing purposes
if (_cacheDirOverride !== undefined) {
await ensureDir(_cacheDirOverride);
return _cacheDirOverride;
}
const { cache } = await generatePaths(packageName);
await ensureDir(cache);
return cache;
}
/**
* Returns the telemetry directory path for a given package (defaults to "hardhat").
* Ensures that the directory exists before returning the path.
*
* @param packageName The name of the package for which to generate paths. Defaults to "hardhat" if no package name is provided.
* @returns A promise that resolves to the path of the telemetry directory.
* @throws FileSystemAccessError for any error.
*/
export async function getTelemetryDir(packageName = HARDHAT_PACKAGE_NAME) {
const { data } = await generatePaths(packageName);
await ensureDir(data);
return data;
}
//# sourceMappingURL=global-dir.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"global-dir.js","sourceRoot":"","sources":["../../src/global-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE/E,yCAAyC;AACzC,IAAI,iBAAqC,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,iBAAiB,GAAG,GAAG,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,iBAAiB,GAAG,SAAS,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,cAAsB,oBAAoB;IAE1C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,cAAsB,oBAAoB;IAE1C,sCAAsC;IACtC,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACnC,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,cAAsB,oBAAoB;IAE1C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,IAAI,CAAC;AACd,CAAC"}

View File

@@ -0,0 +1,117 @@
export type PrefixedHexString = `0x${string}`;
/**
* Converts a non-negative safe integer or bigint to a hexadecimal string.
*
* @param value The number to convert.
* @returns The hexadecimal representation of the number.
* @throws InvalidParameterError If the input is not a safe integer or is negative.
*/
export declare function numberToHexString(value: number | bigint): PrefixedHexString;
/**
* Converts a hexadecimal string to a bigint. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The
* empty string is considered a valid hexadecimal string, so is the string
* "0x" and will be converted to 0.
*
* @param hexString The hexadecimal string to convert. It must be a valid
* hexadecimal string.
* @returns The bigint representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string.
*/
export declare function hexStringToBigInt(hexString: string): bigint;
/**
* Converts a hexadecimal string to a number. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The
* empty string is considered a valid hexadecimal string, so is the string
* "0x" and will be converted to 0.
*
* @param hexString The hexadecimal string to convert. It must be a valid
* hexadecimal string.
* @returns The number representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string or the value exceeds the Number.MAX_SAFE_INTEGER limit.
*/
export declare function hexStringToNumber(hexString: string): number;
/**
* Converts a Uint8Array to a hexadecimal string.
*
* @param bytes The bytes to convert.
* @returns PrefixedHexString The hexadecimal representation of the bytes.
*/
export declare function bytesToHexString(bytes: Uint8Array): PrefixedHexString;
/**
* Converts a hexadecimal string to a Uint8Array. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The empty
* string is considered a valid hexadecimal string, so is the string "0x" and
* will be converted to Uint8Array([0]).
*
* @param hexString The hexadecimal string to convert.
* @returns The byte representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string.
*/
export declare function hexStringToBytes(hexString: string): Uint8Array;
/**
* Normalizes and validates a string that represents a hexadecimal number.
* The normalization process includes trimming any leading or trailing
* whitespace, converting all characters to lowercase, and ensuring the string
* has a "0x" prefix. The validation process checks if the string is a valid
* hexadecimal string.
*
* @param hexString The hex string to normalize.
* @returns The normalized hexadecimal string.
*/
export declare function normalizeHexString(hexString: string): PrefixedHexString;
/**
* Checks if a string starts with "0x" (case-insensitive).
* This function does not validate the input.
*
* @param hexString The string to check.
* @returns True if the string starts with "0x", false otherwise.
*/
export declare function isPrefixedHexString(hexString: string): hexString is PrefixedHexString;
/**
* Removes the "0x" prefix from a hexadecimal string.
* If the string is not prefixed, it is returned as is.
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string without the "0x" prefix.
*/
export declare function getUnprefixedHexString(hexString: string): string;
/**
* Adds the "0x" prefix to a hexadecimal string.
* If the string is already prefixed, it is returned as is.
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string with the "0x" prefix.
*/
export declare function getPrefixedHexString(hexString: string): PrefixedHexString;
/**
* Checks if a value is a hexadecimal string. The string may be prefixed with
* "0x" or not. The empty string is considered a valid hexadecimal string, so
* is the string "0x".
*
* @param value The value to check.
* @returns True if the value is a hexadecimal string, false otherwise.
*/
export declare function isHexString(value: unknown): boolean;
/**
* Removes leading zeros from a hexadecimal string, unless the string
* represents the number zero ("0x0").
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string without leading zeros.
*/
export declare function unpadHexString(hexString: string): string;
/**
* Pads a hexadecimal string with zeros on the left to a specified length, or
* truncates it from the left if it's too long.
* This function does not validate the input.
*
* @param hexString The hexadecimal string to pad.
* @param length The desired length of the hexadecimal string.
* @returns The padded hexadecimal string.
*/
export declare function setLengthLeft(hexString: string, length: number): PrefixedHexString;
//# sourceMappingURL=hex.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hex.d.ts","sourceRoot":"","sources":["../../src/hex.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG,KAAK,MAAM,EAAE,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAW3E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAuB3D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,iBAAiB,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAY9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAUvE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAChB,SAAS,IAAI,iBAAiB,CAEhC;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,iBAAiB,CAUnB"}

View File

@@ -0,0 +1,187 @@
import { InvalidParameterError } from "./common-errors.js";
import { padToEven } from "./internal/hex.js";
/**
* Converts a non-negative safe integer or bigint to a hexadecimal string.
*
* @param value The number to convert.
* @returns The hexadecimal representation of the number.
* @throws InvalidParameterError If the input is not a safe integer or is negative.
*/
export function numberToHexString(value) {
if (value < 0 ||
(typeof value === "number" && !Number.isSafeInteger(value))) {
throw new InvalidParameterError(`Expected a non-negative safe integer or bigint. Received: ${value}`);
}
return `0x${value.toString(16)}`;
}
/**
* Converts a hexadecimal string to a bigint. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The
* empty string is considered a valid hexadecimal string, so is the string
* "0x" and will be converted to 0.
*
* @param hexString The hexadecimal string to convert. It must be a valid
* hexadecimal string.
* @returns The bigint representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string.
*/
export function hexStringToBigInt(hexString) {
if (!isHexString(hexString)) {
throw new InvalidParameterError(`Expected a valid hexadecimal string. Received: ${hexString}`);
}
// Prefix the string as it is required to make BigInt interpret it as a
// hexadecimal number.
let prefixedHexString = getPrefixedHexString(hexString);
// BigInt does not support "0x" as a valid hexadecimal number, so we need to
// add a zero after the prefix if the string is "0x".
prefixedHexString = prefixedHexString === "0x" ? "0x0" : prefixedHexString;
const bigInt = BigInt(prefixedHexString);
return bigInt;
}
/**
* Converts a hexadecimal string to a number. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The
* empty string is considered a valid hexadecimal string, so is the string
* "0x" and will be converted to 0.
*
* @param hexString The hexadecimal string to convert. It must be a valid
* hexadecimal string.
* @returns The number representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string or the value exceeds the Number.MAX_SAFE_INTEGER limit.
*/
export function hexStringToNumber(hexString) {
if (!isHexString(hexString)) {
throw new InvalidParameterError(`Expected a valid hexadecimal string. Received: ${hexString}`);
}
// Prefix the string as it is required to make parseInt interpret it as a
// hexadecimal number.
let prefixedHexString = getPrefixedHexString(hexString);
// Handle the special case where the string is "0x".
prefixedHexString = prefixedHexString === "0x" ? "0x0" : prefixedHexString;
const numberValue = parseInt(prefixedHexString, 16);
if (numberValue > Number.MAX_SAFE_INTEGER) {
throw new InvalidParameterError(`Value exceeds the safe integer limit. Received: ${hexString}`);
}
return numberValue;
}
/**
* Converts a Uint8Array to a hexadecimal string.
*
* @param bytes The bytes to convert.
* @returns PrefixedHexString The hexadecimal representation of the bytes.
*/
export function bytesToHexString(bytes) {
return getPrefixedHexString(Buffer.from(bytes).toString("hex"));
}
/**
* Converts a hexadecimal string to a Uint8Array. The string must be a valid
* hexadecimal string. The string may be prefixed with "0x" or not. The empty
* string is considered a valid hexadecimal string, so is the string "0x" and
* will be converted to Uint8Array([0]).
*
* @param hexString The hexadecimal string to convert.
* @returns The byte representation of the hexadecimal string.
* @throws InvalidParameterError If the input is not a hexadecimal string.
*/
export function hexStringToBytes(hexString) {
if (!isHexString(hexString)) {
throw new InvalidParameterError(`Expected a valid hexadecimal string. Received: ${hexString}`);
}
// Pad the hex string if it's odd, as Buffer.from will truncate it
// the last character if it's not a full byte.
// See: https://nodejs.org/api/buffer.html#buffers-and-character-encodings
const unprefixedHexString = getUnprefixedHexString(padToEven(hexString));
return Uint8Array.from(Buffer.from(unprefixedHexString, "hex"));
}
/**
* Normalizes and validates a string that represents a hexadecimal number.
* The normalization process includes trimming any leading or trailing
* whitespace, converting all characters to lowercase, and ensuring the string
* has a "0x" prefix. The validation process checks if the string is a valid
* hexadecimal string.
*
* @param hexString The hex string to normalize.
* @returns The normalized hexadecimal string.
*/
export function normalizeHexString(hexString) {
const normalizedHexString = hexString.trim().toLowerCase();
if (!isHexString(normalizedHexString)) {
throw new InvalidParameterError(`Expected a valid hexadecimal string. Received: ${hexString}`);
}
return getPrefixedHexString(normalizedHexString);
}
/**
* Checks if a string starts with "0x" (case-insensitive).
* This function does not validate the input.
*
* @param hexString The string to check.
* @returns True if the string starts with "0x", false otherwise.
*/
export function isPrefixedHexString(hexString) {
return hexString.toLowerCase().startsWith("0x");
}
/**
* Removes the "0x" prefix from a hexadecimal string.
* If the string is not prefixed, it is returned as is.
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string without the "0x" prefix.
*/
export function getUnprefixedHexString(hexString) {
return isPrefixedHexString(hexString) ? hexString.substring(2) : hexString;
}
/**
* Adds the "0x" prefix to a hexadecimal string.
* If the string is already prefixed, it is returned as is.
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string with the "0x" prefix.
*/
export function getPrefixedHexString(hexString) {
return isPrefixedHexString(hexString) ? hexString : `0x${hexString}`;
}
/**
* Checks if a value is a hexadecimal string. The string may be prefixed with
* "0x" or not. The empty string is considered a valid hexadecimal string, so
* is the string "0x".
*
* @param value The value to check.
* @returns True if the value is a hexadecimal string, false otherwise.
*/
export function isHexString(value) {
return typeof value === "string" && /^(?:0x)?[0-9a-f]*$/i.test(value);
}
/**
* Removes leading zeros from a hexadecimal string, unless the string
* represents the number zero ("0x0").
* This function does not validate the input.
*
* @param hexString The hexadecimal string.
* @returns The hexadecimal string without leading zeros.
*/
export function unpadHexString(hexString) {
const unprefixedHexString = getUnprefixedHexString(hexString);
const unpaddedHexString = unprefixedHexString.replace(/^0+/, "");
return unpaddedHexString === "" ? "0x0" : `0x${unpaddedHexString}`;
}
/**
* Pads a hexadecimal string with zeros on the left to a specified length, or
* truncates it from the left if it's too long.
* This function does not validate the input.
*
* @param hexString The hexadecimal string to pad.
* @param length The desired length of the hexadecimal string.
* @returns The padded hexadecimal string.
*/
export function setLengthLeft(hexString, length) {
const unprefixedHexString = getUnprefixedHexString(hexString);
// if the string is longer than the desired length, truncate it
if (unprefixedHexString.length > length) {
return `0x${unprefixedHexString.slice(-length)}`;
}
const paddedHexString = unprefixedHexString.padStart(length, "0");
return `0x${paddedHexString}`;
}
//# sourceMappingURL=hex.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hex.js","sourceRoot":"","sources":["../../src/hex.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,45 @@
import type { PrefixedHexString } from "../hex.js";
export interface Artifact {
bytecode: string;
linkReferences: {
[inputSourceName: string]: {
[libraryName: string]: Array<{
start: number;
length: number;
}>;
};
};
}
export interface LibraryLink {
sourceName: string;
libraryName: string;
libraryFqn: string;
address: string;
}
export interface LibraryAddresses {
[contractName: string]: PrefixedHexString;
}
/**
* Check that the provided library addresses are valid Ethereum addresses.
* If any of them are not, an InvalidLibraryAddressError is thrown.
*/
export declare function checkProvidedLibraryAddresses(providedLibraries: LibraryAddresses): void;
/**
* Check that the provided libraries can't be resolved to multiple libraries, or
* that they are not needed by the contract. If any of these conditions are met,
* an AmbiguousLibraryNameError or an UnnecessaryLibraryError is thrown.
*/
export declare function checkAmbiguousOrUnnecessaryLinks(providedLibraries: LibraryAddresses, neededLibraries: LibraryLink[]): void;
/**
* Check that each library is only provided once, either by its name or its
* fully qualified name. If a library is provided more than once, an
* OverlappingLibrariesError is thrown.
*/
export declare function checkOverlappingLibraryNames(providedLibraries: LibraryAddresses, neededLibraries: LibraryLink[]): void;
/**
* Check if the needed libraries have all their addresses resolved. If an
* address is missing, it means that the user didn't provide it in the
* providedLibraries map. In that case, an MissingLibrariesError is thrown.
*/
export declare function checkMissingLibraryAddresses(neededLibraries: LibraryLink[]): void;
//# sourceMappingURL=bytecode.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.d.ts","sourceRoot":"","sources":["../../../src/internal/bytecode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAWnD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE;QACd,CAAC,eAAe,EAAE,MAAM,GAAG;YACzB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;SACjE,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,YAAY,EAAE,MAAM,GAAG,iBAAiB,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,iBAAiB,EAAE,gBAAgB,GAClC,IAAI,CAaN;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,iBAAiB,EAAE,gBAAgB,EACnC,eAAe,EAAE,WAAW,EAAE,GAC7B,IAAI,CAyBN;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,iBAAiB,EAAE,gBAAgB,EACnC,eAAe,EAAE,WAAW,EAAE,GAC7B,IAAI,CAcN;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,WAAW,EAAE,GAC7B,IAAI,CAUN"}

View File

@@ -0,0 +1,73 @@
import { AmbiguousLibraryNameError, InvalidLibraryAddressError, MissingLibrariesError, OverlappingLibrariesError, UnnecessaryLibraryError, } from "../errors/bytecode.js";
import { isAddress } from "../eth.js";
/**
* Check that the provided library addresses are valid Ethereum addresses.
* If any of them are not, an InvalidLibraryAddressError is thrown.
*/
export function checkProvidedLibraryAddresses(providedLibraries) {
const librariesWithInvalidAddresses = {};
for (const [name, address] of Object.entries(providedLibraries)) {
if (!isAddress(address)) {
librariesWithInvalidAddresses[name] = address;
}
}
if (Object.keys(librariesWithInvalidAddresses).length === 0) {
return;
}
throw new InvalidLibraryAddressError(librariesWithInvalidAddresses);
}
/**
* Check that the provided libraries can't be resolved to multiple libraries, or
* that they are not needed by the contract. If any of these conditions are met,
* an AmbiguousLibraryNameError or an UnnecessaryLibraryError is thrown.
*/
export function checkAmbiguousOrUnnecessaryLinks(providedLibraries, neededLibraries) {
const ambiguousLibraries = {};
const unnecessaryLibraries = [];
for (const providedLibraryName of Object.keys(providedLibraries)) {
const matchingLibraries = neededLibraries.filter(({ libraryName, libraryFqn }) => libraryName === providedLibraryName ||
libraryFqn === providedLibraryName);
if (matchingLibraries.length > 1) {
ambiguousLibraries[providedLibraryName] = matchingLibraries;
}
else if (matchingLibraries.length === 0) {
unnecessaryLibraries.push(providedLibraryName);
}
}
if (Object.keys(ambiguousLibraries).length > 0) {
throw new AmbiguousLibraryNameError(ambiguousLibraries);
}
if (unnecessaryLibraries.length > 0) {
throw new UnnecessaryLibraryError(unnecessaryLibraries);
}
}
/**
* Check that each library is only provided once, either by its name or its
* fully qualified name. If a library is provided more than once, an
* OverlappingLibrariesError is thrown.
*/
export function checkOverlappingLibraryNames(providedLibraries, neededLibraries) {
const overlappingLibraries = neededLibraries
.filter(({ libraryName, libraryFqn }) => providedLibraries[libraryFqn] !== undefined &&
providedLibraries[libraryName] !== undefined)
.map(({ libraryFqn }) => libraryFqn);
if (overlappingLibraries.length === 0) {
return;
}
throw new OverlappingLibrariesError(overlappingLibraries);
}
/**
* Check if the needed libraries have all their addresses resolved. If an
* address is missing, it means that the user didn't provide it in the
* providedLibraries map. In that case, an MissingLibrariesError is thrown.
*/
export function checkMissingLibraryAddresses(neededLibraries) {
const missingLibraries = neededLibraries
.filter(({ address }) => address === undefined)
.map(({ libraryFqn }) => libraryFqn);
if (missingLibraries.length === 0) {
return;
}
throw new MissingLibrariesError(missingLibraries);
}
//# sourceMappingURL=bytecode.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytecode.js","sourceRoot":"","sources":["../../../src/internal/bytecode.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,21 @@
declare class RandomBytesGenerator {
#private;
private constructor();
static create(seed: string): Promise<RandomBytesGenerator>;
next(): Promise<Uint8Array>;
}
export declare function getHashGenerator(): Promise<RandomBytesGenerator>;
export declare function getAddressGenerator(): Promise<RandomBytesGenerator>;
/**
* Checks if a value is an Ethereum address and if the checksum is valid.
* This method is a a an adaptation of the ethereumjs methods at this link:
* https://github.com/ethereumjs/ethereumjs-monorepo/blob/47f388bfeec553519d11259fee7e7161a77b29b2/packages/util/src/account.ts#L440-L478
* The main differences are:
* - the two methods have been merged into one
* - tha `eip1191ChainId` parameter has been removed.
* - the code has been modified to use the `hardhat-utils` methods
*
*/
export declare function isValidChecksum(hexAddress: string): Promise<boolean>;
export {};
//# sourceMappingURL=eth.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"eth.d.ts","sourceRoot":"","sources":["../../../src/internal/eth.ts"],"names":[],"mappings":"AAIA,cAAM,oBAAoB;;IAGxB,OAAO;WAIa,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAM1D,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;CAOzC;AAKD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAKtE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAKzE;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB1E"}

View File

@@ -0,0 +1,58 @@
import { utf8StringToBytes } from "../bytes.js";
import { keccak256 } from "../crypto.js";
import { bytesToHexString, getUnprefixedHexString } from "../hex.js";
class RandomBytesGenerator {
#nextValue;
constructor(nextValue) {
this.#nextValue = nextValue;
}
static async create(seed) {
const nextValue = await keccak256(Buffer.from(seed));
return new RandomBytesGenerator(nextValue);
}
async next() {
const valueToReturn = this.#nextValue;
this.#nextValue = await keccak256(this.#nextValue);
return valueToReturn;
}
}
let hashGenerator = null;
let addressGenerator = null;
export async function getHashGenerator() {
if (hashGenerator === null) {
hashGenerator = await RandomBytesGenerator.create("hashSeed");
}
return hashGenerator;
}
export async function getAddressGenerator() {
if (addressGenerator === null) {
addressGenerator = await RandomBytesGenerator.create("addressSeed");
}
return addressGenerator;
}
/**
* Checks if a value is an Ethereum address and if the checksum is valid.
* This method is a a an adaptation of the ethereumjs methods at this link:
* https://github.com/ethereumjs/ethereumjs-monorepo/blob/47f388bfeec553519d11259fee7e7161a77b29b2/packages/util/src/account.ts#L440-L478
* The main differences are:
* - the two methods have been merged into one
* - tha `eip1191ChainId` parameter has been removed.
* - the code has been modified to use the `hardhat-utils` methods
*
*/
export async function isValidChecksum(hexAddress) {
const address = getUnprefixedHexString(hexAddress).toLowerCase();
const bytes = utf8StringToBytes(address);
const hash = bytesToHexString(await keccak256(bytes)).slice(2);
let ret = "";
for (let i = 0; i < address.length; i++) {
if (parseInt(hash[i], 16) >= 8) {
ret += address[i].toUpperCase();
}
else {
ret += address[i];
}
}
return `0x${ret}` === hexAddress;
}
//# sourceMappingURL=eth.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"eth.js","sourceRoot":"","sources":["../../../src/internal/eth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAErE,MAAM,oBAAoB;IACxB,UAAU,CAAa;IAEvB,YAAoB,SAAqB;QACvC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAY;QACrC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAErD,OAAO,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC;QAEtC,IAAI,CAAC,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEnD,OAAO,aAAa,CAAC;IACvB,CAAC;CACF;AAED,IAAI,aAAa,GAAgC,IAAI,CAAC;AACtD,IAAI,gBAAgB,GAAgC,IAAI,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;QAC9B,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,MAAM,OAAO,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAEjE,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEzC,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE/D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,GAAG,EAAE,KAAK,UAAU,CAAC;AACnC,CAAC"}

View File

@@ -0,0 +1,89 @@
import type { TableItem } from "../format.js";
/**
* Calculate the display width of a string by removing ANSI escape codes.
*
* NOTE: This implementation only removes basic ANSI color/style codes and may
* not handle all escape sequences (e.g., cursor movement, complex control
* sequences).
*/
export declare function getStringWidth(str: string): number;
/**
* Calculates the minimum width needed by each column in the table
* to fit its content (accounting for ANSI color codes).
*/
export declare function getColumnWidths(items: TableItem[]): number[];
/**
* Calculates the inner width needed to fit the rows and headers
* (excludes borders, which are added during rendering).
*
* Each column is padded by 1 space on each side, and columns are
* separated by " │ " (3 spaces).
*/
export declare function getContentWidth(columnWidths: number[]): number;
/**
* Calculates the inner width needed to fit titles and section headers
* (excludes borders, which are added during rendering).
*
* Each title/header is padded by 1 space on each side.
* Accounts for ANSI color codes.
*/
export declare function getHeadingWidth(items: TableItem[]): number;
/**
* Calculates the width needed for unused columns when a row/header has fewer
* cells than the total column count (e.g., if table has 6 columns but row
* only has 2 cells, calculates space for the remaining 4 columns).
*/
export declare function getUnusedColumnsWidth(columnWidths: number[], previousCellCount: number): number;
/**
* Renders a horizontal rule segment by repeating a character for each column
* with padding, joined by a separator (e.g., "─────┼─────┼─────").
*/
export declare function renderRuleSegment(columnWidths: number[], char: string, joiner: string): string;
/**
* Renders a complete horizontal rule with left and right borders
* (e.g., "╟─────┼─────┼─────╢").
*/
export declare function renderHorizontalRule(leftBorder: string, columnWidths: number[], char: string, joiner: string, rightBorder: string): string;
/**
* Renders a content line containing cells from either a header or row.
*
* Handles two cases:
* - Full width: When all columns are used, cells are separated by " │ " and
* line ends with " ║" (e.g., "║ cell1 │ cell2 │ cell3 ║")
* - Short line: When fewer columns are used, active cells are followed by
* " │ " and empty space, ending with "║" (e.g., "║ cell1 │ cell2 │ ║")
*
* Accounts for ANSI color codes when padding cells.
*/
export declare function renderContentLine(cells: string[], columnWidths: number[], currentCellCount: number): string;
/**
* Renders the horizontal rule that appears above a header row.
*
* Handles three cases:
* - Transition rule: When going from more columns to fewer, shows ┴ marks
* where columns collapse (e.g., "╟───┼───┼───┴───┴───╢")
* - Full width: When header uses all columns (e.g., "╟───┬───┬───╢" or "╟───┼───┼───╢")
* - Short header: When header uses fewer columns than max (e.g., "╟───┬─────────╢")
*
* The innerJoiner determines the separator character: ┬ after section-header, ┼ otherwise.
*/
export declare function renderHeaderOpen(columnWidths: number[], currentCellCount: number, innerJoiner: string, needsTransition: boolean): string;
/**
* Renders the horizontal rule that appears above a row.
*
* Handles two cases:
* - Full width: When row uses all columns, renders with ┼ joiners and
* ends with ╢ (e.g., "╟───┼───┼───╢")
* - Short row: When row uses fewer columns, renders active columns with
* ┼ joiners, ends with ┤, then fills remaining space and ends with ║
* (e.g., "╟───┼───┤ ║")
*/
export declare function renderRowSeparator(columnWidths: number[], currentCellCount: number): string;
/**
* Renders the section's bottom border, placing ╧ marks under column
* separators where the last row/header had cells (e.g., if the last row
* looked like "║ a │ b │ ║", the bottom border would be
* "╚═══╧═══╧═══════╝").
*/
export declare function renderSectionClose(columnWidths: number[], previousCellCount: number): string;
//# sourceMappingURL=format.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/internal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAY5D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAM9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAQ1D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EAAE,EACtB,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAGR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EAAE,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EAAE,EACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,CAIR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAmCR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,EACxB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,OAAO,GACvB,MAAM,CA2BR;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAkBR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAcR"}

View File

@@ -0,0 +1,199 @@
/**
* Calculate the display width of a string by removing ANSI escape codes.
*
* NOTE: This implementation only removes basic ANSI color/style codes and may
* not handle all escape sequences (e.g., cursor movement, complex control
* sequences).
*/
export function getStringWidth(str) {
// Remove ANSI escape codes if present
const stripped = str.replace(/\u001b\[[0-9;]*m/g, "");
return stripped.length;
}
/**
* Calculates the minimum width needed by each column in the table
* to fit its content (accounting for ANSI color codes).
*/
export function getColumnWidths(items) {
const columnWidths = [];
for (const item of items) {
if (item.type === "row" || item.type === "header") {
item.cells.forEach((cell, i) => {
columnWidths[i] = Math.max(columnWidths[i] ?? 0, getStringWidth(cell));
});
}
}
return columnWidths;
}
/**
* Calculates the inner width needed to fit the rows and headers
* (excludes borders, which are added during rendering).
*
* Each column is padded by 1 space on each side, and columns are
* separated by " │ " (3 spaces).
*/
export function getContentWidth(columnWidths) {
return (columnWidths.reduce((sum, w) => sum + w, 0) +
(columnWidths.length - 1) * 3 +
2);
}
/**
* Calculates the inner width needed to fit titles and section headers
* (excludes borders, which are added during rendering).
*
* Each title/header is padded by 1 space on each side.
* Accounts for ANSI color codes.
*/
export function getHeadingWidth(items) {
let headingWidth = 0;
for (const item of items) {
if (item.type === "section-header" || item.type === "title") {
headingWidth = Math.max(headingWidth, getStringWidth(item.text) + 2);
}
}
return headingWidth;
}
/**
* Calculates the width needed for unused columns when a row/header has fewer
* cells than the total column count (e.g., if table has 6 columns but row
* only has 2 cells, calculates space for the remaining 4 columns).
*/
export function getUnusedColumnsWidth(columnWidths, previousCellCount) {
const remainingWidths = columnWidths.slice(previousCellCount);
return remainingWidths.reduce((sum, w) => sum + w + 3, 0) - 3;
}
/**
* Renders a horizontal rule segment by repeating a character for each column
* with padding, joined by a separator (e.g., "─────┼─────┼─────").
*/
export function renderRuleSegment(columnWidths, char, joiner) {
return columnWidths.map((w) => char.repeat(w + 2)).join(joiner);
}
/**
* Renders a complete horizontal rule with left and right borders
* (e.g., "╟─────┼─────┼─────╢").
*/
export function renderHorizontalRule(leftBorder, columnWidths, char, joiner, rightBorder) {
return (leftBorder + renderRuleSegment(columnWidths, char, joiner) + rightBorder);
}
/**
* Renders a content line containing cells from either a header or row.
*
* Handles two cases:
* - Full width: When all columns are used, cells are separated by " │ " and
* line ends with " ║" (e.g., "║ cell1 │ cell2 │ cell3 ║")
* - Short line: When fewer columns are used, active cells are followed by
* " │ " and empty space, ending with "║" (e.g., "║ cell1 │ cell2 │ ║")
*
* Accounts for ANSI color codes when padding cells.
*/
export function renderContentLine(cells, columnWidths, currentCellCount) {
if (currentCellCount === columnWidths.length) {
return ("║ " +
cells
.map((cell, j) => {
const displayWidth = getStringWidth(cell);
const actualLength = cell.length;
// Adjust padding to account for ANSI escape codes
return cell.padEnd(columnWidths[j] + actualLength - displayWidth);
})
.join(" │ ") +
" ║");
}
else {
const usedWidths = columnWidths.slice(0, currentCellCount);
const remainingWidth = getUnusedColumnsWidth(columnWidths, currentCellCount);
return ("║ " +
cells
.map((cell, j) => {
const displayWidth = getStringWidth(cell);
const actualLength = cell.length;
// Adjust padding to account for ANSI escape codes
return cell.padEnd(usedWidths[j] + actualLength - displayWidth);
})
.join(" │ ") +
" │ " +
" ".repeat(remainingWidth + 1) +
"║");
}
}
/**
* Renders the horizontal rule that appears above a header row.
*
* Handles three cases:
* - Transition rule: When going from more columns to fewer, shows ┴ marks
* where columns collapse (e.g., "╟───┼───┼───┴───┴───╢")
* - Full width: When header uses all columns (e.g., "╟───┬───┬───╢" or "╟───┼───┼───╢")
* - Short header: When header uses fewer columns than max (e.g., "╟───┬─────────╢")
*
* The innerJoiner determines the separator character: ┬ after section-header, ┼ otherwise.
*/
export function renderHeaderOpen(columnWidths, currentCellCount, innerJoiner, needsTransition) {
if (needsTransition) {
const usedWidths = columnWidths.slice(0, currentCellCount);
const collapsingWidths = columnWidths.slice(currentCellCount);
return ("╟" +
renderRuleSegment(usedWidths, "─", "┼") +
"┼" +
renderRuleSegment(collapsingWidths, "─", "┴") +
"╢");
}
else if (currentCellCount === columnWidths.length) {
return renderHorizontalRule("╟", columnWidths, "─", innerJoiner, "╢");
}
else {
const usedWidths = columnWidths.slice(0, currentCellCount);
const remainingWidth = getUnusedColumnsWidth(columnWidths, currentCellCount);
return ("╟" +
renderRuleSegment(usedWidths, "─", innerJoiner) +
innerJoiner +
"─".repeat(remainingWidth + 2) +
"╢");
}
}
/**
* Renders the horizontal rule that appears above a row.
*
* Handles two cases:
* - Full width: When row uses all columns, renders with ┼ joiners and
* ends with ╢ (e.g., "╟───┼───┼───╢")
* - Short row: When row uses fewer columns, renders active columns with
* ┼ joiners, ends with ┤, then fills remaining space and ends with ║
* (e.g., "╟───┼───┤ ║")
*/
export function renderRowSeparator(columnWidths, currentCellCount) {
if (currentCellCount === columnWidths.length) {
return renderHorizontalRule("╟", columnWidths, "─", "┼", "╢");
}
else {
// Short row - ends with ┤ instead of ╢
const usedWidths = columnWidths.slice(0, currentCellCount);
const remainingWidth = getUnusedColumnsWidth(columnWidths, currentCellCount);
return ("╟" +
renderRuleSegment(usedWidths, "─", "┼") +
"┤" +
" ".repeat(remainingWidth + 2) +
"║");
}
}
/**
* Renders the section's bottom border, placing ╧ marks under column
* separators where the last row/header had cells (e.g., if the last row
* looked like "║ a │ b │ ║", the bottom border would be
* "╚═══╧═══╧═══════╝").
*/
export function renderSectionClose(columnWidths, previousCellCount) {
if (previousCellCount === columnWidths.length) {
return renderHorizontalRule("╚", columnWidths, "═", "╧", "╝");
}
else {
const usedWidths = columnWidths.slice(0, previousCellCount);
const unusedWidth = getUnusedColumnsWidth(columnWidths, previousCellCount);
return ("╚" +
renderRuleSegment(usedWidths, "═", "╧") +
"╧" +
renderRuleSegment([unusedWidth], "═", "") +
"╝");
}
}
//# sourceMappingURL=format.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/internal/format.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,4 @@
import type envPaths from "env-paths";
export declare const HARDHAT_PACKAGE_NAME = "hardhat";
export declare function generatePaths(packageName: string): Promise<envPaths.Paths>;
//# sourceMappingURL=global-dir.d.ts.map

Some files were not shown because too many files have changed in this diff Show More