@nomicfoundation/hardhat-utils
Advanced tools
| 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 |
| {"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"} |
| 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 |
| {"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"} |
| import { CustomError } from "../error.js"; | ||
| export class BaseMultiProcessMutexError extends CustomError { | ||
| constructor(message: string, cause?: Error) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| export class InvalidMultiProcessMutexPathError extends BaseMultiProcessMutexError { | ||
| constructor(mutexPath: string) { | ||
| super(`The path ${mutexPath} is not a valid absolute path.`); | ||
| } | ||
| } | ||
| export class MultiProcessMutexError extends BaseMultiProcessMutexError { | ||
| constructor(lockPath: string, cause: Error) { | ||
| super(`Unexpected error with lock at ${lockPath}: ${cause.message}`, cause); | ||
| } | ||
| } | ||
| export class MultiProcessMutexTimeoutError extends BaseMultiProcessMutexError { | ||
| constructor(lockPath: string, timeoutMs: number) { | ||
| super( | ||
| `Timed out waiting to acquire lock at ${lockPath} after ${timeoutMs}ms`, | ||
| ); | ||
| } | ||
| } | ||
| export class StaleMultiProcessMutexError extends BaseMultiProcessMutexError { | ||
| constructor(lockPath: string, ownerUid: number | undefined, cause: Error) { | ||
| 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: string) { | ||
| super(message); | ||
| } | ||
| } | ||
| export class IncompatibleHostnameMultiProcessMutexError extends IncompatibleMultiProcessMutexError { | ||
| constructor( | ||
| lockPath: string, | ||
| foreignHostname: string, | ||
| currentHostname: string, | ||
| ) { | ||
| 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: string, | ||
| foreignPlatform: string, | ||
| currentPlatform: string, | ||
| ) { | ||
| 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: string, foreignUid: number, currentUid: number) { | ||
| super( | ||
| `Lock at ${lockPath} is owned by a different user (uid: ${foreignUid}, current: ${currentUid}). It cannot be removed automatically. Please remove it manually: ${lockPath}`, | ||
| ); | ||
| } | ||
| } |
+11
-0
| # @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 | ||
@@ -4,0 +15,0 @@ |
+7
-41
@@ -1,52 +0,18 @@ | ||
| export type TableRow = string[]; | ||
| export interface TableDivider { | ||
| type: "divider"; | ||
| } | ||
| export type TableItem = TableRow | TableDivider; | ||
| export declare const divider: TableDivider; | ||
| /** | ||
| * Formats an array of rows and dividers into a table string. | ||
| * | ||
| * @param items An array of table rows (string arrays) and dividers. | ||
| * Dividers are objects with type: "divider" and will be rendered as table dividers. | ||
| * @returns The formatted table as a string, ready to be rendered. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * formatTable([ | ||
| * ["Name", "Age"], | ||
| * divider, | ||
| * ["Alice", "30"], | ||
| * ["Bob", "25"], | ||
| * divider, | ||
| * ["Average", "27.5"] | ||
| * ]); | ||
| * | ||
| * // => | ||
| * // | Name | Age | | ||
| * // | ------- | ---- | | ||
| * // | Alice | 30 | | ||
| * // | Bob | 25 | | ||
| * // | ------- | ---- | | ||
| * // | Average | 27.5 | | ||
| * ``` | ||
| */ | ||
| export declare function formatTable(items: TableItem[]): string; | ||
| export interface TableTitleV2 { | ||
| export interface TableTitle { | ||
| type: "title"; | ||
| text: string; | ||
| } | ||
| export interface TableSectionHeaderV2 { | ||
| export interface TableSectionHeader { | ||
| type: "section-header"; | ||
| text: string; | ||
| } | ||
| export interface TableHeaderV2 { | ||
| export interface TableHeader { | ||
| type: "header"; | ||
| cells: string[]; | ||
| } | ||
| export interface TableRowV2 { | ||
| export interface TableRow { | ||
| type: "row"; | ||
| cells: string[]; | ||
| } | ||
| export type TableItemV2 = TableTitleV2 | TableSectionHeaderV2 | TableHeaderV2 | TableRowV2; | ||
| export type TableItem = TableTitle | TableSectionHeader | TableHeader | TableRow; | ||
| /** | ||
@@ -69,3 +35,3 @@ * Formats an array of titles, section headers, headers, and rows into a table | ||
| * ```ts | ||
| * formatTableV2([ | ||
| * formatTable([ | ||
| * { type: "title", text: "My Table" }, | ||
@@ -103,3 +69,3 @@ * { type: "section-header", text: "User Data" }, | ||
| */ | ||
| export declare function formatTableV2(items: TableItemV2[]): string; | ||
| export declare function formatTable(items: TableItem[]): string; | ||
| //# sourceMappingURL=format.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC;AAChC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;CACjB;AACD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEhD,eAAO,MAAM,OAAO,EAAE,YAAkC,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CA8CtD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,oBAAoB,GACpB,aAAa,GACb,UAAU,CAAC;AAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAgG1D"} | ||
| {"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"} |
+2
-72
| import { getColumnWidths, getContentWidth, getHeadingWidth, getStringWidth, renderContentLine, renderHeaderOpen, renderRowSeparator, renderSectionClose, } from "./internal/format.js"; | ||
| export const divider = { type: "divider" }; | ||
| /** | ||
| * Formats an array of rows and dividers into a table string. | ||
| * | ||
| * @param items An array of table rows (string arrays) and dividers. | ||
| * Dividers are objects with type: "divider" and will be rendered as table dividers. | ||
| * @returns The formatted table as a string, ready to be rendered. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * formatTable([ | ||
| * ["Name", "Age"], | ||
| * divider, | ||
| * ["Alice", "30"], | ||
| * ["Bob", "25"], | ||
| * divider, | ||
| * ["Average", "27.5"] | ||
| * ]); | ||
| * | ||
| * // => | ||
| * // | Name | Age | | ||
| * // | ------- | ---- | | ||
| * // | Alice | 30 | | ||
| * // | Bob | 25 | | ||
| * // | ------- | ---- | | ||
| * // | Average | 27.5 | | ||
| * ``` | ||
| */ | ||
| export function formatTable(items) { | ||
| const widths = []; | ||
| const dataRows = []; | ||
| for (const item of items) { | ||
| if (Array.isArray(item)) { | ||
| dataRows.push([...item]); | ||
| } | ||
| } | ||
| // Calculate maximum width for each column | ||
| for (const row of dataRows) { | ||
| for (let i = 0; i < row.length; i++) { | ||
| while (i >= widths.length) { | ||
| widths.push(0); | ||
| } | ||
| widths[i] = Math.max(widths[i], getStringWidth(row[i])); | ||
| } | ||
| } | ||
| const dividerRow = widths.map((width) => "-".repeat(width)); | ||
| const outputRows = []; | ||
| for (const item of items) { | ||
| if (Array.isArray(item)) { | ||
| const row = [...item]; | ||
| // Pad the row to match the number of columns | ||
| while (row.length < widths.length) { | ||
| row.push(""); | ||
| } | ||
| outputRows.push(row); | ||
| } | ||
| else { | ||
| outputRows.push([...dividerRow]); | ||
| } | ||
| } | ||
| outputRows.forEach((row) => { | ||
| for (let i = 0; i < row.length; i++) { | ||
| const displayWidth = getStringWidth(row[i]); | ||
| const actualLength = row[i].length; | ||
| // Adjust padding to account for difference between display width and actual length | ||
| row[i] = row[i].padEnd(widths[i] + actualLength - displayWidth); | ||
| } | ||
| }); | ||
| return outputRows.map((row) => `| ${row.join(" | ")} |`).join("\n"); | ||
| } | ||
| /** | ||
| * Formats an array of titles, section headers, headers, and rows into a table | ||
@@ -89,3 +19,3 @@ * string with box-drawing characters. | ||
| * ```ts | ||
| * formatTableV2([ | ||
| * formatTable([ | ||
| * { type: "title", text: "My Table" }, | ||
@@ -123,3 +53,3 @@ * { type: "section-header", text: "User Data" }, | ||
| */ | ||
| export function formatTableV2(items) { | ||
| export function formatTable(items) { | ||
| if (items.length === 0) { | ||
@@ -126,0 +56,0 @@ return ""; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * 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"). | ||
@@ -14,2 +26,6 @@ * 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. | ||
@@ -16,0 +32,0 @@ * @returns The path to the hardhat cache directory. |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"global-dir.d.ts","sourceRoot":"","sources":["../../src/global-dir.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,WAAW,GAAE,MAA6B,GACzC,OAAO,CAAC,MAAM,CAAC,CAIjB"} | ||
| {"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"} |
| 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"). | ||
@@ -20,2 +38,6 @@ * 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. | ||
@@ -26,2 +48,7 @@ * @returns The path to the hardhat cache directory. | ||
| 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); | ||
@@ -28,0 +55,0 @@ await ensureDir(cache); |
@@ -1,1 +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;;;;;;;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;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,cAAsB,oBAAoB;IAE1C,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"} | ||
| {"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"} |
@@ -1,2 +0,2 @@ | ||
| import type { TableItemV2 } from "../format.js"; | ||
| import type { TableItem } from "../format.js"; | ||
| /** | ||
@@ -14,3 +14,3 @@ * Calculate the display width of a string by removing ANSI escape codes. | ||
| */ | ||
| export declare function getColumnWidths(items: TableItemV2[]): number[]; | ||
| export declare function getColumnWidths(items: TableItem[]): number[]; | ||
| /** | ||
@@ -31,3 +31,3 @@ * Calculates the inner width needed to fit the rows and headers | ||
| */ | ||
| export declare function getHeadingWidth(items: TableItemV2[]): number; | ||
| export declare function getHeadingWidth(items: TableItem[]): number; | ||
| /** | ||
@@ -34,0 +34,0 @@ * Calculates the width needed for unused columns when a row/header has fewer |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/internal/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAY9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAM9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAQ5D;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"} | ||
| {"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"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/internal/format.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/internal/format.ts"],"names":[],"mappings":"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"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/internal/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,YAAY,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,OAAO,MAAM,QAAQ,CAAC;AAgBlC,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU5E;AAED,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,GAAE,cAAmB,EAC/D,6BAA6B,CAAC,EAAE,OAAO,CAAC,UAAU,GAAG,iBAAiB,GACrE,OAAO,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IACxC,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,EAAE,IAAI,CAAC;CACpB,CAAC,CAiBD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASpE;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,GAC/C,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAO7B;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,GAC5B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAKvB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAIxB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,MAAwC,EACjD,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAcxB;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsB9D"} | ||
| {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/internal/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,YAAY,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,OAAO,MAAM,QAAQ,CAAC;AAiBlC,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU5E;AAED,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,GAAE,cAAmB,EAC/D,6BAA6B,CAAC,EAAE,OAAO,CAAC,UAAU,GAAG,iBAAiB,GACrE,OAAO,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IACxC,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,EAAE,IAAI,CAAC;CACpB,CAAC,CAiBD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASpE;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,GAC/C,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAO7B;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,GAC5B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAKvB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,GAC7B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAIxB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,MAAwC,EACjD,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAcxB;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsB9D"} |
@@ -0,1 +1,2 @@ | ||
| import crypto from "node:crypto"; | ||
| import path from "node:path"; | ||
@@ -11,3 +12,3 @@ import { mkdir } from "../fs.js"; | ||
| ext, | ||
| name: `tmp-${name}`, | ||
| name: `tmp-${name}-${crypto.randomBytes(8).toString("hex")}`, | ||
| }); | ||
@@ -14,0 +15,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/internal/request.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/internal/request.ts"],"names":[],"mappings":"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"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":"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"} |
+24
-6
@@ -1,2 +0,2 @@ | ||
| import fs from "node:fs"; | ||
| import { open } from "node:fs/promises"; | ||
| import querystring from "node:querystring"; | ||
@@ -6,3 +6,3 @@ import stream from "node:stream/promises"; | ||
| import { DownloadError, RequestError, DispatcherError, } from "./errors/request.js"; | ||
| import { move } from "./fs.js"; | ||
| import { move, remove } from "./fs.js"; | ||
| import { generateTempFilePath, getBaseDispatcherOptions, getBaseRequestOptions, getBasicDispatcher, getPoolDispatcher, getProxyDispatcher, handleError, } from "./internal/request.js"; | ||
@@ -120,6 +120,7 @@ export const DEFAULT_TIMEOUT_IN_MILLISECONDS = 300_000; // Aligned with unidici | ||
| let statusCode; | ||
| let tempFilePath; | ||
| try { | ||
| /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
| -- We need the full Dispatcher.ResponseData here for stream.pipeline, | ||
| but HttpResponse doesn’t expose the raw ReadableStream. | ||
| but HttpResponse doesn't expose the raw ReadableStream. | ||
| TODO: wrap undici's request so we can keep the public API | ||
@@ -133,5 +134,14 @@ strictly typed without falling back to Undici types. */ | ||
| } | ||
| const tempFilePath = await generateTempFilePath(destination); | ||
| const fileStream = fs.createWriteStream(tempFilePath); | ||
| await stream.pipeline(body, fileStream); | ||
| tempFilePath = await generateTempFilePath(destination); | ||
| let fileHandle; | ||
| try { | ||
| fileHandle = await open(tempFilePath, "w"); | ||
| const fileStream = fileHandle.createWriteStream(); | ||
| await stream.pipeline(body, fileStream); | ||
| } | ||
| 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(); | ||
| } | ||
| await move(tempFilePath, destination); | ||
@@ -141,2 +151,10 @@ } | ||
| ensureError(e); | ||
| if (tempFilePath !== undefined) { | ||
| try { | ||
| await remove(tempFilePath); | ||
| } | ||
| catch { | ||
| // Best-effort: file may not exist or may have already been moved | ||
| } | ||
| } | ||
| handleError(e, url); | ||
@@ -143,0 +161,0 @@ throw new DownloadError(url, e); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/request.ts"],"names":[],"mappings":"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"} |
@@ -0,5 +1,103 @@ | ||
| export { IncompatibleHostnameMultiProcessMutexError, IncompatibleMultiProcessMutexError, IncompatiblePlatformMultiProcessMutexError, IncompatibleUidMultiProcessMutexError, InvalidMultiProcessMutexPathError, MultiProcessMutexError, MultiProcessMutexTimeoutError, StaleMultiProcessMutexError, } from "./errors/synchronization.js"; | ||
| /** | ||
| * A class that implements an inter-process mutex. | ||
| * | ||
| * This Mutex is implemented using hard-link-based atomic file creation. A | ||
| * temporary file containing JSON metadata (PID, hostname, platform, uid, | ||
| * session ID, and creation timestamp) is written first, then hard-linked to | ||
| * the lock path via `fs.linkSync`. `linkSync` fails atomically with `EEXIST` | ||
| * if the lock already exists, ensuring only one process can hold the lock at | ||
| * a time. | ||
| * | ||
| * Staleness is determined by PID liveness only — timestamps are stored for | ||
| * debugging purposes but are never used to determine staleness. This avoids the | ||
| * clock-skew and long-running-task problems that time-based staleness detection | ||
| * has (where a second process can break into a lock that's still legitimately | ||
| * held). | ||
| * | ||
| * Incompatible locks — those created by a different hostname, platform, or | ||
| * uid — are rejected immediately with specific subclasses of | ||
| * `IncompatibleMultiProcessMutexError` | ||
| * (`IncompatibleHostnameMultiProcessMutexError`, | ||
| * `IncompatiblePlatformMultiProcessMutexError`, or | ||
| * `IncompatibleUidMultiProcessMutexError`) because their PID liveness cannot | ||
| * be verified or their lock file cannot be removed. These must be removed | ||
| * manually. | ||
| * | ||
| * When the lock is held by a live process, the caller polls with exponential | ||
| * backoff (default: 5ms → 10ms → ... → 160ms → 200ms cap) until the lock is | ||
| * released or a timeout (default: 60s) is reached. | ||
| * | ||
| * If the filesystem does not support hard links (e.g., certain network | ||
| * filesystems), acquisition fails fast with a `MultiProcessMutexError` rather | ||
| * than degrading into timeout-based retries. | ||
| * | ||
| * ## Performance characteristics | ||
| * | ||
| * - **Uncontended acquisition:** One temp file write + one `linkSync` — takes | ||
| * less than 1ms on most systems. | ||
| * - **Stale lock recovery:** One `readFileSync` to read metadata, one | ||
| * `process.kill(pid, 0)` liveness check, and one `unlinkSync` to remove the | ||
| * stale lock file before retrying acquisition. The retry is immediate (no | ||
| * sleep), so recovery adds sub-millisecond overhead. | ||
| * - **Contended (live holder):** Polls with exponential backoff starting at | ||
| * 5ms and doubling each iteration until capped at 200ms. Worst-case latency | ||
| * after the lock is released is up to `MAX_POLL_INTERVAL_MS` (200ms). | ||
| * - **Release:** A single `unlinkSync` call. | ||
| * | ||
| * ## Limitations | ||
| * | ||
| * - **Polling-based:** There is no filesystem notification; callers discover | ||
| * that the lock is free only on the next poll, so there can be up to 200ms | ||
| * of wasted wait time after the lock is released. | ||
| * - **Not reentrant:** The same process (or even the same `MultiProcessMutex` | ||
| * instance) calling `use()` while already holding the lock will deadlock | ||
| * until the timeout fires. | ||
| * - **Single-host, single-user only:** Encountering a lock from a different | ||
| * hostname throws `IncompatibleHostnameMultiProcessMutexError`, a different | ||
| * platform throws `IncompatiblePlatformMultiProcessMutexError`, and a | ||
| * different uid throws `IncompatibleUidMultiProcessMutexError`. All extend | ||
| * `IncompatibleMultiProcessMutexError`. This means the lock is not safe to | ||
| * use on shared/networked filesystems (e.g., NFS) where multiple hosts or | ||
| * users may access the same path. | ||
| * - **Requires hard-link support:** The underlying filesystem must support | ||
| * `linkSync`. If hard links are unsupported, acquisition fails immediately | ||
| * with `MultiProcessMutexError`. | ||
| * - **PID recycling:** If a process dies and the OS reassigns its PID to a new | ||
| * unrelated process before the stale check runs, the lock is incorrectly | ||
| * considered live. This is extremely unlikely in practice due to the large | ||
| * PID space on modern systems. | ||
| * - **No fairness guarantee:** Multiple waiters polling concurrently have no | ||
| * guaranteed ordering — whichever one succeeds at `linkSync` first after the | ||
| * lock is released wins. | ||
| */ | ||
| export declare class MultiProcessMutex { | ||
| #private; | ||
| constructor(mutexName: string, maxMutexLifespanInMs?: number); | ||
| /** | ||
| * Creates an inter-process mutex given an absolute path. | ||
| * | ||
| * @param absolutePathToLock The absolute path of the mutex. | ||
| * @param timeout The max amount of time to spend trying to acquire the lock | ||
| * in milliseconds. Defaults to 60000. | ||
| * @param initialPollInterval The initial poll interval in milliseconds. | ||
| * Defaults to 5. | ||
| */ | ||
| constructor(absolutePathToLock: string, timeout?: number, initialPollInterval?: number); | ||
| /** | ||
| * Runs the function f while holding the mutex, returning its result. | ||
| * | ||
| * @param f The function to run. | ||
| * @returns The result of the function. | ||
| */ | ||
| use<T>(f: () => Promise<T>): Promise<T>; | ||
| /** | ||
| * Acquires the mutex, returning an async function to release it. | ||
| * The function MUST be called after using the mutex. | ||
| * | ||
| * If this function throws, no cleanup is necessary — the lock was never | ||
| * acquired. | ||
| * | ||
| * @returns The mutex's release function. | ||
| */ | ||
| acquire(): Promise<() => Promise<void>>; | ||
| } | ||
@@ -6,0 +104,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"synchronization.d.ts","sourceRoot":"","sources":["../../src/synchronization.ts"],"names":[],"mappings":"AAwBA,qBAAa,iBAAiB;;gBAIhB,SAAS,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM;IAQ/C,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CA8HrD;AAED;;;;;GAKG;AACH,qBAAa,UAAU;;IAIrB;;;;;;OAMG;IACU,YAAY,CAAC,OAAO,EAC/B,CAAC,EAAE,MAAM,OAAO,GACf,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;CA+B7B"} | ||
| {"version":3,"file":"synchronization.d.ts","sourceRoot":"","sources":["../../src/synchronization.ts"],"names":[],"mappings":"AAqBA,OAAO,EACL,0CAA0C,EAC1C,kCAAkC,EAClC,0CAA0C,EAC1C,qCAAqC,EACrC,iCAAiC,EACjC,sBAAsB,EACtB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AAgCrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,qBAAa,iBAAiB;;IAK5B;;;;;;;;OAQG;gBAED,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,mBAAmB,CAAC,EAAE,MAAM;IAY9B;;;;;OAKG;IACU,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAUpD;;;;;;;;OAQG;IACU,OAAO,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CA+XrD;AAED;;;;;GAKG;AACH,qBAAa,UAAU;;IAIrB;;;;;;OAMG;IACU,YAAY,CAAC,OAAO,EAC/B,CAAC,EAAE,MAAM,OAAO,GACf,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;CA+B7B"} |
+407
-89
@@ -1,105 +0,328 @@ | ||
| // Logic explanation: the fs.writeFile function, when used with the wx+ flag, performs an atomic operation to create a file. | ||
| // If multiple processes try to create the same file simultaneously, only one will succeed. | ||
| // This logic can be utilized to implement a mutex. | ||
| // ATTENTION: in the current implementation, there's still a risk of two processes running simultaneously. | ||
| // For example, if processA has locked the mutex and is running, processB will wait. | ||
| // During this wait, processB continuously checks the elapsed time since the mutex lock file was created. | ||
| // If an excessive amount of time has passed, processB will assume ownership of the mutex to prevent stale locks, even if processA is still running. | ||
| // As a result, two processes will be running simultaneously in what is theoretically a mutex-locked section. | ||
| import fs from "node:fs"; | ||
| import os from "node:os"; | ||
| import path from "node:path"; | ||
| import { randomUUID } from "node:crypto"; | ||
| import * as fs from "node:fs"; | ||
| import * as os from "node:os"; | ||
| import * as path from "node:path"; | ||
| import debug from "debug"; | ||
| import { ensureNodeErrnoExceptionError } from "./error.js"; | ||
| import { FileSystemAccessError } from "./errors/fs.js"; | ||
| import { readUtf8File } from "./fs.js"; | ||
| import { ensureError, ensureNodeErrnoExceptionError } from "./error.js"; | ||
| import { BaseMultiProcessMutexError, IncompatibleHostnameMultiProcessMutexError, IncompatiblePlatformMultiProcessMutexError, IncompatibleUidMultiProcessMutexError, InvalidMultiProcessMutexPathError, MultiProcessMutexError, MultiProcessMutexTimeoutError, StaleMultiProcessMutexError, } from "./errors/synchronization.js"; | ||
| import { ensureDir } from "./fs.js"; | ||
| import { sleep } from "./lang.js"; | ||
| export { IncompatibleHostnameMultiProcessMutexError, IncompatibleMultiProcessMutexError, IncompatiblePlatformMultiProcessMutexError, IncompatibleUidMultiProcessMutexError, InvalidMultiProcessMutexPathError, MultiProcessMutexError, MultiProcessMutexTimeoutError, StaleMultiProcessMutexError, } from "./errors/synchronization.js"; | ||
| const log = debug("hardhat:util:multi-process-mutex"); | ||
| const DEFAULT_MAX_MUTEX_LIFESPAN_IN_MS = 60000; | ||
| const MUTEX_LOOP_WAITING_TIME_IN_MS = 100; | ||
| const PROCESS_SESSION_ID = randomUUID(); | ||
| const DEFAULT_TIMEOUT_MS = 60_000; | ||
| const DEFAULT_INITIAL_POLL_INTERVAL_MS = 5; | ||
| const MAX_POLL_INTERVAL_MS = 200; | ||
| /** | ||
| * Error codes indicating hard links are definitively unsupported on the | ||
| * target filesystem. These cause immediate failure rather than retries. | ||
| */ | ||
| const HARD_LINK_UNSUPPORTED_CODES = new Set(["EOPNOTSUPP", "ENOTSUP", "EXDEV"]); | ||
| /** | ||
| * A class that implements an inter-process mutex. | ||
| * | ||
| * This Mutex is implemented using hard-link-based atomic file creation. A | ||
| * temporary file containing JSON metadata (PID, hostname, platform, uid, | ||
| * session ID, and creation timestamp) is written first, then hard-linked to | ||
| * the lock path via `fs.linkSync`. `linkSync` fails atomically with `EEXIST` | ||
| * if the lock already exists, ensuring only one process can hold the lock at | ||
| * a time. | ||
| * | ||
| * Staleness is determined by PID liveness only — timestamps are stored for | ||
| * debugging purposes but are never used to determine staleness. This avoids the | ||
| * clock-skew and long-running-task problems that time-based staleness detection | ||
| * has (where a second process can break into a lock that's still legitimately | ||
| * held). | ||
| * | ||
| * Incompatible locks — those created by a different hostname, platform, or | ||
| * uid — are rejected immediately with specific subclasses of | ||
| * `IncompatibleMultiProcessMutexError` | ||
| * (`IncompatibleHostnameMultiProcessMutexError`, | ||
| * `IncompatiblePlatformMultiProcessMutexError`, or | ||
| * `IncompatibleUidMultiProcessMutexError`) because their PID liveness cannot | ||
| * be verified or their lock file cannot be removed. These must be removed | ||
| * manually. | ||
| * | ||
| * When the lock is held by a live process, the caller polls with exponential | ||
| * backoff (default: 5ms → 10ms → ... → 160ms → 200ms cap) until the lock is | ||
| * released or a timeout (default: 60s) is reached. | ||
| * | ||
| * If the filesystem does not support hard links (e.g., certain network | ||
| * filesystems), acquisition fails fast with a `MultiProcessMutexError` rather | ||
| * than degrading into timeout-based retries. | ||
| * | ||
| * ## Performance characteristics | ||
| * | ||
| * - **Uncontended acquisition:** One temp file write + one `linkSync` — takes | ||
| * less than 1ms on most systems. | ||
| * - **Stale lock recovery:** One `readFileSync` to read metadata, one | ||
| * `process.kill(pid, 0)` liveness check, and one `unlinkSync` to remove the | ||
| * stale lock file before retrying acquisition. The retry is immediate (no | ||
| * sleep), so recovery adds sub-millisecond overhead. | ||
| * - **Contended (live holder):** Polls with exponential backoff starting at | ||
| * 5ms and doubling each iteration until capped at 200ms. Worst-case latency | ||
| * after the lock is released is up to `MAX_POLL_INTERVAL_MS` (200ms). | ||
| * - **Release:** A single `unlinkSync` call. | ||
| * | ||
| * ## Limitations | ||
| * | ||
| * - **Polling-based:** There is no filesystem notification; callers discover | ||
| * that the lock is free only on the next poll, so there can be up to 200ms | ||
| * of wasted wait time after the lock is released. | ||
| * - **Not reentrant:** The same process (or even the same `MultiProcessMutex` | ||
| * instance) calling `use()` while already holding the lock will deadlock | ||
| * until the timeout fires. | ||
| * - **Single-host, single-user only:** Encountering a lock from a different | ||
| * hostname throws `IncompatibleHostnameMultiProcessMutexError`, a different | ||
| * platform throws `IncompatiblePlatformMultiProcessMutexError`, and a | ||
| * different uid throws `IncompatibleUidMultiProcessMutexError`. All extend | ||
| * `IncompatibleMultiProcessMutexError`. This means the lock is not safe to | ||
| * use on shared/networked filesystems (e.g., NFS) where multiple hosts or | ||
| * users may access the same path. | ||
| * - **Requires hard-link support:** The underlying filesystem must support | ||
| * `linkSync`. If hard links are unsupported, acquisition fails immediately | ||
| * with `MultiProcessMutexError`. | ||
| * - **PID recycling:** If a process dies and the OS reassigns its PID to a new | ||
| * unrelated process before the stale check runs, the lock is incorrectly | ||
| * considered live. This is extremely unlikely in practice due to the large | ||
| * PID space on modern systems. | ||
| * - **No fairness guarantee:** Multiple waiters polling concurrently have no | ||
| * guaranteed ordering — whichever one succeeds at `linkSync` first after the | ||
| * lock is released wins. | ||
| */ | ||
| export class MultiProcessMutex { | ||
| #mutexFilePath; | ||
| #mutexLifespanInMs; | ||
| constructor(mutexName, maxMutexLifespanInMs) { | ||
| log(`Creating mutex with name '${mutexName}'`); | ||
| this.#mutexFilePath = path.join(os.tmpdir(), `${mutexName}.txt`); | ||
| this.#mutexLifespanInMs = | ||
| maxMutexLifespanInMs ?? DEFAULT_MAX_MUTEX_LIFESPAN_IN_MS; | ||
| #lockFilePath; | ||
| #timeout; | ||
| #initialPollInterval; | ||
| /** | ||
| * Creates an inter-process mutex given an absolute path. | ||
| * | ||
| * @param absolutePathToLock The absolute path of the mutex. | ||
| * @param timeout The max amount of time to spend trying to acquire the lock | ||
| * in milliseconds. Defaults to 60000. | ||
| * @param initialPollInterval The initial poll interval in milliseconds. | ||
| * Defaults to 5. | ||
| */ | ||
| constructor(absolutePathToLock, timeout, initialPollInterval) { | ||
| if (!path.isAbsolute(absolutePathToLock)) { | ||
| throw new InvalidMultiProcessMutexPathError(absolutePathToLock); | ||
| } | ||
| this.#lockFilePath = absolutePathToLock; | ||
| this.#timeout = timeout ?? DEFAULT_TIMEOUT_MS; | ||
| this.#initialPollInterval = | ||
| initialPollInterval ?? DEFAULT_INITIAL_POLL_INTERVAL_MS; | ||
| } | ||
| /** | ||
| * Runs the function f while holding the mutex, returning its result. | ||
| * | ||
| * @param f The function to run. | ||
| * @returns The result of the function. | ||
| */ | ||
| async use(f) { | ||
| log(`Starting mutex process with mutex file '${this.#mutexFilePath}'`); | ||
| const release = await this.acquire(); | ||
| try { | ||
| return await f(); | ||
| } | ||
| finally { | ||
| await release(); | ||
| } | ||
| } | ||
| /** | ||
| * Acquires the mutex, returning an async function to release it. | ||
| * The function MUST be called after using the mutex. | ||
| * | ||
| * If this function throws, no cleanup is necessary — the lock was never | ||
| * acquired. | ||
| * | ||
| * @returns The mutex's release function. | ||
| */ | ||
| async acquire() { | ||
| log(`Starting mutex process with lock file '${this.#lockFilePath}'`); | ||
| try { | ||
| await this.#acquireLock(); | ||
| } | ||
| catch (e) { | ||
| ensureError(e); | ||
| if (e instanceof BaseMultiProcessMutexError) { | ||
| throw e; | ||
| } | ||
| throw new MultiProcessMutexError(this.#lockFilePath, e); | ||
| } | ||
| let released = false; | ||
| return async () => { | ||
| if (released) { | ||
| return; | ||
| } | ||
| this.#releaseLock(); | ||
| released = true; | ||
| }; | ||
| } | ||
| async #acquireLock() { | ||
| const startTime = Date.now(); | ||
| let pollInterval = this.#initialPollInterval; | ||
| await ensureDir(path.dirname(this.#lockFilePath)); | ||
| while (true) { | ||
| if (await this.#tryToAcquireMutex()) { | ||
| // Mutex has been acquired | ||
| return this.#executeFunctionAndReleaseMutex(f); | ||
| const result = this.#tryAcquire(); | ||
| if (result.acquired) { | ||
| return; | ||
| } | ||
| // Mutex not acquired | ||
| if (this.#isMutexFileTooOld()) { | ||
| // If the mutex file is too old, it likely indicates a stale lock, so the file should be removed | ||
| log(`Current mutex file is too old, removing it at path '${this.#mutexFilePath}'`); | ||
| this.#deleteMutexFile(); | ||
| // Check timeout | ||
| const elapsed = Date.now() - startTime; | ||
| if (elapsed >= this.#timeout) { | ||
| throw new MultiProcessMutexTimeoutError(this.#lockFilePath, this.#timeout); | ||
| } | ||
| else if (await this.#isMutexProcessOwnerDead()) { | ||
| log(`The process owning the mutex file no longer exists. Removing mutex file at '${this.#mutexFilePath}'.`); | ||
| this.#deleteMutexFile(); | ||
| // Skip sleep after reclaiming a stale lock — retry immediately | ||
| if (result.reclaimedStaleLock) { | ||
| continue; | ||
| } | ||
| else { | ||
| // wait | ||
| await sleep(MUTEX_LOOP_WAITING_TIME_IN_MS / 1000); | ||
| } | ||
| // Wait with exponential backoff | ||
| log(`Lock at ${this.#lockFilePath} is busy, waiting ${pollInterval}ms`); | ||
| await sleep(pollInterval / 1000); | ||
| // Exponential backoff, capped | ||
| pollInterval = Math.min(pollInterval * 2, MAX_POLL_INTERVAL_MS); | ||
| } | ||
| } | ||
| async #tryToAcquireMutex() { | ||
| #releaseLock() { | ||
| try { | ||
| // Create a file only if it does not exist | ||
| fs.writeFileSync(this.#mutexFilePath, process.pid.toString(), { | ||
| flag: "wx+", | ||
| }); | ||
| return true; | ||
| fs.unlinkSync(this.#lockFilePath); | ||
| log(`Released lock at ${this.#lockFilePath}`); | ||
| } | ||
| catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "EEXIST") { | ||
| // File already exists, so the mutex is already acquired | ||
| return false; | ||
| if (e.code === "ENOENT") { | ||
| log(`Lock at ${this.#lockFilePath} already removed`); | ||
| return; | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| throw new MultiProcessMutexError(this.#lockFilePath, e); | ||
| } | ||
| } | ||
| async #executeFunctionAndReleaseMutex(f) { | ||
| log(`Mutex acquired at path '${this.#mutexFilePath}'`); | ||
| #tryAcquire() { | ||
| const lockPath = this.#lockFilePath; | ||
| // Fast path: if the lock file already exists, check staleness directly | ||
| // without creating temp files. This is both an optimization for the | ||
| // common contended case and is required for correct behavior when the | ||
| // parent directory is read-only (stale locks can still be detected via | ||
| // readFileSync even when file creation in the directory is blocked). | ||
| // | ||
| // Note: handleExistingLock() must be called outside the try/catch so | ||
| // that errors like StaleMultiProcessMutexError propagate correctly. | ||
| let lockExists = false; | ||
| try { | ||
| return await f(); | ||
| fs.accessSync(lockPath, fs.constants.F_OK); | ||
| lockExists = true; | ||
| } | ||
| finally { | ||
| // Release the mutex | ||
| // Note: if a process dies, its `finally` block never executes, and the process hangs indefinitely since no response is received. | ||
| // To handle this, we use the function `isMutexProcessOwnerDead`. | ||
| log(`Mutex released at path '${this.#mutexFilePath}'`); | ||
| this.#deleteMutexFile(); | ||
| log(`Mutex released at path '${this.#mutexFilePath}'`); | ||
| catch { | ||
| // Lock doesn't exist (or can't be checked) — proceed to acquire | ||
| } | ||
| } | ||
| #isMutexFileTooOld() { | ||
| let fileStat; | ||
| if (lockExists) { | ||
| return this.#handleExistingLock(); | ||
| } | ||
| // Lock doesn't appear to exist — try to acquire via temp file + hard link | ||
| const metadata = this.#buildMetadata(); | ||
| const contents = JSON.stringify(metadata, null, 2); | ||
| const randomSuffix = Math.random().toString(16).slice(2); | ||
| const tempPath = `${lockPath}.tmp-${process.pid}-${PROCESS_SESSION_ID}-${Date.now()}-${randomSuffix}`; | ||
| let tempFd; | ||
| try { | ||
| fileStat = fs.statSync(this.#mutexFilePath); | ||
| // Create temp file with exclusive flag to prevent collisions | ||
| tempFd = fs.openSync(tempPath, "wx"); | ||
| fs.writeFileSync(tempFd, contents, "utf8"); | ||
| fs.closeSync(tempFd); | ||
| tempFd = undefined; | ||
| // Attempt atomic hard link to the lock path | ||
| fs.linkSync(tempPath, lockPath); | ||
| log(`Acquired lock at ${lockPath}`); | ||
| // Best-effort cleanup of temp files left by dead processes. | ||
| // We hold the lock, so only one process runs this at a time. | ||
| this.#cleanupDeadProcessTempFiles(); | ||
| return { acquired: true }; | ||
| } | ||
| catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "EEXIST") { | ||
| // Lock was created between our accessSync and linkSync | ||
| return this.#handleExistingLock(); | ||
| } | ||
| if (e.code === "ENOENT") { | ||
| // The file might have been deleted by another process while this function was trying to access it. | ||
| return false; | ||
| // Parent directory doesn't exist. Create it and retry. | ||
| const parentDir = path.dirname(lockPath); | ||
| log(`Parent directory ${parentDir} does not exist, creating it`); | ||
| fs.mkdirSync(parentDir, { recursive: true }); | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| // Hard links definitively unsupported — fail fast | ||
| if (HARD_LINK_UNSUPPORTED_CODES.has(e.code ?? "")) { | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } | ||
| // We retry on permission errors, as this is a common transient failure | ||
| // on Windows. | ||
| if (e.code === "EPERM" || e.code === "EACCES") { | ||
| log("Failed to acquire lock, retrying due to permission error"); | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| // Any other error (ENAMETOOLONG, ENOSPC, etc.) | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } | ||
| const now = new Date(); | ||
| const fileDate = new Date(fileStat.ctime); | ||
| const diff = now.getTime() - fileDate.getTime(); | ||
| return diff > this.#mutexLifespanInMs; | ||
| finally { | ||
| // Close fd if still open (write or close failed) | ||
| if (tempFd !== undefined) { | ||
| try { | ||
| fs.closeSync(tempFd); | ||
| } | ||
| catch { | ||
| // Best effort | ||
| } | ||
| } | ||
| // Always clean up the temp file | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } | ||
| catch { | ||
| // Best effort — file may not exist if openSync failed | ||
| } | ||
| } | ||
| } | ||
| #deleteMutexFile() { | ||
| #handleExistingLock() { | ||
| const staleness = this.#checkStaleness(); | ||
| if (staleness.isStale) { | ||
| const reclaimed = this.#tryUnlockingStaleLock(staleness.metadata); | ||
| return { acquired: false, reclaimedStaleLock: reclaimed }; | ||
| } | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| #checkStaleness() { | ||
| const lockPath = this.#lockFilePath; | ||
| const metadata = this.#readMetadata(); | ||
| if (metadata === undefined) { | ||
| log(`Lock at ${lockPath} has missing/corrupt metadata, treating as stale`); | ||
| return { isStale: true, metadata: undefined }; | ||
| } | ||
| // Different hostname — can't verify PID remotely | ||
| if (metadata.hostname !== os.hostname()) { | ||
| throw new IncompatibleHostnameMultiProcessMutexError(lockPath, metadata.hostname, os.hostname()); | ||
| } | ||
| // Different platform — can't verify PID across platforms | ||
| if (metadata.platform !== process.platform) { | ||
| throw new IncompatiblePlatformMultiProcessMutexError(lockPath, metadata.platform, process.platform); | ||
| } | ||
| // Different uid — can't remove a lock owned by another user | ||
| const currentUid = process.getuid?.(); | ||
| if (metadata.uid !== undefined && | ||
| currentUid !== undefined && | ||
| metadata.uid !== currentUid) { | ||
| throw new IncompatibleUidMultiProcessMutexError(lockPath, metadata.uid, currentUid); | ||
| } | ||
| // PID liveness check | ||
| if (!this.#isProcessAlive(metadata.pid)) { | ||
| log(`Lock at ${lockPath} owned by dead process PID=${metadata.pid}`); | ||
| return { isStale: true, metadata }; | ||
| } | ||
| // Process is alive, lock is not stale | ||
| return { isStale: false }; | ||
| } | ||
| #tryUnlockingStaleLock(metadata) { | ||
| const lockPath = this.#lockFilePath; | ||
| try { | ||
| log(`Deleting mutex file at path '${this.#mutexFilePath}'`); | ||
| fs.unlinkSync(this.#mutexFilePath); | ||
| fs.unlinkSync(lockPath); | ||
| log(`Removed stale lock at ${lockPath}`); | ||
| } | ||
@@ -109,29 +332,124 @@ catch (e) { | ||
| if (e.code === "ENOENT") { | ||
| // The file might have been deleted by another process while this function was trying to access it. | ||
| return; | ||
| // Already removed by another process — safe to retry acquisition | ||
| log(`Stale lock at ${lockPath} already removed by another process`); | ||
| return true; | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| if (e.code === "EACCES" || e.code === "EPERM" || e.code === "EBUSY") { | ||
| throw new StaleMultiProcessMutexError(lockPath, metadata?.uid, e); | ||
| } | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } | ||
| // Best-effort cleanup of orphaned temp files from dead processes | ||
| this.#cleanupDeadProcessTempFiles(); | ||
| return true; | ||
| } | ||
| async #isMutexProcessOwnerDead() { | ||
| let mutexPid; | ||
| /** | ||
| * Checks if a process with the given PID is alive using signal 0, which is | ||
| * a platform-independent existence check supported on both POSIX and Windows. | ||
| * | ||
| * `ESRCH` means the process doesn't exist. `EPERM` means it exists but | ||
| * belongs to another user — still alive. | ||
| */ | ||
| #isProcessAlive(pid) { | ||
| try { | ||
| // If the file doesn't exist, it means the owning process deleted it | ||
| mutexPid = await readUtf8File(this.#mutexFilePath); | ||
| process.kill(pid, 0); | ||
| return true; | ||
| } | ||
| catch (_e) { | ||
| return false; | ||
| } | ||
| try { | ||
| process.kill(parseInt(mutexPid, 10), 0); | ||
| } | ||
| catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "ESRCH") { | ||
| // The process owning the mutex no longer exists | ||
| return true; | ||
| return false; // Process does not exist | ||
| } | ||
| // EPERM means the process exists but we don't have permission to signal it | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| #buildMetadata() { | ||
| return { | ||
| pid: process.pid, | ||
| hostname: os.hostname(), | ||
| createdAt: Date.now(), | ||
| ...(process.getuid !== undefined ? { uid: process.getuid() } : {}), | ||
| platform: process.platform, | ||
| sessionId: PROCESS_SESSION_ID, | ||
| }; | ||
| } | ||
| #readMetadata() { | ||
| try { | ||
| const content = fs.readFileSync(this.#lockFilePath, "utf8"); | ||
| const parsed = JSON.parse(content); | ||
| if (typeof parsed !== "object" || | ||
| parsed === null || | ||
| !("pid" in parsed) || | ||
| !("hostname" in parsed) || | ||
| !("createdAt" in parsed) || | ||
| !("platform" in parsed) || | ||
| typeof parsed.pid !== "number" || | ||
| typeof parsed.hostname !== "string" || | ||
| typeof parsed.createdAt !== "number" || | ||
| typeof parsed.platform !== "string" || | ||
| Number.isSafeInteger(parsed.pid) === false || | ||
| parsed.pid < 1 || | ||
| Number.isSafeInteger(parsed.createdAt) === false || | ||
| parsed.createdAt < 1 || | ||
| ("uid" in parsed && | ||
| parsed.uid !== undefined && | ||
| (typeof parsed.uid !== "number" || | ||
| Number.isSafeInteger(parsed.uid) === false)) || | ||
| ("sessionId" in parsed && typeof parsed.sessionId !== "string")) { | ||
| return undefined; | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We just validated it | ||
| return parsed; | ||
| } | ||
| catch { | ||
| // Missing file, corrupt JSON, permission error — all treated as "no valid metadata" | ||
| return undefined; | ||
| } | ||
| } | ||
| /** | ||
| * Best-effort cleanup of orphaned temp files left by dead processes. | ||
| * | ||
| * Scans the parent directory for all temp files matching this lock's naming | ||
| * pattern (`{baseName}.tmp-{pid}-...`), parses the PID from each filename, | ||
| * and removes files whose PID is no longer alive. Files with unparseable | ||
| * PIDs are left untouched (conservative — don't delete what we can't verify). | ||
| * | ||
| * This is safe because the class is single-host-only (cross-host usage | ||
| * throws `IncompatibleHostnameMultiProcessMutexError`). | ||
| */ | ||
| #cleanupDeadProcessTempFiles() { | ||
| const parentDir = path.dirname(this.#lockFilePath); | ||
| const baseName = path.basename(this.#lockFilePath); | ||
| const prefix = `${baseName}.tmp-`; | ||
| try { | ||
| const entries = fs.readdirSync(parentDir); | ||
| for (const entry of entries) { | ||
| if (!entry.startsWith(prefix)) { | ||
| continue; | ||
| } | ||
| // Parse PID from filename: {baseName}.tmp-{pid}-{sessionId}-{ts}-{rand} | ||
| const afterPrefix = entry.slice(prefix.length); | ||
| const pidStr = afterPrefix.split("-")[0]; | ||
| const pid = Number(pidStr); | ||
| if (!Number.isSafeInteger(pid) || pid < 1) { | ||
| // Can't verify liveness — leave file alone | ||
| continue; | ||
| } | ||
| if (this.#isProcessAlive(pid)) { | ||
| continue; | ||
| } | ||
| try { | ||
| fs.unlinkSync(path.join(parentDir, entry)); | ||
| log(`Cleaned up orphaned temp file: ${entry}`); | ||
| } | ||
| catch { | ||
| // Best effort | ||
| } | ||
| } | ||
| } | ||
| catch { | ||
| // Best effort — parent directory may not be readable | ||
| } | ||
| } | ||
| } | ||
@@ -138,0 +456,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"synchronization.js","sourceRoot":"","sources":["../../src/synchronization.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"synchronization.js","sourceRoot":"","sources":["../../src/synchronization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EACL,0BAA0B,EAC1B,0CAA0C,EAC1C,0CAA0C,EAC1C,qCAAqC,EACrC,iCAAiC,EACjC,sBAAsB,EACtB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,OAAO,EACL,0CAA0C,EAC1C,kCAAkC,EAClC,0CAA0C,EAC1C,qCAAqC,EACrC,iCAAiC,EACjC,sBAAsB,EACtB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AAErC,MAAM,GAAG,GAAG,KAAK,CAAC,kCAAkC,CAAC,CAAC;AAEtD,MAAM,kBAAkB,GAAG,UAAU,EAAE,CAAC;AACxC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAC3C,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC;;;GAGG;AACH,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAmBhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,MAAM,OAAO,iBAAiB;IACnB,aAAa,CAAS;IACtB,QAAQ,CAAS;IACjB,oBAAoB,CAAS;IAEtC;;;;;;;;OAQG;IACH,YACE,kBAA0B,EAC1B,OAAgB,EAChB,mBAA4B;QAE5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,iCAAiC,CAAC,kBAAkB,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,kBAAkB,CAAC;QAExC,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,kBAAkB,CAAC;QAC9C,IAAI,CAAC,oBAAoB;YACvB,mBAAmB,IAAI,gCAAgC,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,GAAG,CAAI,CAAmB;QACrC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAErC,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,EAAE,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,OAAO;QAClB,GAAG,CAAC,0CAA0C,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QAErE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,WAAW,CAAC,CAAC,CAAC,CAAC;YAEf,IAAI,CAAC,YAAY,0BAA0B,EAAE,CAAC;gBAC5C,MAAM,CAAC,CAAC;YACV,CAAC;YAED,MAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,KAAK,IAAI,EAAE;YAChB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC;QAE7C,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAElD,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAElC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACpB,OAAO;YACT,CAAC;YAED,gBAAgB;YAChB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACvC,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,6BAA6B,CACrC,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,QAAQ,CACd,CAAC;YACJ,CAAC;YAED,+DAA+D;YAC/D,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAC9B,SAAS;YACX,CAAC;YAED,gCAAgC;YAChC,GAAG,CAAC,WAAW,IAAI,CAAC,aAAa,qBAAqB,YAAY,IAAI,CAAC,CAAC;YACxE,MAAM,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;YAEjC,8BAA8B;YAC9B,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAClC,GAAG,CAAC,oBAAoB,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,6BAA6B,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,GAAG,CAAC,WAAW,IAAI,CAAC,aAAa,kBAAkB,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YACD,MAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,WAAW;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;QAEpC,uEAAuE;QACvE,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,qEAAqE;QACrE,EAAE;QACF,qEAAqE;QACrE,oEAAoE;QACpE,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC3C,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACpC,CAAC;QAED,0EAA0E;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,kBAAkB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;QAEtG,IAAI,MAA0B,CAAC;QAC/B,IAAI,CAAC;YACH,6DAA6D;YAC7D,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3C,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,GAAG,SAAS,CAAC;YAEnB,4CAA4C;YAC5C,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEhC,GAAG,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;YAEpC,4DAA4D;YAC5D,6DAA6D;YAC7D,IAAI,CAAC,4BAA4B,EAAE,CAAC;YAEpC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,6BAA6B,CAAC,CAAC,CAAC,CAAC;YAEjC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,uDAAuD;gBACvD,OAAO,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,CAAC;YAED,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,uDAAuD;gBACvD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACzC,GAAG,CAAC,oBAAoB,SAAS,8BAA8B,CAAC,CAAC;gBACjE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;YACxD,CAAC;YAED,kDAAkD;YAClD,IAAI,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,sBAAsB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;YAED,uEAAuE;YACvE,cAAc;YACd,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9C,GAAG,CAAC,0DAA0D,CAAC,CAAC;gBAChE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;YACxD,CAAC;YAED,+CAA+C;YAC/C,MAAM,IAAI,sBAAsB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACT,iDAAiD;YACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAEzC,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAClE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC;QAC5D,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAED,eAAe;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAEtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,GAAG,CACD,WAAW,QAAQ,kDAAkD,CACtE,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAChD,CAAC;QAED,iDAAiD;QACjD,IAAI,QAAQ,CAAC,QAAQ,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;YACxC,MAAM,IAAI,0CAA0C,CAClD,QAAQ,EACR,QAAQ,CAAC,QAAQ,EACjB,EAAE,CAAC,QAAQ,EAAE,CACd,CAAC;QACJ,CAAC;QAED,yDAAyD;QACzD,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3C,MAAM,IAAI,0CAA0C,CAClD,QAAQ,EACR,QAAQ,CAAC,QAAQ,EACjB,OAAO,CAAC,QAAQ,CACjB,CAAC;QACJ,CAAC;QAED,4DAA4D;QAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,IACE,QAAQ,CAAC,GAAG,KAAK,SAAS;YAC1B,UAAU,KAAK,SAAS;YACxB,QAAQ,CAAC,GAAG,KAAK,UAAU,EAC3B,CAAC;YACD,MAAM,IAAI,qCAAqC,CAC7C,QAAQ,EACR,QAAQ,CAAC,GAAG,EACZ,UAAU,CACX,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,GAAG,CAAC,WAAW,QAAQ,8BAA8B,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;YACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACrC,CAAC;QAED,sCAAsC;QACtC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,sBAAsB,CAAC,QAAkC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;QAEpC,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxB,GAAG,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,6BAA6B,CAAC,CAAC,CAAC,CAAC;YAEjC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,iEAAiE;gBACjE,GAAG,CAAC,iBAAiB,QAAQ,qCAAqC,CAAC,CAAC;gBACpE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACpE,MAAM,IAAI,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,IAAI,sBAAsB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;QAED,iEAAiE;QACjE,IAAI,CAAC,4BAA4B,EAAE,CAAC;QAEpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,eAAe,CAAC,GAAW;QACzB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,6BAA6B,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACvB,OAAO,KAAK,CAAC,CAAC,yBAAyB;YACzC,CAAC;YACD,2EAA2E;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO;YACL,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE;YACvB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,kBAAkB;SAC9B,CAAC;IACJ,CAAC;IAED,aAAa;QACX,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE5C,IACE,OAAO,MAAM,KAAK,QAAQ;gBAC1B,MAAM,KAAK,IAAI;gBACf,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC;gBAClB,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC;gBACvB,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC;gBACxB,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC;gBACvB,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;gBAC9B,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBACnC,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;gBACpC,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBACnC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK;gBAC1C,MAAM,CAAC,GAAG,GAAG,CAAC;gBACd,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK;gBAChD,MAAM,CAAC,SAAS,GAAG,CAAC;gBACpB,CAAC,KAAK,IAAI,MAAM;oBACd,MAAM,CAAC,GAAG,KAAK,SAAS;oBACxB,CAAC,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;wBAC7B,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC;gBAChD,CAAC,WAAW,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,EAC/D,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,iGAAiG;YACjG,OAAO,MAAsB,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,oFAAoF;YACpF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACH,4BAA4B;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,GAAG,QAAQ,OAAO,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBAED,wEAAwE;gBACxE,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;gBAE3B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;oBAC1C,2CAA2C;oBAC3C,SAAS;gBACX,CAAC;gBAED,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;oBAC3C,GAAG,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAC;gBACjD,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACrB,SAAS,GAAG,KAAK,CAAC;IACT,MAAM,GAAsB,EAAE,CAAC;IAExC;;;;;;OAMG;IACI,KAAK,CAAC,YAAY,CACvB,CAAgB;QAEhB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEtC,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,EAAE,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,OAAO,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACvB,IAAI,EAAE,CAAC;gBACT,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,OAAO,CAAsB,CAAC,OAAO,EAAE,EAAE;YAClD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;gBACpB,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"} |
+1
-1
| { | ||
| "name": "@nomicfoundation/hardhat-utils", | ||
| "version": "3.0.6", | ||
| "version": "4.0.0", | ||
| "description": "Utilities for Hardhat and its plugins", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/nomicfoundation/hardhat/tree/v-next/v-next/hardhat-utils", |
+11
-94
@@ -12,86 +12,3 @@ import { | ||
| export type TableRow = string[]; | ||
| export interface TableDivider { | ||
| type: "divider"; | ||
| } | ||
| export type TableItem = TableRow | TableDivider; | ||
| export const divider: TableDivider = { type: "divider" }; | ||
| /** | ||
| * Formats an array of rows and dividers into a table string. | ||
| * | ||
| * @param items An array of table rows (string arrays) and dividers. | ||
| * Dividers are objects with type: "divider" and will be rendered as table dividers. | ||
| * @returns The formatted table as a string, ready to be rendered. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * formatTable([ | ||
| * ["Name", "Age"], | ||
| * divider, | ||
| * ["Alice", "30"], | ||
| * ["Bob", "25"], | ||
| * divider, | ||
| * ["Average", "27.5"] | ||
| * ]); | ||
| * | ||
| * // => | ||
| * // | Name | Age | | ||
| * // | ------- | ---- | | ||
| * // | Alice | 30 | | ||
| * // | Bob | 25 | | ||
| * // | ------- | ---- | | ||
| * // | Average | 27.5 | | ||
| * ``` | ||
| */ | ||
| export function formatTable(items: TableItem[]): string { | ||
| const widths: number[] = []; | ||
| const dataRows: string[][] = []; | ||
| for (const item of items) { | ||
| if (Array.isArray(item)) { | ||
| dataRows.push([...item]); | ||
| } | ||
| } | ||
| // Calculate maximum width for each column | ||
| for (const row of dataRows) { | ||
| for (let i = 0; i < row.length; i++) { | ||
| while (i >= widths.length) { | ||
| widths.push(0); | ||
| } | ||
| widths[i] = Math.max(widths[i], getStringWidth(row[i])); | ||
| } | ||
| } | ||
| const dividerRow = widths.map((width) => "-".repeat(width)); | ||
| const outputRows: string[][] = []; | ||
| for (const item of items) { | ||
| if (Array.isArray(item)) { | ||
| const row = [...item]; | ||
| // Pad the row to match the number of columns | ||
| while (row.length < widths.length) { | ||
| row.push(""); | ||
| } | ||
| outputRows.push(row); | ||
| } else { | ||
| outputRows.push([...dividerRow]); | ||
| } | ||
| } | ||
| outputRows.forEach((row) => { | ||
| for (let i = 0; i < row.length; i++) { | ||
| const displayWidth = getStringWidth(row[i]); | ||
| const actualLength = row[i].length; | ||
| // Adjust padding to account for difference between display width and actual length | ||
| row[i] = row[i].padEnd(widths[i] + actualLength - displayWidth); | ||
| } | ||
| }); | ||
| return outputRows.map((row) => `| ${row.join(" | ")} |`).join("\n"); | ||
| } | ||
| export interface TableTitleV2 { | ||
| export interface TableTitle { | ||
| type: "title"; | ||
@@ -101,3 +18,3 @@ text: string; | ||
| export interface TableSectionHeaderV2 { | ||
| export interface TableSectionHeader { | ||
| type: "section-header"; | ||
@@ -107,3 +24,3 @@ text: string; | ||
| export interface TableHeaderV2 { | ||
| export interface TableHeader { | ||
| type: "header"; | ||
@@ -113,3 +30,3 @@ cells: string[]; | ||
| export interface TableRowV2 { | ||
| export interface TableRow { | ||
| type: "row"; | ||
@@ -119,7 +36,7 @@ cells: string[]; | ||
| export type TableItemV2 = | ||
| | TableTitleV2 | ||
| | TableSectionHeaderV2 | ||
| | TableHeaderV2 | ||
| | TableRowV2; | ||
| export type TableItem = | ||
| | TableTitle | ||
| | TableSectionHeader | ||
| | TableHeader | ||
| | TableRow; | ||
@@ -143,3 +60,3 @@ /** | ||
| * ```ts | ||
| * formatTableV2([ | ||
| * formatTable([ | ||
| * { type: "title", text: "My Table" }, | ||
@@ -177,3 +94,3 @@ * { type: "section-header", text: "User Data" }, | ||
| */ | ||
| export function formatTableV2(items: TableItemV2[]): string { | ||
| export function formatTable(items: TableItem[]): string { | ||
| if (items.length === 0) { | ||
@@ -180,0 +97,0 @@ return ""; |
+31
-0
| import { ensureDir } from "./fs.js"; | ||
| import { generatePaths, HARDHAT_PACKAGE_NAME } from "./internal/global-dir.js"; | ||
| // Internal override for testing purposes | ||
| let _cacheDirOverride: string | undefined; | ||
| /** | ||
| * 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: string): void { | ||
| _cacheDirOverride = dir; | ||
| } | ||
| /** | ||
| * Resets the mock cache directory set by setMockCacheDir. | ||
| * Call this in test cleanup to restore normal behavior. | ||
| */ | ||
| export function resetMockCacheDir(): void { | ||
| _cacheDirOverride = undefined; | ||
| } | ||
| /** | ||
| * Returns the configuration directory path for a given package (defaults to "hardhat"). | ||
@@ -24,2 +45,6 @@ * 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. | ||
@@ -32,2 +57,8 @@ * @returns The path to the hardhat cache directory. | ||
| ): Promise<string> { | ||
| // Allow override for testing purposes | ||
| if (_cacheDirOverride !== undefined) { | ||
| await ensureDir(_cacheDirOverride); | ||
| return _cacheDirOverride; | ||
| } | ||
| const { cache } = await generatePaths(packageName); | ||
@@ -34,0 +65,0 @@ await ensureDir(cache); |
@@ -1,2 +0,2 @@ | ||
| import type { TableItemV2 } from "../format.js"; | ||
| import type { TableItem } from "../format.js"; | ||
@@ -20,3 +20,3 @@ /** | ||
| */ | ||
| export function getColumnWidths(items: TableItemV2[]): number[] { | ||
| export function getColumnWidths(items: TableItem[]): number[] { | ||
| const columnWidths: number[] = []; | ||
@@ -57,3 +57,3 @@ | ||
| */ | ||
| export function getHeadingWidth(items: TableItemV2[]): number { | ||
| export function getHeadingWidth(items: TableItem[]): number { | ||
| let headingWidth = 0; | ||
@@ -60,0 +60,0 @@ for (const item of items) { |
@@ -5,2 +5,3 @@ import type { DispatcherOptions, RequestOptions } from "../request.js"; | ||
| import crypto from "node:crypto"; | ||
| import path from "node:path"; | ||
@@ -28,3 +29,3 @@ | ||
| ext, | ||
| name: `tmp-${name}`, | ||
| name: `tmp-${name}-${crypto.randomBytes(8).toString("hex")}`, | ||
| }); | ||
@@ -31,0 +32,0 @@ } |
+29
-6
| import type EventEmitter from "node:events"; | ||
| import type { FileHandle } from "node:fs/promises"; | ||
| import type { ParsedUrlQueryInput } from "node:querystring"; | ||
| import type UndiciT from "undici"; | ||
| import fs from "node:fs"; | ||
| import { open } from "node:fs/promises"; | ||
| import querystring from "node:querystring"; | ||
@@ -15,3 +16,3 @@ import stream from "node:stream/promises"; | ||
| } from "./errors/request.js"; | ||
| import { move } from "./fs.js"; | ||
| import { move, remove } from "./fs.js"; | ||
| import { | ||
@@ -221,2 +222,3 @@ generateTempFilePath, | ||
| let statusCode: number | undefined; | ||
| let tempFilePath: string | undefined; | ||
@@ -226,3 +228,3 @@ try { | ||
| -- We need the full Dispatcher.ResponseData here for stream.pipeline, | ||
| but HttpResponse doesn’t expose the raw ReadableStream. | ||
| but HttpResponse doesn't expose the raw ReadableStream. | ||
| TODO: wrap undici's request so we can keep the public API | ||
@@ -242,5 +244,18 @@ strictly typed without falling back to Undici types. */ | ||
| const tempFilePath = await generateTempFilePath(destination); | ||
| const fileStream = fs.createWriteStream(tempFilePath); | ||
| await stream.pipeline(body, fileStream); | ||
| tempFilePath = await generateTempFilePath(destination); | ||
| let fileHandle: FileHandle | undefined; | ||
| try { | ||
| fileHandle = await open(tempFilePath, "w"); | ||
| const fileStream = fileHandle.createWriteStream(); | ||
| await stream.pipeline(body, fileStream); | ||
| } 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(); | ||
| } | ||
| await move(tempFilePath, destination); | ||
@@ -250,2 +265,10 @@ } catch (e) { | ||
| if (tempFilePath !== undefined) { | ||
| try { | ||
| await remove(tempFilePath); | ||
| } catch { | ||
| // Best-effort: file may not exist or may have already been moved | ||
| } | ||
| } | ||
| handleError(e, url); | ||
@@ -252,0 +275,0 @@ |
+504
-95
@@ -1,75 +0,314 @@ | ||
| // Logic explanation: the fs.writeFile function, when used with the wx+ flag, performs an atomic operation to create a file. | ||
| // If multiple processes try to create the same file simultaneously, only one will succeed. | ||
| // This logic can be utilized to implement a mutex. | ||
| // ATTENTION: in the current implementation, there's still a risk of two processes running simultaneously. | ||
| // For example, if processA has locked the mutex and is running, processB will wait. | ||
| // During this wait, processB continuously checks the elapsed time since the mutex lock file was created. | ||
| // If an excessive amount of time has passed, processB will assume ownership of the mutex to prevent stale locks, even if processA is still running. | ||
| // As a result, two processes will be running simultaneously in what is theoretically a mutex-locked section. | ||
| import { randomUUID } from "node:crypto"; | ||
| import * as fs from "node:fs"; | ||
| import * as os from "node:os"; | ||
| import * as path from "node:path"; | ||
| import fs from "node:fs"; | ||
| import os from "node:os"; | ||
| import path from "node:path"; | ||
| import debug from "debug"; | ||
| import { ensureNodeErrnoExceptionError } from "./error.js"; | ||
| import { FileSystemAccessError } from "./errors/fs.js"; | ||
| import { readUtf8File } from "./fs.js"; | ||
| import { ensureError, ensureNodeErrnoExceptionError } from "./error.js"; | ||
| import { | ||
| BaseMultiProcessMutexError, | ||
| IncompatibleHostnameMultiProcessMutexError, | ||
| IncompatiblePlatformMultiProcessMutexError, | ||
| IncompatibleUidMultiProcessMutexError, | ||
| InvalidMultiProcessMutexPathError, | ||
| MultiProcessMutexError, | ||
| MultiProcessMutexTimeoutError, | ||
| StaleMultiProcessMutexError, | ||
| } from "./errors/synchronization.js"; | ||
| import { ensureDir } from "./fs.js"; | ||
| import { sleep } from "./lang.js"; | ||
| export { | ||
| IncompatibleHostnameMultiProcessMutexError, | ||
| IncompatibleMultiProcessMutexError, | ||
| IncompatiblePlatformMultiProcessMutexError, | ||
| IncompatibleUidMultiProcessMutexError, | ||
| InvalidMultiProcessMutexPathError, | ||
| MultiProcessMutexError, | ||
| MultiProcessMutexTimeoutError, | ||
| StaleMultiProcessMutexError, | ||
| } from "./errors/synchronization.js"; | ||
| const log = debug("hardhat:util:multi-process-mutex"); | ||
| const DEFAULT_MAX_MUTEX_LIFESPAN_IN_MS = 60000; | ||
| const MUTEX_LOOP_WAITING_TIME_IN_MS = 100; | ||
| const PROCESS_SESSION_ID = randomUUID(); | ||
| const DEFAULT_TIMEOUT_MS = 60_000; | ||
| const DEFAULT_INITIAL_POLL_INTERVAL_MS = 5; | ||
| const MAX_POLL_INTERVAL_MS = 200; | ||
| /** | ||
| * Error codes indicating hard links are definitively unsupported on the | ||
| * target filesystem. These cause immediate failure rather than retries. | ||
| */ | ||
| const HARD_LINK_UNSUPPORTED_CODES = new Set(["EOPNOTSUPP", "ENOTSUP", "EXDEV"]); | ||
| interface LockMetadata { | ||
| pid: number; | ||
| hostname: string; | ||
| createdAt: number; | ||
| uid?: number; | ||
| platform: string; | ||
| sessionId: string; | ||
| } | ||
| type StalenessResult = | ||
| | { isStale: true; metadata: LockMetadata | undefined } | ||
| | { isStale: false }; | ||
| type AcquireResult = | ||
| | { acquired: true } | ||
| | { acquired: false; reclaimedStaleLock: boolean }; | ||
| /** | ||
| * A class that implements an inter-process mutex. | ||
| * | ||
| * This Mutex is implemented using hard-link-based atomic file creation. A | ||
| * temporary file containing JSON metadata (PID, hostname, platform, uid, | ||
| * session ID, and creation timestamp) is written first, then hard-linked to | ||
| * the lock path via `fs.linkSync`. `linkSync` fails atomically with `EEXIST` | ||
| * if the lock already exists, ensuring only one process can hold the lock at | ||
| * a time. | ||
| * | ||
| * Staleness is determined by PID liveness only — timestamps are stored for | ||
| * debugging purposes but are never used to determine staleness. This avoids the | ||
| * clock-skew and long-running-task problems that time-based staleness detection | ||
| * has (where a second process can break into a lock that's still legitimately | ||
| * held). | ||
| * | ||
| * Incompatible locks — those created by a different hostname, platform, or | ||
| * uid — are rejected immediately with specific subclasses of | ||
| * `IncompatibleMultiProcessMutexError` | ||
| * (`IncompatibleHostnameMultiProcessMutexError`, | ||
| * `IncompatiblePlatformMultiProcessMutexError`, or | ||
| * `IncompatibleUidMultiProcessMutexError`) because their PID liveness cannot | ||
| * be verified or their lock file cannot be removed. These must be removed | ||
| * manually. | ||
| * | ||
| * When the lock is held by a live process, the caller polls with exponential | ||
| * backoff (default: 5ms → 10ms → ... → 160ms → 200ms cap) until the lock is | ||
| * released or a timeout (default: 60s) is reached. | ||
| * | ||
| * If the filesystem does not support hard links (e.g., certain network | ||
| * filesystems), acquisition fails fast with a `MultiProcessMutexError` rather | ||
| * than degrading into timeout-based retries. | ||
| * | ||
| * ## Performance characteristics | ||
| * | ||
| * - **Uncontended acquisition:** One temp file write + one `linkSync` — takes | ||
| * less than 1ms on most systems. | ||
| * - **Stale lock recovery:** One `readFileSync` to read metadata, one | ||
| * `process.kill(pid, 0)` liveness check, and one `unlinkSync` to remove the | ||
| * stale lock file before retrying acquisition. The retry is immediate (no | ||
| * sleep), so recovery adds sub-millisecond overhead. | ||
| * - **Contended (live holder):** Polls with exponential backoff starting at | ||
| * 5ms and doubling each iteration until capped at 200ms. Worst-case latency | ||
| * after the lock is released is up to `MAX_POLL_INTERVAL_MS` (200ms). | ||
| * - **Release:** A single `unlinkSync` call. | ||
| * | ||
| * ## Limitations | ||
| * | ||
| * - **Polling-based:** There is no filesystem notification; callers discover | ||
| * that the lock is free only on the next poll, so there can be up to 200ms | ||
| * of wasted wait time after the lock is released. | ||
| * - **Not reentrant:** The same process (or even the same `MultiProcessMutex` | ||
| * instance) calling `use()` while already holding the lock will deadlock | ||
| * until the timeout fires. | ||
| * - **Single-host, single-user only:** Encountering a lock from a different | ||
| * hostname throws `IncompatibleHostnameMultiProcessMutexError`, a different | ||
| * platform throws `IncompatiblePlatformMultiProcessMutexError`, and a | ||
| * different uid throws `IncompatibleUidMultiProcessMutexError`. All extend | ||
| * `IncompatibleMultiProcessMutexError`. This means the lock is not safe to | ||
| * use on shared/networked filesystems (e.g., NFS) where multiple hosts or | ||
| * users may access the same path. | ||
| * - **Requires hard-link support:** The underlying filesystem must support | ||
| * `linkSync`. If hard links are unsupported, acquisition fails immediately | ||
| * with `MultiProcessMutexError`. | ||
| * - **PID recycling:** If a process dies and the OS reassigns its PID to a new | ||
| * unrelated process before the stale check runs, the lock is incorrectly | ||
| * considered live. This is extremely unlikely in practice due to the large | ||
| * PID space on modern systems. | ||
| * - **No fairness guarantee:** Multiple waiters polling concurrently have no | ||
| * guaranteed ordering — whichever one succeeds at `linkSync` first after the | ||
| * lock is released wins. | ||
| */ | ||
| export class MultiProcessMutex { | ||
| readonly #mutexFilePath: string; | ||
| readonly #mutexLifespanInMs: number; | ||
| readonly #lockFilePath: string; | ||
| readonly #timeout: number; | ||
| readonly #initialPollInterval: number; | ||
| constructor(mutexName: string, maxMutexLifespanInMs?: number) { | ||
| log(`Creating mutex with name '${mutexName}'`); | ||
| /** | ||
| * Creates an inter-process mutex given an absolute path. | ||
| * | ||
| * @param absolutePathToLock The absolute path of the mutex. | ||
| * @param timeout The max amount of time to spend trying to acquire the lock | ||
| * in milliseconds. Defaults to 60000. | ||
| * @param initialPollInterval The initial poll interval in milliseconds. | ||
| * Defaults to 5. | ||
| */ | ||
| constructor( | ||
| absolutePathToLock: string, | ||
| timeout?: number, | ||
| initialPollInterval?: number, | ||
| ) { | ||
| if (!path.isAbsolute(absolutePathToLock)) { | ||
| throw new InvalidMultiProcessMutexPathError(absolutePathToLock); | ||
| } | ||
| this.#lockFilePath = absolutePathToLock; | ||
| this.#mutexFilePath = path.join(os.tmpdir(), `${mutexName}.txt`); | ||
| this.#mutexLifespanInMs = | ||
| maxMutexLifespanInMs ?? DEFAULT_MAX_MUTEX_LIFESPAN_IN_MS; | ||
| this.#timeout = timeout ?? DEFAULT_TIMEOUT_MS; | ||
| this.#initialPollInterval = | ||
| initialPollInterval ?? DEFAULT_INITIAL_POLL_INTERVAL_MS; | ||
| } | ||
| /** | ||
| * Runs the function f while holding the mutex, returning its result. | ||
| * | ||
| * @param f The function to run. | ||
| * @returns The result of the function. | ||
| */ | ||
| public async use<T>(f: () => Promise<T>): Promise<T> { | ||
| log(`Starting mutex process with mutex file '${this.#mutexFilePath}'`); | ||
| const release = await this.acquire(); | ||
| try { | ||
| return await f(); | ||
| } finally { | ||
| await release(); | ||
| } | ||
| } | ||
| /** | ||
| * Acquires the mutex, returning an async function to release it. | ||
| * The function MUST be called after using the mutex. | ||
| * | ||
| * If this function throws, no cleanup is necessary — the lock was never | ||
| * acquired. | ||
| * | ||
| * @returns The mutex's release function. | ||
| */ | ||
| public async acquire(): Promise<() => Promise<void>> { | ||
| log(`Starting mutex process with lock file '${this.#lockFilePath}'`); | ||
| try { | ||
| await this.#acquireLock(); | ||
| } catch (e) { | ||
| ensureError(e); | ||
| if (e instanceof BaseMultiProcessMutexError) { | ||
| throw e; | ||
| } | ||
| throw new MultiProcessMutexError(this.#lockFilePath, e); | ||
| } | ||
| let released = false; | ||
| return async () => { | ||
| if (released) { | ||
| return; | ||
| } | ||
| this.#releaseLock(); | ||
| released = true; | ||
| }; | ||
| } | ||
| async #acquireLock(): Promise<void> { | ||
| const startTime = Date.now(); | ||
| let pollInterval = this.#initialPollInterval; | ||
| await ensureDir(path.dirname(this.#lockFilePath)); | ||
| while (true) { | ||
| if (await this.#tryToAcquireMutex()) { | ||
| // Mutex has been acquired | ||
| return this.#executeFunctionAndReleaseMutex(f); | ||
| const result = this.#tryAcquire(); | ||
| if (result.acquired) { | ||
| return; | ||
| } | ||
| // Mutex not acquired | ||
| if (this.#isMutexFileTooOld()) { | ||
| // If the mutex file is too old, it likely indicates a stale lock, so the file should be removed | ||
| log( | ||
| `Current mutex file is too old, removing it at path '${this.#mutexFilePath}'`, | ||
| // Check timeout | ||
| const elapsed = Date.now() - startTime; | ||
| if (elapsed >= this.#timeout) { | ||
| throw new MultiProcessMutexTimeoutError( | ||
| this.#lockFilePath, | ||
| this.#timeout, | ||
| ); | ||
| } | ||
| this.#deleteMutexFile(); | ||
| } else if (await this.#isMutexProcessOwnerDead()) { | ||
| log( | ||
| `The process owning the mutex file no longer exists. Removing mutex file at '${this.#mutexFilePath}'.`, | ||
| ); | ||
| // Skip sleep after reclaiming a stale lock — retry immediately | ||
| if (result.reclaimedStaleLock) { | ||
| continue; | ||
| } | ||
| this.#deleteMutexFile(); | ||
| } else { | ||
| // wait | ||
| await sleep(MUTEX_LOOP_WAITING_TIME_IN_MS / 1000); | ||
| // Wait with exponential backoff | ||
| log(`Lock at ${this.#lockFilePath} is busy, waiting ${pollInterval}ms`); | ||
| await sleep(pollInterval / 1000); | ||
| // Exponential backoff, capped | ||
| pollInterval = Math.min(pollInterval * 2, MAX_POLL_INTERVAL_MS); | ||
| } | ||
| } | ||
| #releaseLock(): void { | ||
| try { | ||
| fs.unlinkSync(this.#lockFilePath); | ||
| log(`Released lock at ${this.#lockFilePath}`); | ||
| } catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "ENOENT") { | ||
| log(`Lock at ${this.#lockFilePath} already removed`); | ||
| return; | ||
| } | ||
| throw new MultiProcessMutexError(this.#lockFilePath, e); | ||
| } | ||
| } | ||
| async #tryToAcquireMutex() { | ||
| #tryAcquire(): AcquireResult { | ||
| const lockPath = this.#lockFilePath; | ||
| // Fast path: if the lock file already exists, check staleness directly | ||
| // without creating temp files. This is both an optimization for the | ||
| // common contended case and is required for correct behavior when the | ||
| // parent directory is read-only (stale locks can still be detected via | ||
| // readFileSync even when file creation in the directory is blocked). | ||
| // | ||
| // Note: handleExistingLock() must be called outside the try/catch so | ||
| // that errors like StaleMultiProcessMutexError propagate correctly. | ||
| let lockExists = false; | ||
| try { | ||
| // Create a file only if it does not exist | ||
| fs.writeFileSync(this.#mutexFilePath, process.pid.toString(), { | ||
| flag: "wx+", | ||
| }); | ||
| fs.accessSync(lockPath, fs.constants.F_OK); | ||
| lockExists = true; | ||
| } catch { | ||
| // Lock doesn't exist (or can't be checked) — proceed to acquire | ||
| } | ||
| return true; | ||
| if (lockExists) { | ||
| return this.#handleExistingLock(); | ||
| } | ||
| // Lock doesn't appear to exist — try to acquire via temp file + hard link | ||
| const metadata = this.#buildMetadata(); | ||
| const contents = JSON.stringify(metadata, null, 2); | ||
| const randomSuffix = Math.random().toString(16).slice(2); | ||
| const tempPath = `${lockPath}.tmp-${process.pid}-${PROCESS_SESSION_ID}-${Date.now()}-${randomSuffix}`; | ||
| let tempFd: number | undefined; | ||
| try { | ||
| // Create temp file with exclusive flag to prevent collisions | ||
| tempFd = fs.openSync(tempPath, "wx"); | ||
| fs.writeFileSync(tempFd, contents, "utf8"); | ||
| fs.closeSync(tempFd); | ||
| tempFd = undefined; | ||
| // Attempt atomic hard link to the lock path | ||
| fs.linkSync(tempPath, lockPath); | ||
| log(`Acquired lock at ${lockPath}`); | ||
| // Best-effort cleanup of temp files left by dead processes. | ||
| // We hold the lock, so only one process runs this at a time. | ||
| this.#cleanupDeadProcessTempFiles(); | ||
| return { acquired: true }; | ||
| } catch (e) { | ||
@@ -79,29 +318,117 @@ ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "EEXIST") { | ||
| // File already exists, so the mutex is already acquired | ||
| return false; | ||
| // Lock was created between our accessSync and linkSync | ||
| return this.#handleExistingLock(); | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| if (e.code === "ENOENT") { | ||
| // Parent directory doesn't exist. Create it and retry. | ||
| const parentDir = path.dirname(lockPath); | ||
| log(`Parent directory ${parentDir} does not exist, creating it`); | ||
| fs.mkdirSync(parentDir, { recursive: true }); | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| // Hard links definitively unsupported — fail fast | ||
| if (HARD_LINK_UNSUPPORTED_CODES.has(e.code ?? "")) { | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } | ||
| // We retry on permission errors, as this is a common transient failure | ||
| // on Windows. | ||
| if (e.code === "EPERM" || e.code === "EACCES") { | ||
| log("Failed to acquire lock, retrying due to permission error"); | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| // Any other error (ENAMETOOLONG, ENOSPC, etc.) | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } finally { | ||
| // Close fd if still open (write or close failed) | ||
| if (tempFd !== undefined) { | ||
| try { | ||
| fs.closeSync(tempFd); | ||
| } catch { | ||
| // Best effort | ||
| } | ||
| } | ||
| // Always clean up the temp file | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } catch { | ||
| // Best effort — file may not exist if openSync failed | ||
| } | ||
| } | ||
| } | ||
| async #executeFunctionAndReleaseMutex<T>(f: () => Promise<T>): Promise<T> { | ||
| log(`Mutex acquired at path '${this.#mutexFilePath}'`); | ||
| #handleExistingLock(): AcquireResult { | ||
| const staleness = this.#checkStaleness(); | ||
| try { | ||
| return await f(); | ||
| } finally { | ||
| // Release the mutex | ||
| // Note: if a process dies, its `finally` block never executes, and the process hangs indefinitely since no response is received. | ||
| // To handle this, we use the function `isMutexProcessOwnerDead`. | ||
| log(`Mutex released at path '${this.#mutexFilePath}'`); | ||
| this.#deleteMutexFile(); | ||
| log(`Mutex released at path '${this.#mutexFilePath}'`); | ||
| if (staleness.isStale) { | ||
| const reclaimed = this.#tryUnlockingStaleLock(staleness.metadata); | ||
| return { acquired: false, reclaimedStaleLock: reclaimed }; | ||
| } | ||
| return { acquired: false, reclaimedStaleLock: false }; | ||
| } | ||
| #isMutexFileTooOld(): boolean { | ||
| let fileStat; | ||
| #checkStaleness(): StalenessResult { | ||
| const lockPath = this.#lockFilePath; | ||
| const metadata = this.#readMetadata(); | ||
| if (metadata === undefined) { | ||
| log( | ||
| `Lock at ${lockPath} has missing/corrupt metadata, treating as stale`, | ||
| ); | ||
| return { isStale: true, metadata: undefined }; | ||
| } | ||
| // Different hostname — can't verify PID remotely | ||
| if (metadata.hostname !== os.hostname()) { | ||
| throw new IncompatibleHostnameMultiProcessMutexError( | ||
| lockPath, | ||
| metadata.hostname, | ||
| os.hostname(), | ||
| ); | ||
| } | ||
| // Different platform — can't verify PID across platforms | ||
| if (metadata.platform !== process.platform) { | ||
| throw new IncompatiblePlatformMultiProcessMutexError( | ||
| lockPath, | ||
| metadata.platform, | ||
| process.platform, | ||
| ); | ||
| } | ||
| // Different uid — can't remove a lock owned by another user | ||
| const currentUid = process.getuid?.(); | ||
| if ( | ||
| metadata.uid !== undefined && | ||
| currentUid !== undefined && | ||
| metadata.uid !== currentUid | ||
| ) { | ||
| throw new IncompatibleUidMultiProcessMutexError( | ||
| lockPath, | ||
| metadata.uid, | ||
| currentUid, | ||
| ); | ||
| } | ||
| // PID liveness check | ||
| if (!this.#isProcessAlive(metadata.pid)) { | ||
| log(`Lock at ${lockPath} owned by dead process PID=${metadata.pid}`); | ||
| return { isStale: true, metadata }; | ||
| } | ||
| // Process is alive, lock is not stale | ||
| return { isStale: false }; | ||
| } | ||
| #tryUnlockingStaleLock(metadata: LockMetadata | undefined): boolean { | ||
| const lockPath = this.#lockFilePath; | ||
| try { | ||
| fileStat = fs.statSync(this.#mutexFilePath); | ||
| fs.unlinkSync(lockPath); | ||
| log(`Removed stale lock at ${lockPath}`); | ||
| } catch (e) { | ||
@@ -111,54 +438,136 @@ ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "ENOENT") { | ||
| // The file might have been deleted by another process while this function was trying to access it. | ||
| return false; | ||
| // Already removed by another process — safe to retry acquisition | ||
| log(`Stale lock at ${lockPath} already removed by another process`); | ||
| return true; | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| if (e.code === "EACCES" || e.code === "EPERM" || e.code === "EBUSY") { | ||
| throw new StaleMultiProcessMutexError(lockPath, metadata?.uid, e); | ||
| } | ||
| throw new MultiProcessMutexError(lockPath, e); | ||
| } | ||
| const now = new Date(); | ||
| const fileDate = new Date(fileStat.ctime); | ||
| const diff = now.getTime() - fileDate.getTime(); | ||
| // Best-effort cleanup of orphaned temp files from dead processes | ||
| this.#cleanupDeadProcessTempFiles(); | ||
| return diff > this.#mutexLifespanInMs; | ||
| return true; | ||
| } | ||
| #deleteMutexFile() { | ||
| /** | ||
| * Checks if a process with the given PID is alive using signal 0, which is | ||
| * a platform-independent existence check supported on both POSIX and Windows. | ||
| * | ||
| * `ESRCH` means the process doesn't exist. `EPERM` means it exists but | ||
| * belongs to another user — still alive. | ||
| */ | ||
| #isProcessAlive(pid: number): boolean { | ||
| try { | ||
| log(`Deleting mutex file at path '${this.#mutexFilePath}'`); | ||
| fs.unlinkSync(this.#mutexFilePath); | ||
| process.kill(pid, 0); | ||
| return true; | ||
| } catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| if (e.code === "ENOENT") { | ||
| // The file might have been deleted by another process while this function was trying to access it. | ||
| return; | ||
| if (e.code === "ESRCH") { | ||
| return false; // Process does not exist | ||
| } | ||
| throw new FileSystemAccessError(e.message, e); | ||
| // EPERM means the process exists but we don't have permission to signal it | ||
| return true; | ||
| } | ||
| } | ||
| async #isMutexProcessOwnerDead(): Promise<boolean> { | ||
| let mutexPid: string; | ||
| #buildMetadata(): LockMetadata { | ||
| return { | ||
| pid: process.pid, | ||
| hostname: os.hostname(), | ||
| createdAt: Date.now(), | ||
| ...(process.getuid !== undefined ? { uid: process.getuid() } : {}), | ||
| platform: process.platform, | ||
| sessionId: PROCESS_SESSION_ID, | ||
| }; | ||
| } | ||
| #readMetadata(): LockMetadata | undefined { | ||
| try { | ||
| // If the file doesn't exist, it means the owning process deleted it | ||
| mutexPid = await readUtf8File(this.#mutexFilePath); | ||
| } catch (_e) { | ||
| return false; | ||
| const content = fs.readFileSync(this.#lockFilePath, "utf8"); | ||
| const parsed: unknown = JSON.parse(content); | ||
| if ( | ||
| typeof parsed !== "object" || | ||
| parsed === null || | ||
| !("pid" in parsed) || | ||
| !("hostname" in parsed) || | ||
| !("createdAt" in parsed) || | ||
| !("platform" in parsed) || | ||
| typeof parsed.pid !== "number" || | ||
| typeof parsed.hostname !== "string" || | ||
| typeof parsed.createdAt !== "number" || | ||
| typeof parsed.platform !== "string" || | ||
| Number.isSafeInteger(parsed.pid) === false || | ||
| parsed.pid < 1 || | ||
| Number.isSafeInteger(parsed.createdAt) === false || | ||
| parsed.createdAt < 1 || | ||
| ("uid" in parsed && | ||
| parsed.uid !== undefined && | ||
| (typeof parsed.uid !== "number" || | ||
| Number.isSafeInteger(parsed.uid) === false)) || | ||
| ("sessionId" in parsed && typeof parsed.sessionId !== "string") | ||
| ) { | ||
| return undefined; | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We just validated it | ||
| return parsed as LockMetadata; | ||
| } catch { | ||
| // Missing file, corrupt JSON, permission error — all treated as "no valid metadata" | ||
| return undefined; | ||
| } | ||
| } | ||
| /** | ||
| * Best-effort cleanup of orphaned temp files left by dead processes. | ||
| * | ||
| * Scans the parent directory for all temp files matching this lock's naming | ||
| * pattern (`{baseName}.tmp-{pid}-...`), parses the PID from each filename, | ||
| * and removes files whose PID is no longer alive. Files with unparseable | ||
| * PIDs are left untouched (conservative — don't delete what we can't verify). | ||
| * | ||
| * This is safe because the class is single-host-only (cross-host usage | ||
| * throws `IncompatibleHostnameMultiProcessMutexError`). | ||
| */ | ||
| #cleanupDeadProcessTempFiles(): void { | ||
| const parentDir = path.dirname(this.#lockFilePath); | ||
| const baseName = path.basename(this.#lockFilePath); | ||
| const prefix = `${baseName}.tmp-`; | ||
| try { | ||
| process.kill(parseInt(mutexPid, 10), 0); | ||
| } catch (e) { | ||
| ensureNodeErrnoExceptionError(e); | ||
| const entries = fs.readdirSync(parentDir); | ||
| for (const entry of entries) { | ||
| if (!entry.startsWith(prefix)) { | ||
| continue; | ||
| } | ||
| if (e.code === "ESRCH") { | ||
| // The process owning the mutex no longer exists | ||
| return true; | ||
| // Parse PID from filename: {baseName}.tmp-{pid}-{sessionId}-{ts}-{rand} | ||
| const afterPrefix = entry.slice(prefix.length); | ||
| const pidStr = afterPrefix.split("-")[0]; | ||
| const pid = Number(pidStr); | ||
| if (!Number.isSafeInteger(pid) || pid < 1) { | ||
| // Can't verify liveness — leave file alone | ||
| continue; | ||
| } | ||
| if (this.#isProcessAlive(pid)) { | ||
| continue; | ||
| } | ||
| try { | ||
| fs.unlinkSync(path.join(parentDir, entry)); | ||
| log(`Cleaned up orphaned temp file: ${entry}`); | ||
| } catch { | ||
| // Best effort | ||
| } | ||
| } | ||
| } catch { | ||
| // Best effort — parent directory may not be readable | ||
| } | ||
| return false; | ||
| } | ||
@@ -165,0 +574,0 @@ } |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
492006
10.69%209
2.45%9604
9.77%52
18.18%