movehat 0.2.5 → 0.2.7
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/dist/commands/run.d.ts +17 -0
- package/dist/commands/run.js +46 -32
- package/dist/core/AccountManager.d.ts +121 -139
- package/dist/core/AccountManager.js +217 -158
- package/dist/core/config.js +109 -27
- package/dist/harness/Harness.d.ts +32 -4
- package/dist/harness/Harness.js +32 -4
- package/dist/helpers/setup.js +6 -3
- package/dist/helpers/setupLocalTesting.js +12 -4
- package/dist/helpers/testFixtures.d.ts +5 -4
- package/dist/helpers/testFixtures.js +4 -5
- package/dist/index.d.ts +3 -1
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.js +8 -4
- package/dist/templates/tests/Counter.test.ts +6 -5
- package/dist/types/runtime.d.ts +2 -0
- package/dist/utils/parseCliOutput.d.ts +6 -3
- package/dist/utils/parseCliOutput.js +10 -5
- package/package.json +1 -1
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import type { RunResult } from "../utils/childProcessAdapter.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the tsx CLI entrypoint (`<tsx-pkg>/dist/cli.mjs`) used by
|
|
4
|
+
* `movehat run` to execute user scripts. Prefers movehat's bundled tsx
|
|
5
|
+
* by default; falls back to the cwd's tsx only if bundled is missing
|
|
6
|
+
* (defensive — should not happen for normal installs). Set
|
|
7
|
+
* `MOVEHAT_TSX_FROM_CWD=1` or pass `preferCwd: true` to flip the
|
|
8
|
+
* order — power-users who pinned a different tsx in their project.
|
|
9
|
+
*
|
|
10
|
+
* Security: the default order closes #52 (untrusted cwd could ship a
|
|
11
|
+
* malicious `node_modules/tsx/dist/cli.mjs`).
|
|
12
|
+
*
|
|
13
|
+
* Exported so the resolution logic can be unit-tested without
|
|
14
|
+
* spawning a real process.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveTsxCliPath(opts?: {
|
|
17
|
+
preferCwd?: boolean;
|
|
18
|
+
}): string | null;
|
|
2
19
|
/**
|
|
3
20
|
* Apply the exit policy for a child whose output was inherited by the
|
|
4
21
|
* parent. When the child dies via signal, re-raise it on the parent so
|
package/dist/commands/run.js
CHANGED
|
@@ -4,6 +4,45 @@ import { fileURLToPath } from "url";
|
|
|
4
4
|
import { createRequire } from "module";
|
|
5
5
|
import { runCli } from "../utils/runCli.js";
|
|
6
6
|
import { logger } from "../ui/index.js";
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the tsx CLI entrypoint (`<tsx-pkg>/dist/cli.mjs`) used by
|
|
11
|
+
* `movehat run` to execute user scripts. Prefers movehat's bundled tsx
|
|
12
|
+
* by default; falls back to the cwd's tsx only if bundled is missing
|
|
13
|
+
* (defensive — should not happen for normal installs). Set
|
|
14
|
+
* `MOVEHAT_TSX_FROM_CWD=1` or pass `preferCwd: true` to flip the
|
|
15
|
+
* order — power-users who pinned a different tsx in their project.
|
|
16
|
+
*
|
|
17
|
+
* Security: the default order closes #52 (untrusted cwd could ship a
|
|
18
|
+
* malicious `node_modules/tsx/dist/cli.mjs`).
|
|
19
|
+
*
|
|
20
|
+
* Exported so the resolution logic can be unit-tested without
|
|
21
|
+
* spawning a real process.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveTsxCliPath(opts) {
|
|
24
|
+
const preferCwd = opts?.preferCwd ?? process.env.MOVEHAT_TSX_FROM_CWD === "1";
|
|
25
|
+
const bundledRoot = __dirname;
|
|
26
|
+
const cwdRoot = process.cwd();
|
|
27
|
+
const lookupOrder = preferCwd
|
|
28
|
+
? [cwdRoot, bundledRoot]
|
|
29
|
+
: [bundledRoot, cwdRoot];
|
|
30
|
+
for (const root of lookupOrder) {
|
|
31
|
+
try {
|
|
32
|
+
const tsxEntry = requireFromHere.resolve("tsx", { paths: [root] });
|
|
33
|
+
// require.resolve("tsx") returns .../tsx/dist/loader.mjs; walk up
|
|
34
|
+
// to the package root and into dist/cli.mjs.
|
|
35
|
+
const packageRoot = dirname(dirname(tsxEntry));
|
|
36
|
+
const cliPath = join(packageRoot, "dist", "cli.mjs");
|
|
37
|
+
if (existsSync(cliPath))
|
|
38
|
+
return cliPath;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Lookup failed at this root; try the next one.
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
7
46
|
/**
|
|
8
47
|
* Apply the exit policy for a child whose output was inherited by the
|
|
9
48
|
* parent. When the child dies via signal, re-raise it on the parent so
|
|
@@ -50,39 +89,14 @@ export default async function runCommand(scriptPath) {
|
|
|
50
89
|
logger.plain(` Network: ${network}`);
|
|
51
90
|
}
|
|
52
91
|
logger.newline();
|
|
53
|
-
// Find tsx binary -
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let tsxPath;
|
|
60
|
-
try {
|
|
61
|
-
// Try to resolve tsx package from user's project first
|
|
62
|
-
const tsxPackagePath = require.resolve("tsx", { paths: [process.cwd()] });
|
|
63
|
-
// require.resolve("tsx") returns .../tsx/dist/loader.mjs
|
|
64
|
-
// We need to go up to the tsx package root, then into dist/cli.mjs
|
|
65
|
-
const tsxPackageRoot = dirname(dirname(tsxPackagePath));
|
|
66
|
-
tsxPath = join(tsxPackageRoot, "dist", "cli.mjs");
|
|
67
|
-
// Verify the file exists
|
|
68
|
-
if (!existsSync(tsxPath)) {
|
|
69
|
-
throw new Error("cli.mjs not found");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
try {
|
|
74
|
-
// Fallback to movehat's own tsx
|
|
75
|
-
const tsxPackagePath = require.resolve("tsx", { paths: [__dirname] });
|
|
76
|
-
const tsxPackageRoot = dirname(dirname(tsxPackagePath));
|
|
77
|
-
tsxPath = join(tsxPackageRoot, "dist", "cli.mjs");
|
|
78
|
-
if (!existsSync(tsxPath)) {
|
|
79
|
-
throw new Error("cli.mjs not found");
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
tsxPath = "";
|
|
84
|
-
}
|
|
92
|
+
// Find tsx binary — bundled-first per #52 (supply-chain hardening).
|
|
93
|
+
// Cwd resolution stays available behind an opt-in env var for users
|
|
94
|
+
// who pinned a different tsx in their project.
|
|
95
|
+
if (process.env.MOVEHAT_TSX_FROM_CWD === "1") {
|
|
96
|
+
logger.warning("MOVEHAT_TSX_FROM_CWD=1: resolving tsx from cwd first. " +
|
|
97
|
+
"Only use this in trusted project directories.");
|
|
85
98
|
}
|
|
99
|
+
const tsxPath = resolveTsxCliPath();
|
|
86
100
|
if (!tsxPath) {
|
|
87
101
|
logger.error("tsx binary not found");
|
|
88
102
|
logger.plain(" Make sure 'tsx' is installed in your project:");
|
|
@@ -14,183 +14,165 @@ export interface SaveAccountPoolOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
includeImported?: boolean | undefined;
|
|
16
16
|
}
|
|
17
|
+
export interface AccountManagerOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Filesystem location where `saveAccountPool` writes `test-pool.json`
|
|
20
|
+
* and `loadAccountPool` reads from. When omitted, the path is computed
|
|
21
|
+
* LAZILY on each call from `join(process.cwd(), ".movehat", "accounts")`
|
|
22
|
+
* — so `process.chdir()` between construction and pool I/O is respected.
|
|
23
|
+
*
|
|
24
|
+
* Pass an explicit value when per-instance isolation matters (parallel
|
|
25
|
+
* test files, harness pools that must not collide with another suite's).
|
|
26
|
+
*
|
|
27
|
+
* The process-wide static facade exposed on the `AccountManager` class
|
|
28
|
+
* itself uses a separate singleton whose `poolPath` is EAGERLY captured
|
|
29
|
+
* at module-import time. That preserves the legacy F8(b) behavior for
|
|
30
|
+
* any code still on the static API during the 0.2.7 deprecation window;
|
|
31
|
+
* the static facade is removed in 0.3.0.
|
|
32
|
+
*/
|
|
33
|
+
poolPath?: string | undefined;
|
|
34
|
+
}
|
|
17
35
|
/**
|
|
18
36
|
* Centralized Account Manager for movehat
|
|
19
37
|
*
|
|
20
38
|
* Manages all account creation, loading, and lifecycle operations.
|
|
21
|
-
* Provides a pool of reusable test accounts with labels for better test
|
|
39
|
+
* Provides a pool of reusable test accounts with labels for better test
|
|
40
|
+
* readability.
|
|
41
|
+
*
|
|
42
|
+
* Two API surfaces are exposed:
|
|
43
|
+
*
|
|
44
|
+
* **Instance API (recommended; M9.1+)** — `new AccountManager(options?)`
|
|
45
|
+
* gives a fully isolated pool. Two instances in the same process have
|
|
46
|
+
* independent labelMaps, private-key maps, and account pools. Each
|
|
47
|
+
* `Harness` constructed in 0.3.0+ will own one of these; user code
|
|
48
|
+
* accesses labeled accounts via `harness.accounts.<label>` (Harness
|
|
49
|
+
* snapshots them at construction time).
|
|
50
|
+
*
|
|
51
|
+
* **Static facade (deprecated; will be removed in 0.3.0)** — every
|
|
52
|
+
* former static method (`AccountManager.createAccount(...)`, etc.) still
|
|
53
|
+
* works and forwards to a single process-wide singleton. This preserves
|
|
54
|
+
* the existing label-sharing behavior across calls during the
|
|
55
|
+
* deprecation window. Migration target is the instance API; see M9 meta
|
|
56
|
+
* (#270) and migration guide at `/docs/upgrading/0.3.0` (published in
|
|
57
|
+
* M9.4).
|
|
22
58
|
*/
|
|
23
59
|
export declare class AccountManager {
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
60
|
+
private readonly pool;
|
|
61
|
+
private readonly privateKeys;
|
|
62
|
+
private readonly labelMap;
|
|
63
|
+
private readonly generatedAccountAddresses;
|
|
64
|
+
private poolLoaded;
|
|
65
|
+
private readonly poolPathOverride;
|
|
66
|
+
constructor(options?: AccountManagerOptions);
|
|
67
|
+
/**
|
|
68
|
+
* Resolved pool directory. When the caller supplied an explicit
|
|
69
|
+
* `poolPath` to the constructor, that value is returned verbatim.
|
|
70
|
+
* Otherwise the path is computed LAZILY from the current
|
|
71
|
+
* `process.cwd()` on each access — so `process.chdir()` performed
|
|
72
|
+
* between construction and pool I/O takes effect, unlike the legacy
|
|
73
|
+
* static-only API which captured cwd at module import time
|
|
74
|
+
* (audit finding F8(b)).
|
|
75
|
+
*/
|
|
76
|
+
private get poolPath();
|
|
77
|
+
/**
|
|
78
|
+
* Get a test account from the pool. If label is provided and exists,
|
|
79
|
+
* returns that account. Otherwise creates a new account with the
|
|
80
|
+
* optional label.
|
|
81
|
+
*
|
|
82
|
+
* @param label Optional label for the account (e.g., "alice", "bob")
|
|
35
83
|
* @returns An Account instance
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* const alice = AccountManager.getTestAccount("alice");
|
|
39
|
-
* const randomAccount = AccountManager.getTestAccount();
|
|
40
84
|
*/
|
|
41
|
-
|
|
85
|
+
getTestAccount(label?: string): Account;
|
|
42
86
|
/**
|
|
43
|
-
* Create a new account and optionally add it to the pool with a
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* @param fund Whether to fund the account (handled externally)
|
|
47
|
-
* @returns A new Account instance
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* const deployer = AccountManager.createAccount("deployer");
|
|
51
|
-
* const bob = AccountManager.createAccount("bob", true);
|
|
87
|
+
* Create a new account and optionally add it to the pool with a
|
|
88
|
+
* label. The `fund` parameter is accepted for API symmetry; actual
|
|
89
|
+
* funding is the caller's responsibility.
|
|
52
90
|
*/
|
|
53
|
-
|
|
91
|
+
createAccount(label?: string, _fund?: boolean): Account;
|
|
54
92
|
/**
|
|
55
|
-
* Get an account by its label
|
|
56
|
-
*
|
|
57
|
-
* @param label The label to look up
|
|
58
|
-
* @returns The Account if found, undefined otherwise
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* const alice = AccountManager.getAccountByLabel("alice");
|
|
62
|
-
* if (alice) {
|
|
63
|
-
* console.log(`Alice's address: ${alice.accountAddress.toString()}`);
|
|
64
|
-
* }
|
|
93
|
+
* Get an account by its label, or undefined if not present.
|
|
65
94
|
*/
|
|
66
|
-
|
|
95
|
+
getAccountByLabel(label: string): Account | undefined;
|
|
67
96
|
/**
|
|
68
|
-
* Load account from environment variable
|
|
69
|
-
*
|
|
70
|
-
* @param envVar The environment variable name (defaults to "PRIVATE_KEY")
|
|
71
|
-
* @returns Account instance
|
|
72
|
-
* @throws Error if environment variable is not set
|
|
97
|
+
* Load account from environment variable.
|
|
73
98
|
*
|
|
74
|
-
* @
|
|
75
|
-
* const account = AccountManager.loadAccountFromEnv("MH_PRIVATE_KEY");
|
|
99
|
+
* @throws Error if the environment variable is not set
|
|
76
100
|
*/
|
|
77
|
-
|
|
101
|
+
loadAccountFromEnv(envVar?: string): Account;
|
|
78
102
|
/**
|
|
79
|
-
* Load account from a private key hex string
|
|
80
|
-
*
|
|
81
|
-
* @param privateKeyHex The private key as a hex string (with or without 0x prefix)
|
|
82
|
-
* @returns Account instance
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* const account = AccountManager.loadAccountFromPrivateKey("0xabc123...");
|
|
103
|
+
* Load account from a private key hex string (with or without 0x prefix).
|
|
86
104
|
*/
|
|
87
|
-
|
|
105
|
+
loadAccountFromPrivateKey(privateKeyHex: string): Account;
|
|
88
106
|
/**
|
|
89
|
-
* Load all accounts from movehat config
|
|
90
|
-
*
|
|
91
|
-
* @param config The resolved MovehatConfig
|
|
92
|
-
* @returns Array of Account instances
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* const config = await resolveNetworkConfig(userConfig);
|
|
96
|
-
* const accounts = AccountManager.loadAccountsFromConfig(config);
|
|
107
|
+
* Load all accounts from movehat config.
|
|
97
108
|
*/
|
|
98
|
-
|
|
109
|
+
loadAccountsFromConfig(config: MovehatConfig): Account[];
|
|
99
110
|
/**
|
|
100
|
-
* Get all labeled accounts in the pool
|
|
101
|
-
*
|
|
102
|
-
* @returns Record of label to Account mappings
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* const labeled = AccountManager.getLabeledAccounts();
|
|
106
|
-
* console.log(`Deployer: ${labeled.deployer?.accountAddress.toString()}`);
|
|
111
|
+
* Get all labeled accounts in the pool.
|
|
107
112
|
*/
|
|
108
|
-
|
|
113
|
+
getLabeledAccounts(): Record<string, Account>;
|
|
109
114
|
/**
|
|
110
|
-
* Save the current account pool to disk for persistence
|
|
111
|
-
*
|
|
112
|
-
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* AccountManager.saveAccountPool();
|
|
115
|
+
* Save the current account pool to disk for persistence.
|
|
116
116
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
saveAccountPool(): void;
|
|
118
|
+
saveAccountPool(poolPath: string): void;
|
|
119
|
+
saveAccountPool(options: SaveAccountPoolOptions): void;
|
|
120
|
+
saveAccountPool(poolPath: string, options: SaveAccountPoolOptions): void;
|
|
121
121
|
/**
|
|
122
|
-
* Load account pool from disk
|
|
123
|
-
*
|
|
124
|
-
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
125
|
-
* @returns true if pool was loaded, false if file doesn't exist
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* if (AccountManager.loadAccountPool()) {
|
|
129
|
-
* console.log("Pool loaded successfully");
|
|
130
|
-
* }
|
|
122
|
+
* Load account pool from disk. Returns true if a pool file was found
|
|
123
|
+
* and parsed, false if the file does not exist or parsing failed.
|
|
131
124
|
*/
|
|
132
|
-
|
|
125
|
+
loadAccountPool(poolPath?: string): boolean;
|
|
133
126
|
/**
|
|
134
|
-
* Clear the entire account pool
|
|
135
|
-
* Useful for test isolation
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* after(() => {
|
|
139
|
-
* AccountManager.clearPool();
|
|
140
|
-
* });
|
|
127
|
+
* Clear the entire account pool. Useful for test isolation.
|
|
141
128
|
*/
|
|
142
|
-
|
|
129
|
+
clearPool(): void;
|
|
143
130
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @returns Number of accounts in the pool
|
|
131
|
+
* Number of accounts in the pool.
|
|
147
132
|
*/
|
|
148
|
-
|
|
133
|
+
getPoolSize(): number;
|
|
149
134
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* @returns Array of all Account instances
|
|
135
|
+
* All accounts in the pool.
|
|
153
136
|
*/
|
|
154
|
-
|
|
137
|
+
getAllAccounts(): Account[];
|
|
155
138
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* @param label The label to check
|
|
159
|
-
* @returns true if label exists, false otherwise
|
|
139
|
+
* Whether a label is currently bound to an account in this pool.
|
|
160
140
|
*/
|
|
161
|
-
|
|
141
|
+
hasLabel(label: string): boolean;
|
|
162
142
|
/**
|
|
163
|
-
* Get or create an account with a specific label
|
|
164
|
-
* If the label exists, returns the existing account
|
|
165
|
-
* Otherwise creates a new account with that label
|
|
166
|
-
*
|
|
167
|
-
* @param label The label for the account
|
|
168
|
-
* @returns Account instance
|
|
169
|
-
*
|
|
170
|
-
* @example
|
|
171
|
-
* const alice = AccountManager.getOrCreateLabeled("alice");
|
|
172
|
-
* const aliceAgain = AccountManager.getOrCreateLabeled("alice"); // Same account
|
|
143
|
+
* Get or create an account with a specific label.
|
|
173
144
|
*/
|
|
174
|
-
|
|
145
|
+
getOrCreateLabeled(label: string): Account;
|
|
175
146
|
/**
|
|
176
|
-
* Batch create multiple labeled accounts
|
|
177
|
-
*
|
|
178
|
-
* @param labels Array of labels to create
|
|
179
|
-
* @returns Record of label to Account mappings
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* const accounts = AccountManager.createBatch(["alice", "bob", "charlie"]);
|
|
183
|
-
* console.log(accounts.alice.accountAddress.toString());
|
|
147
|
+
* Batch create multiple labeled accounts.
|
|
184
148
|
*/
|
|
185
|
-
|
|
149
|
+
createBatch(labels: readonly string[]): Record<string, Account>;
|
|
186
150
|
/**
|
|
187
|
-
* Export account private keys for backup/sharing
|
|
188
|
-
* WARNING: Only use this for test accounts, never production keys
|
|
189
|
-
*
|
|
190
|
-
* @param labels Optional array of labels to export (exports all if not provided)
|
|
191
|
-
* @returns Record of label/address to private key hex string
|
|
151
|
+
* Export account private keys for backup/sharing.
|
|
152
|
+
* WARNING: Only use this for test accounts, never production keys.
|
|
192
153
|
*/
|
|
154
|
+
exportPrivateKeys(labels?: string[]): Record<string, string>;
|
|
155
|
+
private accountFromPrivateKey;
|
|
156
|
+
private trackAccount;
|
|
157
|
+
static getTestAccount(label?: string): Account;
|
|
158
|
+
static createAccount(label?: string, fund?: boolean): Account;
|
|
159
|
+
static getAccountByLabel(label: string): Account | undefined;
|
|
160
|
+
static loadAccountFromEnv(envVar?: string): Account;
|
|
161
|
+
static loadAccountFromPrivateKey(privateKeyHex: string): Account;
|
|
162
|
+
static loadAccountsFromConfig(config: MovehatConfig): Account[];
|
|
163
|
+
static getLabeledAccounts(): Record<string, Account>;
|
|
164
|
+
static saveAccountPool(): void;
|
|
165
|
+
static saveAccountPool(poolPath: string): void;
|
|
166
|
+
static saveAccountPool(options: SaveAccountPoolOptions): void;
|
|
167
|
+
static saveAccountPool(poolPath: string, options: SaveAccountPoolOptions): void;
|
|
168
|
+
static loadAccountPool(poolPath?: string): boolean;
|
|
169
|
+
static clearPool(): void;
|
|
170
|
+
static getPoolSize(): number;
|
|
171
|
+
static getAllAccounts(): Account[];
|
|
172
|
+
static hasLabel(label: string): boolean;
|
|
173
|
+
static getOrCreateLabeled(label: string): Account;
|
|
174
|
+
static createBatch(labels: readonly string[]): Record<string, Account>;
|
|
193
175
|
static exportPrivateKeys(labels?: string[]): Record<string, string>;
|
|
194
|
-
private static accountFromPrivateKey;
|
|
195
|
-
private static trackAccount;
|
|
196
176
|
}
|
|
177
|
+
/** @internal — test-only. Resets the once-per-method dedup Set. */
|
|
178
|
+
export declare function _resetDeprecationWarnings(): void;
|