movehat 0.2.2 → 0.2.4
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/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +19 -10
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/test.js +12 -19
- package/dist/commands/test.js.map +1 -1
- package/dist/core/Publisher.d.ts.map +1 -1
- package/dist/core/Publisher.js +20 -14
- package/dist/core/Publisher.js.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +8 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/deployments.d.ts.map +1 -1
- package/dist/core/deployments.js +4 -2
- package/dist/core/deployments.js.map +1 -1
- package/dist/fork/manager.d.ts +1 -1
- package/dist/fork/manager.js +11 -11
- package/dist/fork/manager.js.map +1 -1
- package/dist/fork/server.d.ts.map +1 -1
- package/dist/fork/server.js +21 -15
- package/dist/fork/server.js.map +1 -1
- package/dist/fork/test.d.ts.map +1 -1
- package/dist/fork/test.js +3 -2
- package/dist/fork/test.js.map +1 -1
- package/dist/harness/codeObject.js +11 -8
- package/dist/harness/codeObject.js.map +1 -1
- package/dist/harness/script.d.ts.map +1 -1
- package/dist/harness/script.js +9 -6
- package/dist/harness/script.js.map +1 -1
- package/dist/helpers/setupLocalTesting.js +5 -5
- package/dist/helpers/setupLocalTesting.js.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +1 -1
- package/dist/node/LocalNodeManager.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.js +61 -23
- package/dist/node/LocalNodeManager.js.map +1 -1
- package/dist/node/__tests__/LocalNodeManager.test.js +110 -11
- package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -1
- package/dist/ui/__tests__/logger.test.d.ts +2 -0
- package/dist/ui/__tests__/logger.test.d.ts.map +1 -0
- package/dist/ui/__tests__/logger.test.js +75 -0
- package/dist/ui/__tests__/logger.test.js.map +1 -0
- package/dist/ui/formatters.d.ts +0 -16
- package/dist/ui/formatters.d.ts.map +1 -1
- package/dist/ui/formatters.js +1 -1
- package/dist/ui/formatters.js.map +1 -1
- package/dist/ui/logger.d.ts +41 -0
- package/dist/ui/logger.d.ts.map +1 -1
- package/dist/ui/logger.js +49 -0
- package/dist/ui/logger.js.map +1 -1
- package/dist/ui/spinner.d.ts +25 -0
- package/dist/ui/spinner.d.ts.map +1 -1
- package/dist/ui/spinner.js +44 -0
- package/dist/ui/spinner.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +4 -0
- package/src/commands/compile.ts +24 -15
- package/src/commands/test.ts +12 -19
- package/src/core/Publisher.ts +49 -34
- package/src/core/config.ts +9 -6
- package/src/core/deployments.ts +5 -4
- package/src/fork/manager.ts +11 -11
- package/src/fork/server.ts +21 -15
- package/src/fork/test.ts +3 -2
- package/src/harness/codeObject.ts +8 -5
- package/src/harness/script.ts +7 -4
- package/src/helpers/setupLocalTesting.ts +5 -5
- package/src/node/LocalNodeManager.ts +64 -25
- package/src/node/__tests__/LocalNodeManager.test.ts +140 -14
- package/src/types/config.ts +1 -1
- package/src/ui/__tests__/logger.test.ts +89 -0
- package/src/ui/formatters.ts +1 -1
- package/src/ui/logger.ts +62 -0
- package/src/ui/spinner.ts +47 -0
package/dist/ui/logger.d.ts
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Available log levels
|
|
3
3
|
*/
|
|
4
4
|
export type LogLevel = 'info' | 'success' | 'error' | 'warning' | 'debug';
|
|
5
|
+
/**
|
|
6
|
+
* Verbosity level for subprocess output and gray-prefixed chatter.
|
|
7
|
+
* - `quiet` — reserved; currently behaves like `normal`
|
|
8
|
+
* - `normal` — default; system logs only, subprocess chatter hidden
|
|
9
|
+
* - `verbose` — surface subprocess stdout with a muted gray `›` prefix
|
|
10
|
+
*/
|
|
11
|
+
export type Verbosity = 'quiet' | 'normal' | 'verbose';
|
|
5
12
|
/**
|
|
6
13
|
* Logger configuration options
|
|
7
14
|
*/
|
|
@@ -12,7 +19,16 @@ export interface LoggerConfig {
|
|
|
12
19
|
level?: LogLevel;
|
|
13
20
|
/** Include timestamps in log messages */
|
|
14
21
|
timestamp?: boolean;
|
|
22
|
+
/** Verbosity level for subprocess output */
|
|
23
|
+
verbosity?: Verbosity;
|
|
15
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether subprocess chatter should reach the user's terminal.
|
|
27
|
+
* Honors both the in-process config (set by the `-v` CLI flag's
|
|
28
|
+
* preAction hook) and the `MOVEHAT_VERBOSE=1` env var (which lets
|
|
29
|
+
* callers opt in before the CLI parses args, e.g. in shell scripts).
|
|
30
|
+
*/
|
|
31
|
+
export declare const isVerbose: () => boolean;
|
|
16
32
|
/**
|
|
17
33
|
* Configure logger globally
|
|
18
34
|
*
|
|
@@ -124,6 +140,28 @@ export declare const newline: () => void;
|
|
|
124
140
|
* logger.kv('Network', 'testnet', 2);
|
|
125
141
|
*/
|
|
126
142
|
export declare const section: (title: string) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Single muted horizontal rule. Use to close out a phase or to
|
|
145
|
+
* visually separate output sections.
|
|
146
|
+
*/
|
|
147
|
+
export declare const divider: () => void;
|
|
148
|
+
/**
|
|
149
|
+
* Phase header — renders a muted top rule, a bold brand-colored title
|
|
150
|
+
* indented two spaces, and a muted bottom rule. Use at top-level phase
|
|
151
|
+
* boundaries (local node start, deploy flow, test orchestrator
|
|
152
|
+
* sections) so the user can visually anchor where one phase ends and
|
|
153
|
+
* the next begins.
|
|
154
|
+
*
|
|
155
|
+
* @param title - Phase title (e.g. "Local Movement node")
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* logger.phase('Local Movement node');
|
|
159
|
+
* // Renders:
|
|
160
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
161
|
+
* // Local Movement node
|
|
162
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
163
|
+
*/
|
|
164
|
+
export declare const phase: (title: string) => void;
|
|
127
165
|
/**
|
|
128
166
|
* Key-value pair
|
|
129
167
|
* Use for displaying structured data
|
|
@@ -163,6 +201,7 @@ export declare const item: (text: string, indent?: number) => void;
|
|
|
163
201
|
*/
|
|
164
202
|
export declare const logger: {
|
|
165
203
|
configure: (newConfig: Partial<LoggerConfig>) => void;
|
|
204
|
+
isVerbose: () => boolean;
|
|
166
205
|
info: (message: string, indent?: number) => void;
|
|
167
206
|
success: (message: string, indent?: number) => void;
|
|
168
207
|
error: (message: string, indent?: number) => void;
|
|
@@ -171,6 +210,8 @@ export declare const logger: {
|
|
|
171
210
|
plain: (message: string) => void;
|
|
172
211
|
newline: () => void;
|
|
173
212
|
section: (title: string) => void;
|
|
213
|
+
phase: (title: string) => void;
|
|
214
|
+
divider: () => void;
|
|
174
215
|
kv: (key: string, value: string, indent?: number) => void;
|
|
175
216
|
item: (text: string, indent?: number) => void;
|
|
176
217
|
};
|
package/dist/ui/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAYD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,OAC0C,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,OAAO,CAAC,YAAY,CAAC,KAAG,IAElE,CAAC;AAUF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI3D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,KAAG,IAGvC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,QAAO,IAG1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,KAAG,IAGvC,CAAC;AAQF;;;GAGG;AACH,eAAO,MAAM,OAAO,QAAO,IAG1B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,IAMrC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,EAAE,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,SAAQ,MAAU,KAAG,IAInE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,SAAQ,MAAU,KAAG,IAIvD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;2BAzOwB,OAAO,CAAC,YAAY,CAAC,KAAG,IAAI;qBAf1C,OAAO;oBAsCN,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB9B,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBnC,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB/B,MAAM,WAAU,MAAM,KAAO,IAAI;oBAqBpC,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBhC,MAAM,KAAG,IAAI;mBAcjB,IAAI;qBAgBA,MAAM,KAAG,IAAI;mBAoCf,MAAM,KAAG,IAAI;mBArBf,IAAI;cAyCP,MAAM,SAAS,MAAM,WAAU,MAAM,KAAO,IAAI;iBAmB7C,MAAM,WAAU,MAAM,KAAO,IAAI;CA+B3D,CAAC"}
|
package/dist/ui/logger.js
CHANGED
|
@@ -7,7 +7,15 @@ let config = {
|
|
|
7
7
|
silent: false,
|
|
8
8
|
level: 'info',
|
|
9
9
|
timestamp: false,
|
|
10
|
+
verbosity: process.env.MOVEHAT_VERBOSE === '1' ? 'verbose' : 'normal',
|
|
10
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Whether subprocess chatter should reach the user's terminal.
|
|
14
|
+
* Honors both the in-process config (set by the `-v` CLI flag's
|
|
15
|
+
* preAction hook) and the `MOVEHAT_VERBOSE=1` env var (which lets
|
|
16
|
+
* callers opt in before the CLI parses args, e.g. in shell scripts).
|
|
17
|
+
*/
|
|
18
|
+
export const isVerbose = () => config.verbosity === 'verbose' || process.env.MOVEHAT_VERBOSE === '1';
|
|
11
19
|
/**
|
|
12
20
|
* Configure logger globally
|
|
13
21
|
*
|
|
@@ -165,6 +173,44 @@ export const section = (title) => {
|
|
|
165
173
|
return;
|
|
166
174
|
console.log(`\n${colors.brandBright(title)}`);
|
|
167
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* Width of the `━` rule used by `phase` and `divider`. Matched to a
|
|
178
|
+
* comfortable terminal width that fits in a side-by-side dev layout.
|
|
179
|
+
*/
|
|
180
|
+
const PHASE_RULE_WIDTH = 52;
|
|
181
|
+
/**
|
|
182
|
+
* Single muted horizontal rule. Use to close out a phase or to
|
|
183
|
+
* visually separate output sections.
|
|
184
|
+
*/
|
|
185
|
+
export const divider = () => {
|
|
186
|
+
if (config.silent)
|
|
187
|
+
return;
|
|
188
|
+
console.log(colors.muted('━'.repeat(PHASE_RULE_WIDTH)));
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Phase header — renders a muted top rule, a bold brand-colored title
|
|
192
|
+
* indented two spaces, and a muted bottom rule. Use at top-level phase
|
|
193
|
+
* boundaries (local node start, deploy flow, test orchestrator
|
|
194
|
+
* sections) so the user can visually anchor where one phase ends and
|
|
195
|
+
* the next begins.
|
|
196
|
+
*
|
|
197
|
+
* @param title - Phase title (e.g. "Local Movement node")
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* logger.phase('Local Movement node');
|
|
201
|
+
* // Renders:
|
|
202
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
203
|
+
* // Local Movement node
|
|
204
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
205
|
+
*/
|
|
206
|
+
export const phase = (title) => {
|
|
207
|
+
if (config.silent)
|
|
208
|
+
return;
|
|
209
|
+
const rule = colors.muted('━'.repeat(PHASE_RULE_WIDTH));
|
|
210
|
+
console.log(rule);
|
|
211
|
+
console.log(` ${colors.brandBright(title)}`);
|
|
212
|
+
console.log(rule);
|
|
213
|
+
};
|
|
168
214
|
/**
|
|
169
215
|
* Key-value pair
|
|
170
216
|
* Use for displaying structured data
|
|
@@ -214,6 +260,7 @@ export const item = (text, indent = 0) => {
|
|
|
214
260
|
*/
|
|
215
261
|
export const logger = {
|
|
216
262
|
configure: configureLogger,
|
|
263
|
+
isVerbose,
|
|
217
264
|
info,
|
|
218
265
|
success,
|
|
219
266
|
error,
|
|
@@ -222,6 +269,8 @@ export const logger = {
|
|
|
222
269
|
plain,
|
|
223
270
|
newline,
|
|
224
271
|
section,
|
|
272
|
+
phase,
|
|
273
|
+
divider,
|
|
225
274
|
kv,
|
|
226
275
|
item,
|
|
227
276
|
};
|
package/dist/ui/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/spinner.d.ts
CHANGED
|
@@ -65,6 +65,31 @@ export declare const spinner: (options: SpinnerOptions) => Ora;
|
|
|
65
65
|
* );
|
|
66
66
|
*/
|
|
67
67
|
export declare const withSpinner: <T>(startText: string, task: () => Promise<T>, successText?: string, errorText?: string, indent?: number) => Promise<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Execute async task with a spinner that updates its label with
|
|
70
|
+
* elapsed seconds while the task runs. Use for long-running phases
|
|
71
|
+
* (local node startup, publish + tx wait) where the user wants
|
|
72
|
+
* visible progress feedback in lieu of subprocess chatter.
|
|
73
|
+
*
|
|
74
|
+
* Pairs with the `§9` console-UX convention: any phase that
|
|
75
|
+
* empirically takes ≥3s in normal use should wrap its body in
|
|
76
|
+
* `withTimedSpinner` so the terminal never goes silent while work
|
|
77
|
+
* happens.
|
|
78
|
+
*
|
|
79
|
+
* @param label - Stable label shown next to the spinner (e.g. "Starting node")
|
|
80
|
+
* @param task - Async function to execute
|
|
81
|
+
* @param indent - Number of spaces to indent (default: 0)
|
|
82
|
+
* @returns Promise resolving to task result
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* await withTimedSpinner('Starting local node', async () => {
|
|
86
|
+
* await this.waitForReady(60_000);
|
|
87
|
+
* });
|
|
88
|
+
* // Renders: ⠋ Starting local node — 0.0s ... ⠼ Starting local node — 14.2s
|
|
89
|
+
* // On success: ✔ Starting local node (14.2s)
|
|
90
|
+
* // On error: ✖ <error.message>
|
|
91
|
+
*/
|
|
92
|
+
export declare const withTimedSpinner: <T>(label: string, task: () => Promise<T>, indent?: number) => Promise<T>;
|
|
68
93
|
/**
|
|
69
94
|
* Spinner chain for sequential operations
|
|
70
95
|
* Manages multiple spinners in sequence
|
package/dist/ui/spinner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,GAAG,EAAE,KAAK,OAAO,IAAI,UAAU,EAAE,MAAM,KAAK,CAAC;AAGhE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,KAAG,GAcjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,WAAW,MAAM,EACjB,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,cAAc,MAAM,EACpB,YAAY,MAAM,EAClB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAYX,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,QAAO,YA0BrC,CAAC"}
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,GAAG,EAAE,KAAK,OAAO,IAAI,UAAU,EAAE,MAAM,KAAK,CAAC;AAGhE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,KAAG,GAcjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,WAAW,MAAM,EACjB,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,cAAc,MAAM,EACpB,YAAY,MAAM,EAClB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAYX,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,GAAU,CAAC,EACtC,OAAO,MAAM,EACb,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAiBX,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,QAAO,YA0BrC,CAAC"}
|
package/dist/ui/spinner.js
CHANGED
|
@@ -72,6 +72,50 @@ export const withSpinner = async (startText, task, successText, errorText, inden
|
|
|
72
72
|
throw error;
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Execute async task with a spinner that updates its label with
|
|
77
|
+
* elapsed seconds while the task runs. Use for long-running phases
|
|
78
|
+
* (local node startup, publish + tx wait) where the user wants
|
|
79
|
+
* visible progress feedback in lieu of subprocess chatter.
|
|
80
|
+
*
|
|
81
|
+
* Pairs with the `§9` console-UX convention: any phase that
|
|
82
|
+
* empirically takes ≥3s in normal use should wrap its body in
|
|
83
|
+
* `withTimedSpinner` so the terminal never goes silent while work
|
|
84
|
+
* happens.
|
|
85
|
+
*
|
|
86
|
+
* @param label - Stable label shown next to the spinner (e.g. "Starting node")
|
|
87
|
+
* @param task - Async function to execute
|
|
88
|
+
* @param indent - Number of spaces to indent (default: 0)
|
|
89
|
+
* @returns Promise resolving to task result
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* await withTimedSpinner('Starting local node', async () => {
|
|
93
|
+
* await this.waitForReady(60_000);
|
|
94
|
+
* });
|
|
95
|
+
* // Renders: ⠋ Starting local node — 0.0s ... ⠼ Starting local node — 14.2s
|
|
96
|
+
* // On success: ✔ Starting local node (14.2s)
|
|
97
|
+
* // On error: ✖ <error.message>
|
|
98
|
+
*/
|
|
99
|
+
export const withTimedSpinner = async (label, task, indent = 0) => {
|
|
100
|
+
const start = Date.now();
|
|
101
|
+
const spin = spinner({ text: `${label} — 0.0s`, indent });
|
|
102
|
+
const timer = setInterval(() => {
|
|
103
|
+
spin.text = `${label} — ${((Date.now() - start) / 1000).toFixed(1)}s`;
|
|
104
|
+
}, 500);
|
|
105
|
+
try {
|
|
106
|
+
const result = await task();
|
|
107
|
+
spin.succeed(`${label} (${((Date.now() - start) / 1000).toFixed(1)}s)`);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
112
|
+
spin.fail(errMsg);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
clearInterval(timer);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
75
119
|
/**
|
|
76
120
|
* Create a sequential spinner chain
|
|
77
121
|
* Useful for multi-step processes like initialization
|
package/dist/ui/spinner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAA6C,MAAM,KAAK,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAqB7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAuB,EAAO,EAAE;IACtD,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEzE,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,UAAU,GAAe;QAC7B,IAAI,EAAE,YAAY,GAAG,IAAI;QACzB,KAAK;QACL,OAAO;QACP,6DAA6D;QAC7D,SAAS,EAAE,cAAc,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;KAC7D,CAAC;IAEF,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;AACjC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,SAAiB,EACjB,IAAsB,EACtB,WAAoB,EACpB,SAAkB,EAClB,SAAiB,CAAC,EACN,EAAE;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,WAAW,MAAM,EAAE,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAkBF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAiB,EAAE;IACnD,IAAI,cAAc,GAAe,IAAI,CAAC;IAEtC,OAAO;QACL,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,IAAsB,EACtB,SAAiB,CAAC;YAElB,cAAc,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;gBAC5B,cAAc,CAAC,OAAO,EAAE,CAAC;gBACzB,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,cAAc,CAAC,IAAI,EAAE,CAAC;gBACtB,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,QAAQ;YACN,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAI,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -50,6 +50,7 @@ program
|
|
|
50
50
|
.version(version)
|
|
51
51
|
.option('--network <name>', 'Network to use (testnet, mainnet, local, etc.)')
|
|
52
52
|
.option('--redeploy', 'Force redeploy even if already deployed')
|
|
53
|
+
.option('-v, --verbose', 'Show subprocess output (movement node, aptos move) for debugging')
|
|
53
54
|
.hook('preAction', (thisCommand) => {
|
|
54
55
|
// Store network option in environment for commands to access
|
|
55
56
|
const options = thisCommand.opts();
|
|
@@ -59,6 +60,9 @@ program
|
|
|
59
60
|
if (options.redeploy) {
|
|
60
61
|
process.env.MH_CLI_REDEPLOY = 'true';
|
|
61
62
|
}
|
|
63
|
+
if (options.verbose) {
|
|
64
|
+
process.env.MOVEHAT_VERBOSE = '1';
|
|
65
|
+
}
|
|
62
66
|
});
|
|
63
67
|
|
|
64
68
|
program
|
package/src/commands/compile.ts
CHANGED
|
@@ -2,7 +2,8 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { loadUserConfig } from "../core/config.js";
|
|
4
4
|
import { validatePathSafety } from "../core/shell.js";
|
|
5
|
-
import { logger } from "../ui/index.js";
|
|
5
|
+
import { logger, isVerbose } from "../ui/index.js";
|
|
6
|
+
import { withSpinner } from "../ui/spinner.js";
|
|
6
7
|
import { runCli } from "../utils/runCli.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -195,25 +196,33 @@ async function runMovementBuild(
|
|
|
195
196
|
args: readonly string[],
|
|
196
197
|
cwd: string
|
|
197
198
|
): Promise<void> {
|
|
198
|
-
// Use throwOnNonZeroExit:false so we can
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
const result = await
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
// Use throwOnNonZeroExit:false so we can route stdout/stderr through
|
|
200
|
+
// the §9 verbosity gate ourselves. On failure we surface everything;
|
|
201
|
+
// on success the chatter is hidden unless isVerbose().
|
|
202
|
+
const result = await withSpinner("Compiling Move package", () =>
|
|
203
|
+
runCli(
|
|
204
|
+
{
|
|
205
|
+
command: "movement",
|
|
206
|
+
args,
|
|
207
|
+
cwd,
|
|
208
|
+
timeoutMs: 120000, // 2 minutes for git dependency downloads
|
|
209
|
+
},
|
|
210
|
+
{ throwOnNonZeroExit: false }
|
|
211
|
+
),
|
|
209
212
|
);
|
|
210
213
|
|
|
211
|
-
if (result.stdout) console.log(result.stdout.trim());
|
|
212
|
-
if (result.stderr) console.error(result.stderr.trim());
|
|
213
|
-
|
|
214
214
|
if (result.exitCode !== 0) {
|
|
215
|
+
// Build failed — show the user everything we have so they can debug.
|
|
216
|
+
if (result.stdout) logger.plain(result.stdout.trim());
|
|
217
|
+
if (result.stderr) logger.plain(result.stderr.trim());
|
|
215
218
|
throw new Error(`movement move build exited with code ${result.exitCode}`);
|
|
216
219
|
}
|
|
220
|
+
|
|
221
|
+
// Success path: route output through the verbosity gate.
|
|
222
|
+
if (isVerbose()) {
|
|
223
|
+
if (result.stdout) logger.info(result.stdout.trim(), 2);
|
|
224
|
+
if (result.stderr) logger.info(result.stderr.trim(), 2);
|
|
225
|
+
}
|
|
217
226
|
}
|
|
218
227
|
|
|
219
228
|
/**
|
package/src/commands/test.ts
CHANGED
|
@@ -97,8 +97,7 @@ async function showTestMenu(): Promise<TestType | undefined> {
|
|
|
97
97
|
*/
|
|
98
98
|
async function runMoveTestsOnly(filter?: string): Promise<void> {
|
|
99
99
|
logger.newline();
|
|
100
|
-
|
|
101
|
-
console.log(colors.muted("─".repeat(50)));
|
|
100
|
+
logger.phase("Move Unit Tests");
|
|
102
101
|
logger.newline();
|
|
103
102
|
|
|
104
103
|
try {
|
|
@@ -118,8 +117,7 @@ async function runMoveTestsOnly(filter?: string): Promise<void> {
|
|
|
118
117
|
*/
|
|
119
118
|
async function runTypeScriptTestsOnly(watch: boolean = false): Promise<void> {
|
|
120
119
|
logger.newline();
|
|
121
|
-
|
|
122
|
-
console.log(colors.muted("─".repeat(50)));
|
|
120
|
+
logger.phase("TypeScript Integration Tests");
|
|
123
121
|
|
|
124
122
|
if (!watch) {
|
|
125
123
|
logger.newline();
|
|
@@ -146,13 +144,11 @@ async function runTypeScriptTestsOnly(watch: boolean = false): Promise<void> {
|
|
|
146
144
|
*/
|
|
147
145
|
async function runAllTests(filter?: string): Promise<void> {
|
|
148
146
|
logger.newline();
|
|
149
|
-
|
|
150
|
-
console.log(colors.muted("═".repeat(50)));
|
|
147
|
+
logger.phase("Running All Tests");
|
|
151
148
|
|
|
152
149
|
// Section 1: Move Tests
|
|
153
150
|
logger.newline();
|
|
154
|
-
|
|
155
|
-
console.log(colors.muted("─".repeat(50)));
|
|
151
|
+
logger.phase("1. Move Unit Tests");
|
|
156
152
|
logger.newline();
|
|
157
153
|
|
|
158
154
|
try {
|
|
@@ -163,28 +159,25 @@ async function runAllTests(filter?: string): Promise<void> {
|
|
|
163
159
|
} catch (error) {
|
|
164
160
|
logger.newline();
|
|
165
161
|
logger.error("Move tests failed");
|
|
166
|
-
|
|
162
|
+
logger.divider();
|
|
167
163
|
process.exit(1);
|
|
168
164
|
}
|
|
169
165
|
|
|
170
166
|
// Section 2: TypeScript Tests
|
|
171
167
|
logger.newline();
|
|
172
|
-
|
|
173
|
-
logger.newline();
|
|
174
|
-
console.log(`${colors.brandBright("2.")} ${colors.bold("TypeScript Integration Tests")}`);
|
|
175
|
-
console.log(colors.muted("─".repeat(50)));
|
|
168
|
+
logger.phase("2. TypeScript Integration Tests");
|
|
176
169
|
logger.newline();
|
|
177
170
|
|
|
178
171
|
try {
|
|
179
172
|
await runTypeScriptTests(false);
|
|
180
173
|
logger.newline();
|
|
181
|
-
|
|
174
|
+
logger.divider();
|
|
182
175
|
logger.newline();
|
|
183
176
|
logger.success("All tests passed!");
|
|
184
177
|
logger.newline();
|
|
185
178
|
} catch (error) {
|
|
186
179
|
logger.newline();
|
|
187
|
-
|
|
180
|
+
logger.divider();
|
|
188
181
|
const message = error instanceof Error ? error.message : String(error);
|
|
189
182
|
logger.error(message);
|
|
190
183
|
process.exit(1);
|
|
@@ -198,8 +191,8 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
|
|
|
198
191
|
const testDir = join(process.cwd(), "tests");
|
|
199
192
|
|
|
200
193
|
if (!existsSync(testDir)) {
|
|
201
|
-
|
|
202
|
-
|
|
194
|
+
logger.plain(`${colors.muted(symbols.info)} No TypeScript tests found ${colors.muted("(tests/ directory not found)")}`);
|
|
195
|
+
logger.plain(` ${colors.muted("Skipping TypeScript tests...")}`);
|
|
203
196
|
logger.newline();
|
|
204
197
|
return;
|
|
205
198
|
}
|
|
@@ -208,7 +201,7 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
|
|
|
208
201
|
|
|
209
202
|
if (!existsSync(mochaPath)) {
|
|
210
203
|
logger.error("Mocha not found in project dependencies");
|
|
211
|
-
|
|
204
|
+
logger.plain(` ${colors.muted("Install it with:")} ${colors.info("npm install --save-dev mocha")}`);
|
|
212
205
|
throw new Error("Mocha not found");
|
|
213
206
|
}
|
|
214
207
|
|
|
@@ -232,7 +225,7 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
|
|
|
232
225
|
process.exit(1);
|
|
233
226
|
});
|
|
234
227
|
|
|
235
|
-
|
|
228
|
+
logger.plain(`${colors.info(symbols.info)} Watch mode active. Press Ctrl+C to exit.`);
|
|
236
229
|
logger.newline();
|
|
237
230
|
return;
|
|
238
231
|
}
|
package/src/core/Publisher.ts
CHANGED
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
import { validatePathSafety } from "./shell.js";
|
|
11
11
|
import { CliExecutionError, ModuleAlreadyDeployedError, PostPublishError } from "../errors.js";
|
|
12
12
|
import { runCli } from "../utils/runCli.js";
|
|
13
|
-
import { logger } from "../ui/index.js";
|
|
13
|
+
import { logger, isVerbose } from "../ui/index.js";
|
|
14
|
+
import { withSpinner } from "../ui/spinner.js";
|
|
14
15
|
import type { ChildProcessAdapter } from "../utils/childProcessAdapter.js";
|
|
15
16
|
import {
|
|
16
17
|
writeTempKeyFile,
|
|
@@ -122,19 +123,23 @@ export class Publisher {
|
|
|
122
123
|
: [];
|
|
123
124
|
|
|
124
125
|
// Build first with named addresses
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
const buildResult = await withSpinner(
|
|
127
|
+
"Building package",
|
|
128
|
+
() =>
|
|
129
|
+
runCli(
|
|
130
|
+
{
|
|
131
|
+
command: "movement",
|
|
132
|
+
args: ["move", "build", "--package-dir", safeDir, ...namedAddrArgs],
|
|
133
|
+
timeoutMs: 120000, // 2 minutes for git dependency downloads
|
|
134
|
+
},
|
|
135
|
+
{ adapter: this.deps.adapter }
|
|
136
|
+
),
|
|
133
137
|
);
|
|
134
|
-
if (
|
|
138
|
+
if (isVerbose() && buildResult.stdout) {
|
|
139
|
+
logger.info(buildResult.stdout.trim(), 2);
|
|
140
|
+
}
|
|
135
141
|
|
|
136
142
|
// Publish using direct parameters (avoid config file issues)
|
|
137
|
-
logger.step("Publishing to blockchain...");
|
|
138
143
|
|
|
139
144
|
// Format the private key into AIP-80 shape so the Movement CLI
|
|
140
145
|
// doesn't emit its raw-hex deprecation warning. `formatPrivateKey`
|
|
@@ -179,31 +184,41 @@ export class Publisher {
|
|
|
179
184
|
// stdout/stderr redaction still applies as defense in depth
|
|
180
185
|
// for any `ed25519-priv-…` substring that surfaces in CLI
|
|
181
186
|
// output (Movement CLI sometimes echoes the key on error).
|
|
182
|
-
const publishResult = await
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
187
|
+
const publishResult = await withSpinner(
|
|
188
|
+
"Publishing to blockchain",
|
|
189
|
+
() =>
|
|
190
|
+
runCli(
|
|
191
|
+
{
|
|
192
|
+
command: "movement",
|
|
193
|
+
args: [
|
|
194
|
+
"move",
|
|
195
|
+
"publish",
|
|
196
|
+
"--package-dir",
|
|
197
|
+
safeDir,
|
|
198
|
+
"--url",
|
|
199
|
+
config.rpc,
|
|
200
|
+
"--private-key-file",
|
|
201
|
+
keyFilePath,
|
|
202
|
+
"--sender-account",
|
|
203
|
+
deployerAddress,
|
|
204
|
+
"--assume-yes",
|
|
205
|
+
...namedAddrArgs,
|
|
206
|
+
],
|
|
207
|
+
timeoutMs: 120000, // 2 minutes for blockchain transactions
|
|
208
|
+
},
|
|
209
|
+
{ adapter: this.deps.adapter }
|
|
210
|
+
),
|
|
202
211
|
);
|
|
203
212
|
publishOut = publishResult.stdout;
|
|
204
213
|
publishErr = publishResult.stderr;
|
|
205
|
-
|
|
206
|
-
|
|
214
|
+
// Both stdout and stderr from the publish subprocess are gated
|
|
215
|
+
// behind isVerbose() — Movement CLI emits progress to both
|
|
216
|
+
// streams ("Compiling, may take a little while..."), so a
|
|
217
|
+
// visible stderr line is not by itself a failure signal. The
|
|
218
|
+
// surrounding withSpinner converts the runCli throw on real
|
|
219
|
+
// failure into the visible spinner.fail() output instead.
|
|
220
|
+
if (isVerbose() && publishOut) logger.info(publishOut.trim(), 2);
|
|
221
|
+
if (isVerbose() && publishErr) logger.info(publishErr.trim(), 2);
|
|
207
222
|
} finally {
|
|
208
223
|
// Unlink the temp key file via the observable cleanup helper.
|
|
209
224
|
// ENOENT and other already-gone outcomes are benign (null).
|
|
@@ -279,7 +294,7 @@ export class Publisher {
|
|
|
279
294
|
if (error instanceof CliExecutionError) {
|
|
280
295
|
// stdout/stderr are already redacted by runCli before reaching here,
|
|
281
296
|
// so this branch is safe to log verbatim.
|
|
282
|
-
if (error.stdoutPreview)
|
|
297
|
+
if (error.stdoutPreview) logger.info(error.stdoutPreview, 2);
|
|
283
298
|
logger.error(`Failed to publish module: ${error.message}\n${error.stderr}`);
|
|
284
299
|
} else {
|
|
285
300
|
// Preserve existing behaviour for non-CLI errors (filesystem write
|
package/src/core/config.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from "path";
|
|
|
3
3
|
import { existsSync, statSync } from "fs";
|
|
4
4
|
import { Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
|
|
5
5
|
import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
|
|
6
|
+
import { logger } from "../ui/index.js";
|
|
6
7
|
|
|
7
8
|
interface ConfigCacheEntry {
|
|
8
9
|
mtimeMs: number;
|
|
@@ -132,7 +133,7 @@ export async function resolveNetworkConfig(
|
|
|
132
133
|
url: "https://testnet.movementnetwork.xyz/v1",
|
|
133
134
|
chainId: "testnet",
|
|
134
135
|
};
|
|
135
|
-
|
|
136
|
+
logger.info("testnet not found in config - using default Movement testnet configuration");
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
// Special case: Auto-generate config for local fork server
|
|
@@ -141,7 +142,7 @@ export async function resolveNetworkConfig(
|
|
|
141
142
|
url: "http://localhost:8080/v1",
|
|
142
143
|
chainId: "local",
|
|
143
144
|
};
|
|
144
|
-
|
|
145
|
+
logger.info("Local network not found in config - using default fork server configuration");
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
if (!networkConfig) {
|
|
@@ -187,8 +188,10 @@ export async function resolveNetworkConfig(
|
|
|
187
188
|
// 3. Deterministic = consistent test results
|
|
188
189
|
const testPrivateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
189
190
|
accounts = [testPrivateKey];
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
logger.newline();
|
|
192
|
+
logger.warning("[TESTNET] Using auto-generated test account (safe for testing only)");
|
|
193
|
+
logger.warning("[TESTNET] For mainnet, set PRIVATE_KEY in .env");
|
|
194
|
+
logger.newline();
|
|
192
195
|
} else {
|
|
193
196
|
// For any other network (especially mainnet), REQUIRE explicit configuration
|
|
194
197
|
// This prevents accidentally using the test key on production networks
|
|
@@ -273,8 +276,8 @@ function deriveAccountAddress(privateKeyHex: string | undefined): string {
|
|
|
273
276
|
// The private key may have come from several sources (network.accounts,
|
|
274
277
|
// global accounts, PRIVATE_KEY env, auto-generated testnet key). Keep
|
|
275
278
|
// the hint generic so it never points at the wrong source.
|
|
276
|
-
|
|
277
|
-
`
|
|
279
|
+
logger.warning(
|
|
280
|
+
`Could not derive account address from the resolved private key: ${
|
|
278
281
|
(err as Error).message
|
|
279
282
|
}. Verify the key configured for this network is a valid Ed25519 private key (with or without the "ed25519-priv-" prefix).`
|
|
280
283
|
);
|