hardhat 3.1.8 → 3.1.10

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.
Files changed (146) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/src/config.d.ts +20 -0
  3. package/dist/src/config.d.ts.map +1 -1
  4. package/dist/src/config.js +31 -0
  5. package/dist/src/config.js.map +1 -1
  6. package/dist/src/internal/builtin-plugins/coverage/coverage-manager.d.ts.map +1 -1
  7. package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js +33 -21
  8. package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js.map +1 -1
  9. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.d.ts.map +1 -1
  10. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js +7 -8
  11. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js.map +1 -1
  12. package/dist/src/internal/builtin-plugins/coverage/instrumentation.d.ts +27 -0
  13. package/dist/src/internal/builtin-plugins/coverage/instrumentation.d.ts.map +1 -0
  14. package/dist/src/internal/builtin-plugins/coverage/instrumentation.js +27 -0
  15. package/dist/src/internal/builtin-plugins/coverage/instrumentation.js.map +1 -0
  16. package/dist/src/internal/builtin-plugins/flatten/task-action.d.ts.map +1 -1
  17. package/dist/src/internal/builtin-plugins/flatten/task-action.js +1 -1
  18. package/dist/src/internal/builtin-plugins/flatten/task-action.js.map +1 -1
  19. package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.d.ts +0 -1
  20. package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.d.ts.map +1 -1
  21. package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.js +4 -8
  22. package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.js.map +1 -1
  23. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.d.ts.map +1 -1
  24. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.js +58 -20
  25. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.js.map +1 -1
  26. package/dist/src/internal/builtin-plugins/network-manager/type-validation.d.ts.map +1 -1
  27. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js +8 -0
  28. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js.map +1 -1
  29. package/dist/src/internal/builtin-plugins/node/task-action.d.ts.map +1 -1
  30. package/dist/src/internal/builtin-plugins/node/task-action.js +1 -2
  31. package/dist/src/internal/builtin-plugins/node/task-action.js.map +1 -1
  32. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts.map +1 -1
  33. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js +1 -1
  34. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js.map +1 -1
  35. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.d.ts +0 -3
  36. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.d.ts.map +1 -1
  37. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.js +8 -10
  38. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.js.map +1 -1
  39. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.d.ts +2 -1
  40. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.d.ts.map +1 -1
  41. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.js +4 -2
  42. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.js.map +1 -1
  43. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts +3 -1
  44. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts.map +1 -1
  45. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.js +8 -2
  46. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.js.map +1 -1
  47. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.d.ts.map +1 -1
  48. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.js +19 -5
  49. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.js.map +1 -1
  50. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts +8 -1
  51. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts.map +1 -1
  52. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js +54 -20
  53. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js.map +1 -1
  54. package/dist/src/internal/builtin-plugins/solidity/type-extensions.d.ts +22 -0
  55. package/dist/src/internal/builtin-plugins/solidity/type-extensions.d.ts.map +1 -1
  56. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts.map +1 -1
  57. package/dist/src/internal/builtin-plugins/solidity-test/config.js +1 -0
  58. package/dist/src/internal/builtin-plugins/solidity-test/config.js.map +1 -1
  59. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts +1 -0
  60. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts.map +1 -1
  61. package/dist/src/internal/cli/error-handler.d.ts.map +1 -1
  62. package/dist/src/internal/cli/error-handler.js +15 -0
  63. package/dist/src/internal/cli/error-handler.js.map +1 -1
  64. package/dist/src/internal/cli/telemetry/sentry/reporter.d.ts.map +1 -1
  65. package/dist/src/internal/cli/telemetry/sentry/reporter.js +4 -0
  66. package/dist/src/internal/cli/telemetry/sentry/reporter.js.map +1 -1
  67. package/dist/src/internal/cli/telemetry/sentry/transport.js +1 -0
  68. package/dist/src/internal/cli/telemetry/sentry/transport.js.map +1 -1
  69. package/dist/src/internal/core/config-validation.d.ts +3 -3
  70. package/dist/src/internal/core/config-validation.d.ts.map +1 -1
  71. package/dist/src/internal/core/config-validation.js +48 -18
  72. package/dist/src/internal/core/config-validation.js.map +1 -1
  73. package/dist/src/internal/core/tasks/builders.d.ts +26 -16
  74. package/dist/src/internal/core/tasks/builders.d.ts.map +1 -1
  75. package/dist/src/internal/core/tasks/builders.js +65 -6
  76. package/dist/src/internal/core/tasks/builders.js.map +1 -1
  77. package/dist/src/internal/core/tasks/resolved-task.d.ts +2 -2
  78. package/dist/src/internal/core/tasks/resolved-task.d.ts.map +1 -1
  79. package/dist/src/internal/core/tasks/resolved-task.js +23 -9
  80. package/dist/src/internal/core/tasks/resolved-task.js.map +1 -1
  81. package/dist/src/internal/core/tasks/task-manager.d.ts.map +1 -1
  82. package/dist/src/internal/core/tasks/task-manager.js +14 -6
  83. package/dist/src/internal/core/tasks/task-manager.js.map +1 -1
  84. package/dist/src/internal/core/tasks/validations.d.ts +2 -0
  85. package/dist/src/internal/core/tasks/validations.d.ts.map +1 -1
  86. package/dist/src/internal/core/tasks/validations.js +11 -0
  87. package/dist/src/internal/core/tasks/validations.js.map +1 -1
  88. package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.d.ts +2 -0
  89. package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.d.ts.map +1 -0
  90. package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js +12 -0
  91. package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js.map +1 -0
  92. package/dist/src/internal/using-hardhat2-plugin-errors.d.ts +35 -0
  93. package/dist/src/internal/using-hardhat2-plugin-errors.d.ts.map +1 -0
  94. package/dist/src/internal/using-hardhat2-plugin-errors.js +98 -0
  95. package/dist/src/internal/using-hardhat2-plugin-errors.js.map +1 -0
  96. package/dist/src/plugins.d.ts +8 -0
  97. package/dist/src/plugins.d.ts.map +1 -1
  98. package/dist/src/plugins.js +13 -0
  99. package/dist/src/plugins.js.map +1 -1
  100. package/dist/src/types/index.d.ts +15 -0
  101. package/dist/src/types/index.d.ts.map +1 -0
  102. package/dist/src/types/index.js +15 -0
  103. package/dist/src/types/index.js.map +1 -0
  104. package/dist/src/types/plugins.d.ts +2 -2
  105. package/dist/src/types/solidity/errors.d.ts +18 -0
  106. package/dist/src/types/solidity/errors.d.ts.map +1 -1
  107. package/dist/src/types/solidity/errors.js.map +1 -1
  108. package/dist/src/types/tasks.d.ts +95 -34
  109. package/dist/src/types/tasks.d.ts.map +1 -1
  110. package/package.json +10 -6
  111. package/src/config.ts +37 -0
  112. package/src/internal/builtin-plugins/coverage/coverage-manager.ts +57 -50
  113. package/src/internal/builtin-plugins/coverage/hook-handlers/solidity.ts +6 -17
  114. package/src/internal/builtin-plugins/coverage/instrumentation.ts +52 -0
  115. package/src/internal/builtin-plugins/flatten/task-action.ts +1 -0
  116. package/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.ts +6 -11
  117. package/src/internal/builtin-plugins/network-manager/hook-handlers/config.ts +65 -21
  118. package/src/internal/builtin-plugins/network-manager/type-validation.ts +9 -0
  119. package/src/internal/builtin-plugins/node/task-action.ts +2 -2
  120. package/src/internal/builtin-plugins/solidity/build-system/build-system.ts +1 -0
  121. package/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.ts +14 -11
  122. package/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.ts +23 -1
  123. package/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.ts +16 -2
  124. package/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.ts +19 -5
  125. package/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.ts +103 -29
  126. package/src/internal/builtin-plugins/solidity/type-extensions.ts +28 -0
  127. package/src/internal/builtin-plugins/solidity-test/config.ts +1 -0
  128. package/src/internal/builtin-plugins/solidity-test/type-extensions.ts +1 -0
  129. package/src/internal/cli/error-handler.ts +18 -0
  130. package/src/internal/cli/telemetry/sentry/reporter.ts +5 -0
  131. package/src/internal/cli/telemetry/sentry/transport.ts +1 -0
  132. package/src/internal/core/config-validation.ts +67 -18
  133. package/src/internal/core/tasks/builders.ts +174 -30
  134. package/src/internal/core/tasks/resolved-task.ts +31 -13
  135. package/src/internal/core/tasks/task-manager.ts +23 -5
  136. package/src/internal/core/tasks/validations.ts +40 -0
  137. package/src/internal/deprecated-module-imported-from-hardhat2-plugin.ts +12 -0
  138. package/src/internal/using-hardhat2-plugin-errors.ts +108 -0
  139. package/src/plugins.ts +16 -0
  140. package/src/types/index.ts +14 -0
  141. package/src/types/plugins.ts +2 -2
  142. package/src/types/solidity/errors.ts +22 -0
  143. package/src/types/tasks.ts +133 -36
  144. package/templates/hardhat-3/01-node-test-runner-viem/package.json +10 -10
  145. package/templates/hardhat-3/02-mocha-ethers/package.json +16 -16
  146. package/templates/hardhat-3/03-minimal/package.json +1 -1
