@nomicfoundation/hardhat-utils 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @nomicfoundation/hardhat-utils
2
2
 
3
+ ## 3.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d821a0a: Fix npm artifact cleanup on windows ([#7459](https://github.com/NomicFoundation/hardhat/issues/7459))
8
+ - b13620a: Add compilation progress spinner to show build progress ([#7460](https://github.com/NomicFoundation/hardhat/pull/7460))
9
+
10
+ ## 3.0.2
11
+
12
+ ### Patch Changes
13
+
14
+ - 8c1cb1e: Fixed peer dependencies for Hardhat so `rpc` utils can be loaded ([#7415](https://github.com/NomicFoundation/hardhat/issues/7415))
15
+
3
16
  ## 3.0.1
4
17
 
5
18
  ### Patch Changes
@@ -0,0 +1,46 @@
1
+ export declare const FRAME_INTERVAL_MS = 80;
2
+ export interface ISpinner {
3
+ readonly isEnabled: boolean;
4
+ start(): void;
5
+ stop(): void;
6
+ }
7
+ /**
8
+ * Optional settings when creating a spinner.
9
+ */
10
+ export interface SpinnerOptions {
11
+ /**
12
+ * Text shown next to the spinner.
13
+ */
14
+ text?: string;
15
+ /**
16
+ * Stream used to write frames.
17
+ */
18
+ stream?: NodeJS.WriteStream;
19
+ /**
20
+ * Whether the spinner is enabled.
21
+ */
22
+ enabled?: boolean;
23
+ }
24
+ /**
25
+ * Create a spinner instance.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const spinner = createSpinner({ text: "Compiling…" });
30
+ * spinner.start();
31
+ *
32
+ * try {
33
+ * await compileContracts();
34
+ * spinner.stop();
35
+ * console.log("Compiled 12 contracts");
36
+ * } catch (error) {
37
+ * spinner.stop();
38
+ * console.error("Compilation failed");
39
+ * }
40
+ * ```
41
+ *
42
+ * @param options Optional spinner configuration.
43
+ * @returns {Spinner} A spinner instance.
44
+ */
45
+ export declare function createSpinner(options?: SpinnerOptions): ISpinner;
46
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/spinner.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IAE5B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,cAAmB,GAAG,QAAQ,CAcpE"}
@@ -0,0 +1,91 @@
1
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
2
+ export const FRAME_INTERVAL_MS = 80;
3
+ /**
4
+ * Spinner that writes frames to a stream.
5
+ */
6
+ class Spinner {
7
+ isEnabled;
8
+ #text;
9
+ #interval = null;
10
+ #stream;
11
+ constructor(options) {
12
+ this.isEnabled = options.enabled;
13
+ this.#stream = options.stream;
14
+ this.#text = options.text;
15
+ }
16
+ /**
17
+ * Begin rendering frames when enabled.
18
+ */
19
+ start() {
20
+ if (!this.isEnabled) {
21
+ return;
22
+ }
23
+ this.#stopAnimation();
24
+ let frameIndex = 0;
25
+ this.#interval = setInterval(() => {
26
+ this.#render(FRAMES[frameIndex]);
27
+ frameIndex = (frameIndex + 1) % FRAMES.length;
28
+ }, FRAME_INTERVAL_MS);
29
+ }
30
+ /**
31
+ * Stop the spinner without printing a final line.
32
+ */
33
+ stop() {
34
+ this.#stopAnimation();
35
+ }
36
+ #clearLine() {
37
+ this.#stream.clearLine(0);
38
+ this.#stream.cursorTo(0);
39
+ }
40
+ #render(frame) {
41
+ if (!this.isEnabled) {
42
+ return;
43
+ }
44
+ this.#clearLine();
45
+ this.#stream.write(`${frame} ${this.#text}`);
46
+ }
47
+ #stopAnimation() {
48
+ if (this.#interval === null) {
49
+ return;
50
+ }
51
+ clearInterval(this.#interval);
52
+ this.#interval = null;
53
+ if (this.isEnabled) {
54
+ this.#clearLine();
55
+ }
56
+ }
57
+ }
58
+ /**
59
+ * Create a spinner instance.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const spinner = createSpinner({ text: "Compiling…" });
64
+ * spinner.start();
65
+ *
66
+ * try {
67
+ * await compileContracts();
68
+ * spinner.stop();
69
+ * console.log("Compiled 12 contracts");
70
+ * } catch (error) {
71
+ * spinner.stop();
72
+ * console.error("Compilation failed");
73
+ * }
74
+ * ```
75
+ *
76
+ * @param options Optional spinner configuration.
77
+ * @returns {Spinner} A spinner instance.
78
+ */
79
+ export function createSpinner(options = {}) {
80
+ const stream = options.stream ?? process.stdout;
81
+ const enabled = stream.isTTY === true &&
82
+ process.env.TERM !== "dumb" &&
83
+ (options.enabled ?? true);
84
+ const text = options.text ?? "";
85
+ return new Spinner({
86
+ enabled,
87
+ stream,
88
+ text,
89
+ });
90
+ }
91
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/spinner.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AA4BpC;;GAEG;AACH,MAAM,OAAO;IACK,SAAS,CAAU;IAC1B,KAAK,CAAS;IACvB,SAAS,GAA0B,IAAI,CAAC;IAC/B,OAAO,CAAqB;IAErC,YAAY,OAAiC;QAC3C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5B,CAAC;IACD;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YACjC,UAAU,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAChD,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,IAAI;QACT,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,UAAU;QACR,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,KAAa;QACnB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,aAAa,CAAC,UAA0B,EAAE;IACxD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAEhD,MAAM,OAAO,GACX,MAAM,CAAC,KAAK,KAAK,IAAI;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM;QAC3B,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;IAE5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC;QACjB,OAAO;QACP,MAAM;QACN,IAAI;KACL,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomicfoundation/hardhat-utils",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Utilities for Hardhat and its plugins",
5
5
  "homepage": "https://github.com/nomicfoundation/hardhat/tree/v-next/v-next/hardhat-utils",
6
6
  "repository": {
@@ -35,7 +35,8 @@
35
35
  "./string": "./dist/src/string.js",
36
36
  "./stream": "./dist/src/stream.js",
37
37
  "./subprocess": "./dist/src/subprocess.js",
38
- "./synchronization": "./dist/src/synchronization.js"
38
+ "./synchronization": "./dist/src/synchronization.js",
39
+ "./spinner": "./dist/src/spinner.js"
39
40
  },
40
41
  "keywords": [
41
42
  "ethereum",
package/src/spinner.ts ADDED
@@ -0,0 +1,130 @@
1
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
2
+ export const FRAME_INTERVAL_MS = 80;
3
+
4
+ export interface ISpinner {
5
+ readonly isEnabled: boolean;
6
+ start(): void;
7
+ stop(): void;
8
+ }
9
+
10
+ /**
11
+ * Optional settings when creating a spinner.
12
+ */
13
+ export interface SpinnerOptions {
14
+ /**
15
+ * Text shown next to the spinner.
16
+ */
17
+ text?: string;
18
+
19
+ /**
20
+ * Stream used to write frames.
21
+ */
22
+ stream?: NodeJS.WriteStream;
23
+
24
+ /**
25
+ * Whether the spinner is enabled.
26
+ */
27
+ enabled?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Spinner that writes frames to a stream.
32
+ */
33
+ class Spinner implements ISpinner {
34
+ public readonly isEnabled: boolean;
35
+ readonly #text: string;
36
+ #interval: NodeJS.Timeout | null = null;
37
+ readonly #stream: NodeJS.WriteStream;
38
+
39
+ constructor(options: Required<SpinnerOptions>) {
40
+ this.isEnabled = options.enabled;
41
+ this.#stream = options.stream;
42
+ this.#text = options.text;
43
+ }
44
+ /**
45
+ * Begin rendering frames when enabled.
46
+ */
47
+ public start(): void {
48
+ if (!this.isEnabled) {
49
+ return;
50
+ }
51
+
52
+ this.#stopAnimation();
53
+ let frameIndex = 0;
54
+
55
+ this.#interval = setInterval(() => {
56
+ this.#render(FRAMES[frameIndex]);
57
+ frameIndex = (frameIndex + 1) % FRAMES.length;
58
+ }, FRAME_INTERVAL_MS);
59
+ }
60
+
61
+ /**
62
+ * Stop the spinner without printing a final line.
63
+ */
64
+ public stop(): void {
65
+ this.#stopAnimation();
66
+ }
67
+
68
+ #clearLine(): void {
69
+ this.#stream.clearLine(0);
70
+ this.#stream.cursorTo(0);
71
+ }
72
+
73
+ #render(frame: string): void {
74
+ if (!this.isEnabled) {
75
+ return;
76
+ }
77
+ this.#clearLine();
78
+ this.#stream.write(`${frame} ${this.#text}`);
79
+ }
80
+
81
+ #stopAnimation(): void {
82
+ if (this.#interval === null) {
83
+ return;
84
+ }
85
+
86
+ clearInterval(this.#interval);
87
+ this.#interval = null;
88
+
89
+ if (this.isEnabled) {
90
+ this.#clearLine();
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Create a spinner instance.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const spinner = createSpinner({ text: "Compiling…" });
101
+ * spinner.start();
102
+ *
103
+ * try {
104
+ * await compileContracts();
105
+ * spinner.stop();
106
+ * console.log("Compiled 12 contracts");
107
+ * } catch (error) {
108
+ * spinner.stop();
109
+ * console.error("Compilation failed");
110
+ * }
111
+ * ```
112
+ *
113
+ * @param options Optional spinner configuration.
114
+ * @returns {Spinner} A spinner instance.
115
+ */
116
+ export function createSpinner(options: SpinnerOptions = {}): ISpinner {
117
+ const stream = options.stream ?? process.stdout;
118
+
119
+ const enabled =
120
+ stream.isTTY === true &&
121
+ process.env.TERM !== "dumb" &&
122
+ (options.enabled ?? true);
123
+
124
+ const text = options.text ?? "";
125
+ return new Spinner({
126
+ enabled,
127
+ stream,
128
+ text,
129
+ });
130
+ }