@@ -5,6 +5,7 @@ import {
5
5
  import chalk from "chalk";
6
6
 
7
7
  import { HARDHAT_NAME, HARDHAT_WEBSITE_URL } from "../constants.js";
8
+ import { UsingHardhat2PluginError } from "../using-hardhat2-plugin-errors.js";
8
9
 
9
10
  /**
10
11
  * The different categories of errors that can be handled by hardhat cli.
@@ -69,6 +70,11 @@ export function printErrorMessages(
69
70
  shouldShowStackTraces: boolean = false,
70
71
  print: (message: string | Error) => void = console.error,
71
72
  ): void {
73
+ if (error instanceof UsingHardhat2PluginError) {
74
+ printUsingHardhat2Error(error, print);
75
+ return;
76
+ }
77
+
72
78
  const showStackTraces =
73
79
  shouldShowStackTraces ||
74
80
  getErrorWithCategory(error).category === ErrorCategory.OTHER;
@@ -146,3 +152,15 @@ function getErrorMessages(error: Error): ErrorMessages {
146
152
  };
147
153
  }
148
154
  }
155
+ function printUsingHardhat2Error(
156
+ error: UsingHardhat2PluginError,
157
+ print: (message: string | Error) => void = console.error,
158
+ ): void {
159
+ print(chalk.red.bold(`Hardhat 3 installation error:`));
160
+ print("");
161
+ if (error.callerRelativePath !== undefined) {
162
+ print(error.message);
163
+ } else {
164
+ print(error.stack);
165
+ }
166
+ }
@@ -8,6 +8,7 @@ import {
8
8
  ProviderError,
9
9
  UnknownError,
10
10
  } from "../../../builtin-plugins/network-manager/provider-errors.js";
11
+ import { UsingHardhat2PluginError } from "../../../using-hardhat2-plugin-errors.js";
11
12
  import { getHardhatVersion } from "../../../utils/package.js";
12
13
  import { isTelemetryAllowed } from "../telemetry-permissions.js";
13
14
 
@@ -134,6 +135,10 @@ class Reporter {
134
135
  return false;
135
136
  }
136
137
 
138
+ if (error instanceof UsingHardhat2PluginError) {
139
+ return false;
140
+ }
141
+
137
142
  if (HardhatPluginError.isHardhatPluginError(error)) {
138
143
  // Don't log errors from third-party plugins
139
144
  return false;
@@ -177,6 +177,7 @@ async function sendSerializedEnvelopeToSentryBackend(
177
177
  .filter(Boolean)
178
178
  .join(", ");
179
179
 
180
+ // eslint-disable-next-line no-restricted-globals -- TODO: determine whether this should be using undici
180
181
  const res = await fetch(ingestUrl, {
181
182
  method: "POST",
182
183
  headers: {
@@ -18,9 +18,9 @@ import {
18
18
  } from "../../types/arguments.js";
19
19
  import {
20
20
  type EmptyTaskDefinition,
21
+ TaskDefinitionType,
21
22
  type NewTaskDefinition,
22
23
  type TaskDefinition,
23
- TaskDefinitionType,
24
24
  type TaskOverrideDefinition,
25
25
  } from "../../types/tasks.js";
26
26
 
@@ -185,6 +185,7 @@ function validatePath(
185
185
  export function validateTasksConfig(
186
186
  tasks: TaskDefinition[],
187
187
  path: Array<string | number> = [],
188
+ isPlugin: boolean = false,
188
189
  ): HardhatUserConfigValidationError[] {
189
190
  const validationErrors: HardhatUserConfigValidationError[] = [];
190
191
 
@@ -207,13 +208,13 @@ export function validateTasksConfig(
207
208
  }
208
209
  case TaskDefinitionType.NEW_TASK: {
209
210
  validationErrors.push(
210
- ...validateNewTask(task, [...path, "tasks", index]),
211
+ ...validateNewTask(task, [...path, "tasks", index], isPlugin),
211
212
  );
212
213
  break;
213
214
  }
214
215
  case TaskDefinitionType.TASK_OVERRIDE: {
215
216
  validationErrors.push(
216
- ...validateTaskOverride(task, [...path, "tasks", index]),
217
+ ...validateTaskOverride(task, [...path, "tasks", index], isPlugin),
217
218
  );
218
219
  break;
219
220
  }
@@ -252,6 +253,7 @@ export function validateEmptyTask(
252
253
  export function validateNewTask(
253
254
  task: NewTaskDefinition,
254
255
  path: Array<string | number>,
256
+ isPlugin: boolean = false,
255
257
  ): HardhatUserConfigValidationError[] {
256
258
  const validationErrors: HardhatUserConfigValidationError[] = [];
257
259
 
@@ -272,13 +274,7 @@ export function validateNewTask(
272
274
  });
273
275
  }
274
276
 
275
- if (typeof task.action !== "function") {
276
- validationErrors.push({
277
- path: [...path, "action"],
278
- message:
279
- "task action must be a lazy import function returning a module with a default export",
280
- });
281
- }
277
+ validationErrors.push(...validateActionFields(task, path, isPlugin));
282
278
 
283
279
  if (isObject(task.options)) {
284
280
  validationErrors.push(
@@ -308,6 +304,7 @@ export function validateNewTask(
308
304
  export function validateTaskOverride(
309
305
  task: TaskOverrideDefinition,
310
306
  path: Array<string | number>,
307
+ isPlugin: boolean = false,
311
308
  ): HardhatUserConfigValidationError[] {
312
309
  const validationErrors: HardhatUserConfigValidationError[] = [];
313
310
 
@@ -328,13 +325,7 @@ export function validateTaskOverride(
328
325
  });
329
326
  }
330
327
 
331
- if (typeof task.action !== "function") {
332
- validationErrors.push({
333
- path: [...path, "action"],
334
- message:
335
- "task action must be a lazy import function returning a module with a default export",
336
- });
337
- }
328
+ validationErrors.push(...validateActionFields(task, path, isPlugin));
338
329
 
339
330
  if (isObject(task.options)) {
340
331
  validationErrors.push(
@@ -350,6 +341,60 @@ export function validateTaskOverride(
350
341
  return validationErrors;
351
342
  }
352
343
 
344
+ function validateActionFields(
345
+ task: { action?: unknown; inlineAction?: unknown },
346
+ path: Array<string | number>,
347
+ isPlugin: boolean = false,
348
+ ): HardhatUserConfigValidationError[] {
349
+ const validationErrors: HardhatUserConfigValidationError[] = [];
350
+
351
+ // Mutual exclusivity: cannot have both action and inlineAction
352
+ if (task.action !== undefined && task.inlineAction !== undefined) {
353
+ validationErrors.push({
354
+ path: [...path],
355
+ message: 'task cannot define both "action" and "inlineAction"',
356
+ });
357
+ }
358
+
359
+ if (isPlugin && task.inlineAction !== undefined) {
360
+ validationErrors.push({
361
+ path: [...path, "inlineAction"],
362
+ message:
363
+ "plugins cannot use inline actions. Use a lazy action import instead",
364
+ });
365
+ }
366
+
367
+ // At least one action must be defined
368
+ if (task.action === undefined && task.inlineAction === undefined) {
369
+ validationErrors.push({
370
+ path: [...path, "action"],
371
+ message: 'task must define either "action" or "inlineAction"',
372
+ });
373
+ }
374
+
375
+ if (task.action !== undefined) {
376
+ if (typeof task.action !== "function") {
377
+ validationErrors.push({
378
+ path: [...path, "action"],
379
+ message:
380
+ "task action must be a lazy import function returning a module with a default export",
381
+ });
382
+ }
383
+ }
384
+
385
+ if (task.inlineAction !== undefined) {
386
+ if (typeof task.inlineAction !== "function") {
387
+ validationErrors.push({
388
+ path: [...path, "inlineAction"],
389
+ message:
390
+ "task inlineAction must be a function implementing the task's behavior",
391
+ });
392
+ }
393
+ }
394
+
395
+ return validationErrors;
396
+ }
397
+
353
398
  export function validateOptions(
354
399
  options: Record<string, OptionDefinition>,
355
400
  path: Array<string | number>,
@@ -665,7 +710,11 @@ export function validatePluginsConfig(
665
710
  if (plugin.tasks !== undefined) {
666
711
  if (Array.isArray(plugin.tasks)) {
667
712
  validationErrors.push(
668
- ...validateTasksConfig(plugin.tasks, [...path, "plugins", index]),
713
+ ...validateTasksConfig(
714
+ plugin.tasks,
715
+ [...path, "plugins", index],
716
+ true,
717
+ ),
669
718
  );
670
719
  } else {
671
720
  validationErrors.push({
@@ -15,6 +15,8 @@ import type {
15
15
  ExtendTaskArguments,
16
16
  TaskArguments,
17
17
  LazyActionObject,
18
+ TaskAction,
19
+ TaskOverrideAction,
18
20
  } from "../../../types/tasks.js";
19
21
 
20
22
  import { HardhatError } from "@nomicfoundation/hardhat-errors";
@@ -54,7 +56,11 @@ export class EmptyTaskDefinitionBuilderImplementation
54
56
 
55
57
  export class NewTaskDefinitionBuilderImplementation<
56
58
  TaskArgumentsT extends TaskArguments = TaskArguments,
57
- > implements NewTaskDefinitionBuilder<TaskArgumentsT>
59
+ ActionTypeT extends
60
+ | "LAZY_ACTION"
61
+ | "INLINE_ACTION"
62
+ | "MISSING_ACTION" = "MISSING_ACTION",
63
+ > implements NewTaskDefinitionBuilder<TaskArgumentsT, ActionTypeT>
58
64
  {
59
65
  readonly #id: string[];
60
66
  readonly #usedNames: Set<string> = new Set();
@@ -65,6 +71,7 @@ export class NewTaskDefinitionBuilderImplementation<
65
71
  #description: string;
66
72
 
67
73
  #action?: LazyActionObject<NewTaskActionFunction<TaskArgumentsT>>;
74
+ #inlineAction?: NewTaskActionFunction<TaskArgumentsT>;
68
75
 
69
76
  constructor(id: string | string[], description: string = "") {
70
77
  validateId(id);
@@ -80,10 +87,26 @@ export class NewTaskDefinitionBuilderImplementation<
80
87
 
81
88
  public setAction(
82
89
  action: LazyActionObject<NewTaskActionFunction<TaskArgumentsT>>,
83
- ): this {
90
+ ): NewTaskDefinitionBuilder<TaskArgumentsT, "LAZY_ACTION"> {
91
+ this.#ensureNoActionSet();
92
+
84
93
  this.#action = action;
85
94
 
86
- return this;
95
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
96
+ -- Cast to update the ActionTypeT to the expected type for this scenario. */
97
+ return this as NewTaskDefinitionBuilder<TaskArgumentsT, "LAZY_ACTION">;
98
+ }
99
+
100
+ public setInlineAction(
101
+ inlineAction: NewTaskActionFunction<TaskArgumentsT>,
102
+ ): NewTaskDefinitionBuilder<TaskArgumentsT, "INLINE_ACTION"> {
103
+ this.#ensureNoActionSet();
104
+
105
+ this.#inlineAction = inlineAction;
106
+
107
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
108
+ -- Cast to update the ActionTypeT to the expected type for this scenario. */
109
+ return this as NewTaskDefinitionBuilder<TaskArgumentsT, "INLINE_ACTION">;
87
110
  }
88
111
 
89
112
  public addOption<
@@ -104,7 +127,8 @@ export class NewTaskDefinitionBuilderImplementation<
104
127
  defaultValue: ArgumentTypeToValueType<TypeT>;
105
128
  hidden?: boolean;
106
129
  }): NewTaskDefinitionBuilder<
107
- ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>
130
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
131
+ ActionTypeT
108
132
  > {
109
133
  const argumentType = type ?? ArgumentType.STRING;
110
134
 
@@ -121,7 +145,13 @@ export class NewTaskDefinitionBuilderImplementation<
121
145
 
122
146
  this.#options[name] = optionDefinition;
123
147
 
124
- return this;
148
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
149
+ -- Cast to update the generic argument types. Propagate 'ActionTypeT' to preserve
150
+ the current action state for subsequent method calls. */
151
+ return this as NewTaskDefinitionBuilder<
152
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
153
+ ActionTypeT
154
+ >;
125
155
  }
126
156
 
127
157
  public addFlag<NameT extends string>(flagConfig: {
@@ -130,7 +160,8 @@ export class NewTaskDefinitionBuilderImplementation<
130
160
  description?: string;
131
161
  hidden?: boolean;
132
162
  }): NewTaskDefinitionBuilder<
133
- ExtendTaskArguments<NameT, ArgumentType.FLAG, TaskArgumentsT>
163
+ ExtendTaskArguments<NameT, ArgumentType.FLAG, TaskArgumentsT>,
164
+ ActionTypeT
134
165
  > {
135
166
  return this.addOption({
136
167
  ...flagConfig,
@@ -146,7 +177,8 @@ export class NewTaskDefinitionBuilderImplementation<
146
177
  description?: string;
147
178
  defaultValue?: number;
148
179
  }): NewTaskDefinitionBuilder<
149
- ExtendTaskArguments<NameT, ArgumentType.LEVEL, TaskArgumentsT>
180
+ ExtendTaskArguments<NameT, ArgumentType.LEVEL, TaskArgumentsT>,
181
+ ActionTypeT
150
182
  > {
151
183
  return this.addOption({
152
184
  ...levelConfig,
@@ -164,7 +196,8 @@ export class NewTaskDefinitionBuilderImplementation<
164
196
  type?: TypeT;
165
197
  defaultValue?: ArgumentTypeToValueType<TypeT>;
166
198
  }): NewTaskDefinitionBuilder<
167
- ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>
199
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
200
+ ActionTypeT
168
201
  > {
169
202
  return this.#addPositionalArgument({
170
203
  ...argConfig,
@@ -181,7 +214,8 @@ export class NewTaskDefinitionBuilderImplementation<
181
214
  type?: TypeT;
182
215
  defaultValue?: Array<ArgumentTypeToValueType<TypeT>>;
183
216
  }): NewTaskDefinitionBuilder<
184
- ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>
217
+ ExtendTaskArguments<NameT, TypeT[], TaskArgumentsT>,
218
+ ActionTypeT
185
219
  > {
186
220
  return this.#addPositionalArgument({
187
221
  ...argConfig,
@@ -189,8 +223,15 @@ export class NewTaskDefinitionBuilderImplementation<
189
223
  });
190
224
  }
191
225
 
192
- public build(): NewTaskDefinition {
193
- if (this.#action === undefined) {
226
+ public build(): ActionTypeT extends "LAZY_ACTION"
227
+ ? Extract<
228
+ NewTaskDefinition,
229
+ { action: LazyActionObject<NewTaskActionFunction> }
230
+ >
231
+ : ActionTypeT extends "INLINE_ACTION"
232
+ ? Extract<NewTaskDefinition, { inlineAction: NewTaskActionFunction }>
233
+ : never {
234
+ if (this.#action === undefined && this.#inlineAction === undefined) {
194
235
  throw new HardhatError(
195
236
  HardhatError.ERRORS.CORE.TASK_DEFINITIONS.NO_ACTION,
196
237
  {
@@ -199,18 +240,30 @@ export class NewTaskDefinitionBuilderImplementation<
199
240
  );
200
241
  }
201
242
 
243
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
244
+ -- Cast the return value because TypeScript cannot verify that the object matches
245
+ the conditional type. */
202
246
  return {
203
247
  type: TaskDefinitionType.NEW_TASK,
204
248
  id: this.#id,
205
249
  description: this.#description,
206
250
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
207
- -- The type of the action is narrowed in the setAction function to
251
+ -- The type of the action is narrowed in the setAction function or setInlineAction to
208
252
  improve the argument types. Once the task is built, we use the more
209
253
  general type to avoid having to parameterize the NewTaskDefinition */
210
- action: this.#action as LazyActionObject<NewTaskActionFunction>,
254
+ ...((this.#action !== undefined
255
+ ? { action: this.#action }
256
+ : { inlineAction: this.#inlineAction }) as TaskAction),
211
257
  options: this.#options,
212
258
  positionalArguments: this.#positionalArgs,
213
- };
259
+ } as ActionTypeT extends "LAZY_ACTION"
260
+ ? Extract<
261
+ NewTaskDefinition,
262
+ { action: LazyActionObject<NewTaskActionFunction> }
263
+ >
264
+ : ActionTypeT extends "INLINE_ACTION"
265
+ ? Extract<NewTaskDefinition, { inlineAction: NewTaskActionFunction }>
266
+ : never;
214
267
  }
215
268
 
216
269
  #addPositionalArgument<
@@ -231,7 +284,8 @@ export class NewTaskDefinitionBuilderImplementation<
231
284
  | Array<ArgumentTypeToValueType<TypeT>>;
232
285
  isVariadic: boolean;
233
286
  }): NewTaskDefinitionBuilder<
234
- ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>
287
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
288
+ ActionTypeT
235
289
  > {
236
290
  const argumentType = type ?? ArgumentType.STRING;
237
291
 
@@ -253,13 +307,34 @@ export class NewTaskDefinitionBuilderImplementation<
253
307
 
254
308
  this.#positionalArgs.push(positionalArgDef);
255
309
 
256
- return this;
310
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
311
+ -- Cast to update the generic argument types. Propagate 'ActionTypeT' to preserve
312
+ the current action state for subsequent method calls. */
313
+ return this as NewTaskDefinitionBuilder<
314
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
315
+ ActionTypeT
316
+ >;
317
+ }
318
+
319
+ #ensureNoActionSet(): void {
320
+ if (this.#action !== undefined || this.#inlineAction !== undefined) {
321
+ throw new HardhatError(
322
+ HardhatError.ERRORS.CORE.TASK_DEFINITIONS.ACTION_ALREADY_SET,
323
+ {
324
+ task: formatTaskId(this.#id),
325
+ },
326
+ );
327
+ }
257
328
  }
258
329
  }
259
330
 
260
331
  export class TaskOverrideDefinitionBuilderImplementation<
261
332
  TaskArgumentsT extends TaskArguments = TaskArguments,
262
- > implements TaskOverrideDefinitionBuilder<TaskArgumentsT>
333
+ ActionTypeT extends
334
+ | "LAZY_ACTION"
335
+ | "INLINE_ACTION"
336
+ | "MISSING_ACTION" = "MISSING_ACTION",
337
+ > implements TaskOverrideDefinitionBuilder<TaskArgumentsT, ActionTypeT>
263
338
  {
264
339
  readonly #id: string[];
265
340
 
@@ -268,6 +343,7 @@ export class TaskOverrideDefinitionBuilderImplementation<
268
343
  #description?: string;
269
344
 
270
345
  #action?: LazyActionObject<TaskOverrideActionFunction<TaskArgumentsT>>;
346
+ #inlineAction?: TaskOverrideActionFunction<TaskArgumentsT>;
271
347
 
272
348
  constructor(id: string | string[]) {
273
349
  validateId(id);
@@ -282,10 +358,29 @@ export class TaskOverrideDefinitionBuilderImplementation<
282
358
 
283
359
  public setAction(
284
360
  action: LazyActionObject<TaskOverrideActionFunction<TaskArgumentsT>>,
285
- ): this {
361
+ ): TaskOverrideDefinitionBuilder<TaskArgumentsT, "LAZY_ACTION"> {
362
+ this.#ensureNoActionSet();
363
+
286
364
  this.#action = action;
287
365
 
288
- return this;
366
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
367
+ -- Cast to update the ActionTypeT to the expected type for this scenario. */
368
+ return this as TaskOverrideDefinitionBuilder<TaskArgumentsT, "LAZY_ACTION">;
369
+ }
370
+
371
+ public setInlineAction(
372
+ inlineAction: TaskOverrideActionFunction<TaskArgumentsT>,
373
+ ): TaskOverrideDefinitionBuilder<TaskArgumentsT, "INLINE_ACTION"> {
374
+ this.#ensureNoActionSet();
375
+
376
+ this.#inlineAction = inlineAction;
377
+
378
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
379
+ -- Cast to update the ActionTypeT to the expected type for this scenario. */
380
+ return this as TaskOverrideDefinitionBuilder<
381
+ TaskArgumentsT,
382
+ "INLINE_ACTION"
383
+ >;
289
384
  }
290
385
 
291
386
  public addOption<
@@ -306,7 +401,8 @@ export class TaskOverrideDefinitionBuilderImplementation<
306
401
  defaultValue: ArgumentTypeToValueType<TypeT>;
307
402
  hidden?: boolean;
308
403
  }): TaskOverrideDefinitionBuilder<
309
- ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>
404
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
405
+ ActionTypeT
310
406
  > {
311
407
  const argumentType = type ?? ArgumentType.STRING;
312
408
 
@@ -331,16 +427,23 @@ export class TaskOverrideDefinitionBuilderImplementation<
331
427
 
332
428
  this.#options[name] = optionDefinition;
333
429
 
334
- return this;
430
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
431
+ -- Cast to update the generic argument types. Propagate 'ActionTypeT' to preserve
432
+ the current action state for subsequent method calls. */
433
+ return this as TaskOverrideDefinitionBuilder<
434
+ ExtendTaskArguments<NameT, TypeT, TaskArgumentsT>,
435
+ ActionTypeT
436
+ >;
335
437
  }
336
438
 
337
439
  public addFlag<NameT extends string>(flagConfig: {
338
- name: string;
440
+ name: NameT;
339
441
  shortName?: string;
340
442
  description?: string;
341
443
  hidden?: boolean;
342
444
  }): TaskOverrideDefinitionBuilder<
343
- ExtendTaskArguments<NameT, ArgumentType.FLAG, TaskArgumentsT>
445
+ ExtendTaskArguments<NameT, ArgumentType.FLAG, TaskArgumentsT>,
446
+ ActionTypeT
344
447
  > {
345
448
  return this.addOption({
346
449
  ...flagConfig,
@@ -351,12 +454,13 @@ export class TaskOverrideDefinitionBuilderImplementation<
351
454
  }
352
455
 
353
456
  public addLevel<NameT extends string>(levelConfig: {
354
- name: string;
457
+ name: NameT;
355
458
  shortName?: string;
356
459
  description?: string;
357
460
  defaultValue?: number;
358
461
  }): TaskOverrideDefinitionBuilder<
359
- ExtendTaskArguments<NameT, ArgumentType.LEVEL, TaskArgumentsT>
462
+ ExtendTaskArguments<NameT, ArgumentType.LEVEL, TaskArgumentsT>,
463
+ ActionTypeT
360
464
  > {
361
465
  return this.addOption({
362
466
  ...levelConfig,
@@ -365,8 +469,18 @@ export class TaskOverrideDefinitionBuilderImplementation<
365
469
  });
366
470
  }
367
471
 
368
- public build(): TaskOverrideDefinition {
369
- if (this.#action === undefined) {
472
+ public build(): ActionTypeT extends "LAZY_ACTION"
473
+ ? Extract<
474
+ TaskOverrideDefinition,
475
+ { action: LazyActionObject<TaskOverrideActionFunction> }
476
+ >
477
+ : ActionTypeT extends "INLINE_ACTION"
478
+ ? Extract<
479
+ TaskOverrideDefinition,
480
+ { inlineAction: TaskOverrideActionFunction }
481
+ >
482
+ : never {
483
+ if (this.#action === undefined && this.#inlineAction === undefined) {
370
484
  throw new HardhatError(
371
485
  HardhatError.ERRORS.CORE.TASK_DEFINITIONS.NO_ACTION,
372
486
  {
@@ -375,16 +489,46 @@ export class TaskOverrideDefinitionBuilderImplementation<
375
489
  );
376
490
  }
377
491
 
492
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
493
+ -- Cast the return value because TypeScript cannot verify that the object matches
494
+ the conditional type. */
378
495
  return {
379
496
  type: TaskDefinitionType.TASK_OVERRIDE,
380
497
  id: this.#id,
381
498
  description: this.#description,
382
499
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
383
- -- The type of the action is narrowed in the setAction function to
500
+ -- The type of the action is narrowed in the setAction function or setInlineAction to
384
501
  improve the argument types. Once the task is built, we use the more
385
502
  general type to avoid having to parameterize the TaskOverrideDefinition */
386
- action: this.#action as LazyActionObject<TaskOverrideActionFunction>,
503
+ ...((this.#action !== undefined
504
+ ? {
505
+ action: this.#action,
506
+ }
507
+ : {
508
+ inlineAction: this.#inlineAction,
509
+ }) as TaskOverrideAction),
387
510
  options: this.#options,
388
- };
511
+ } as ActionTypeT extends "LAZY_ACTION"
512
+ ? Extract<
513
+ TaskOverrideDefinition,
514
+ { action: LazyActionObject<TaskOverrideActionFunction> }
515
+ >
516
+ : ActionTypeT extends "INLINE_ACTION"
517
+ ? Extract<
518
+ TaskOverrideDefinition,
519
+ { inlineAction: TaskOverrideActionFunction }
520
+ >
521
+ : never;
522
+ }
523
+
524
+ #ensureNoActionSet(): void {
525
+ if (this.#action !== undefined || this.#inlineAction !== undefined) {
526
+ throw new HardhatError(
527
+ HardhatError.ERRORS.CORE.TASK_DEFINITIONS.ACTION_ALREADY_SET,
528
+ {
529
+ task: formatTaskId(this.#id),
530
+ },
531
+ );
532
+ }
389
533
  }
390
534
  }
@@ -8,6 +8,7 @@ import type {
8
8
  LazyActionObject,
9
9
  NewTaskActionFunction,
10
10
  Task,
11
+ TaskAction,
11
12
  TaskActions,
12
13
  TaskArguments,
13
14
  TaskOverrideActionFunction,
@@ -36,7 +37,7 @@ export class ResolvedTask implements Task {
36
37
  return new ResolvedTask(
37
38
  id,
38
39
  description,
39
- [{ pluginId, action: undefined }],
40
+ [{ pluginId, action: undefined, inlineAction: undefined }],
40
41
  new Map(),
41
42
  [],
42
43
  pluginId,
@@ -49,7 +50,7 @@ export class ResolvedTask implements Task {
49
50
  hre: HardhatRuntimeEnvironment,
50
51
  id: string[],
51
52
  description: string,
52
- action: LazyActionObject<NewTaskActionFunction>,
53
+ taskAction: TaskAction,
53
54
  options: Record<string, OptionDefinition>,
54
55
  positionalArguments: PositionalArgumentDefinition[],
55
56
  pluginId?: string,
@@ -57,7 +58,12 @@ export class ResolvedTask implements Task {
57
58
  return new ResolvedTask(
58
59
  id,
59
60
  description,
60
- [{ pluginId, action }],
61
+ [
62
+ {
63
+ pluginId,
64
+ ...taskAction,
65
+ },
66
+ ],
61
67
  new Map(Object.entries(options)),
62
68
  positionalArguments,
63
69
  pluginId,
@@ -80,7 +86,11 @@ export class ResolvedTask implements Task {
80
86
  }
81
87
 
82
88
  public get isEmpty(): boolean {
83
- return this.actions.length === 1 && this.actions[0].action === undefined;
89
+ return (
90
+ this.actions.length === 1 &&
91
+ this.actions[0].action === undefined &&
92
+ this.actions[0].inlineAction === undefined
93
+ );
84
94
  }
85
95
 
86
96
  /**
@@ -142,17 +152,25 @@ export class ResolvedTask implements Task {
142
152
  nextTaskArguments: TaskArguments,
143
153
  currentIndex = this.actions.length - 1,
144
154
  ): Promise<any> => {
155
+ const currentTaskAction = this.actions[currentIndex];
156
+
157
+ let actionFn: NewTaskActionFunction | TaskOverrideActionFunction;
158
+
145
159
  // The first action may be empty if the task was originally an empty task
146
- const currentAction =
147
- this.actions[currentIndex].action ??
148
- (async () => ({
149
- default: () => {},
150
- }));
160
+ if (currentTaskAction.inlineAction !== undefined) {
161
+ actionFn = currentTaskAction.inlineAction;
162
+ } else {
163
+ const action =
164
+ currentTaskAction.action ??
165
+ (async () => ({
166
+ default: () => {},
167
+ }));
151
168
 
152
- const actionFn = await this.#resolveImportAction(
153
- currentAction,
154
- this.actions[currentIndex].pluginId,
155
- );
169
+ actionFn = await this.#resolveImportAction(
170
+ action,
171
+ currentTaskAction.pluginId,
172
+ );
173
+ }
156
174
 
157
175
  if (currentIndex === 0) {
158
176
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --