@toon-protocol/townhouse 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -438
- package/dist/{chunk-W33MEOPM.js → chunk-QHFUIWEN.js} +14 -8
- package/dist/{chunk-W33MEOPM.js.map → chunk-QHFUIWEN.js.map} +1 -1
- package/dist/cli.js +93 -37
- package/dist/cli.js.map +1 -1
- package/dist/compose/townhouse-hs.yml +8 -8
- package/dist/image-manifest.json +10 -10
- package/dist/index.js +1 -1
- package/dist/{tui-OIFXGBTL.js → tui-QE3ZRZO3.js} +21 -8
- package/dist/tui-QE3ZRZO3.js.map +1 -0
- package/package.json +4 -4
- package/dist/tui-OIFXGBTL.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
serviceFromContainerName,
|
|
28
28
|
tailContainerLogs,
|
|
29
29
|
writeHsConnectorConfig
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-QHFUIWEN.js";
|
|
31
31
|
import "./chunk-5O4SBV5O.js";
|
|
32
32
|
import {
|
|
33
33
|
CONTAINER_PREFIX
|
|
@@ -46,7 +46,8 @@ import {
|
|
|
46
46
|
existsSync,
|
|
47
47
|
renameSync,
|
|
48
48
|
rmSync,
|
|
49
|
-
statSync
|
|
49
|
+
statSync,
|
|
50
|
+
realpathSync
|
|
50
51
|
} from "fs";
|
|
51
52
|
import { join, resolve, dirname } from "path";
|
|
52
53
|
import { homedir } from "os";
|
|
@@ -2026,6 +2027,18 @@ Flags:
|
|
|
2026
2027
|
If no flags given, starts all enabled nodes from config.`;
|
|
2027
2028
|
var DEFAULT_CONFIG_DIR = join(homedir(), ".townhouse");
|
|
2028
2029
|
var DEFAULT_CONFIG_PATH = join(DEFAULT_CONFIG_DIR, "config.yaml");
|
|
2030
|
+
function printInitNextStep(dir) {
|
|
2031
|
+
const isDefaultDir = dir === resolve(DEFAULT_CONFIG_DIR);
|
|
2032
|
+
const cmd = isDefaultDir ? "npx @toon-protocol/townhouse hs up" : `npx @toon-protocol/townhouse hs up -c ${join(dir, "config.yaml")}`;
|
|
2033
|
+
console.log("");
|
|
2034
|
+
console.log("Next \u2014 start your node:");
|
|
2035
|
+
console.log(` ${cmd}`);
|
|
2036
|
+
console.log("");
|
|
2037
|
+
console.log(
|
|
2038
|
+
"First run pulls container images and bootstraps a hidden service."
|
|
2039
|
+
);
|
|
2040
|
+
console.log("It can take a few minutes; progress is shown throughout.");
|
|
2041
|
+
}
|
|
2029
2042
|
async function handleInit(force, configDir, password, preset, yes) {
|
|
2030
2043
|
const dir = resolve(configDir ?? DEFAULT_CONFIG_DIR);
|
|
2031
2044
|
const configPath = join(dir, "config.yaml");
|
|
@@ -2059,9 +2072,17 @@ async function handleInit(force, configDir, password, preset, yes) {
|
|
|
2059
2072
|
console.log(`Config created at ${configPath}`);
|
|
2060
2073
|
const walletPath = join(dir, "wallet.enc");
|
|
2061
2074
|
if (existsSync(walletPath) && !force) {
|
|
2075
|
+
console.log("");
|
|
2062
2076
|
console.log(
|
|
2063
|
-
`Wallet already exists at ${walletPath}
|
|
2077
|
+
`Wallet already exists at ${walletPath} \u2014 keeping your existing keys.`
|
|
2064
2078
|
);
|
|
2079
|
+
console.log(
|
|
2080
|
+
"Your seed phrase from the first run is still valid; nothing changed."
|
|
2081
|
+
);
|
|
2082
|
+
console.log(
|
|
2083
|
+
"(Re-run with --force to regenerate, which REPLACES your keys.)"
|
|
2084
|
+
);
|
|
2085
|
+
printInitNextStep(dir);
|
|
2065
2086
|
return;
|
|
2066
2087
|
}
|
|
2067
2088
|
const walletPassword = password ?? process.env["TOWNHOUSE_WALLET_PASSWORD"];
|
|
@@ -2095,6 +2116,7 @@ async function handleInit(force, configDir, password, preset, yes) {
|
|
|
2095
2116
|
console.log(` ${"".padEnd(6)} EVM: ${info.evmAddress}`);
|
|
2096
2117
|
}
|
|
2097
2118
|
walletManager.lock();
|
|
2119
|
+
printInitNextStep(dir);
|
|
2098
2120
|
}
|
|
2099
2121
|
async function handleSetup(configDir, port, noBrowser, dockerInstance, browserOpener) {
|
|
2100
2122
|
const dir = resolve(configDir ?? DEFAULT_CONFIG_DIR);
|
|
@@ -3007,8 +3029,52 @@ function isAnonBootstrapTimeout(err) {
|
|
|
3007
3029
|
${err.stderr ?? ""}`;
|
|
3008
3030
|
return /connector.*unhealthy|dependency.*connector.*fail/i.test(text);
|
|
3009
3031
|
}
|
|
3032
|
+
async function attachDashboard(hostname) {
|
|
3033
|
+
if (!shouldRenderInk()) return;
|
|
3034
|
+
try {
|
|
3035
|
+
const { mountTui } = await import("./tui-QE3ZRZO3.js");
|
|
3036
|
+
const apiUrlOverride = process.env["HS_TOWNHOUSE_API_URL"];
|
|
3037
|
+
const mountOpts = apiUrlOverride !== void 0 ? { apiUrl: apiUrlOverride } : {};
|
|
3038
|
+
const instance = mountTui(mountOpts);
|
|
3039
|
+
await instance.waitUntilExit();
|
|
3040
|
+
} catch (tuiErr) {
|
|
3041
|
+
const detail = tuiErr instanceof Error ? tuiErr.message : String(tuiErr);
|
|
3042
|
+
console.error("");
|
|
3043
|
+
console.error(`Your node is live at ${hostname}.`);
|
|
3044
|
+
console.error(
|
|
3045
|
+
`The live dashboard could not open (${detail}) \u2014 this is a display issue, not a node issue. Your node keeps running.`
|
|
3046
|
+
);
|
|
3047
|
+
console.error(
|
|
3048
|
+
"Stop it anytime with: npx @toon-protocol/townhouse hs down"
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3010
3052
|
async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
3011
3053
|
const { password, force, skipPreflight, hsOverrides } = options;
|
|
3054
|
+
if (!force) {
|
|
3055
|
+
const adminClientFactory = hsOverrides?.createAdminClient ?? ((url, t) => new ConnectorAdminClient(url, t));
|
|
3056
|
+
const probe = adminClientFactory(HS_CONNECTOR_ADMIN_URL, 3e3);
|
|
3057
|
+
try {
|
|
3058
|
+
const existing = await probe.getHsHostname();
|
|
3059
|
+
if (existing.hostname !== null) {
|
|
3060
|
+
console.log(`Apex live at ${existing.hostname}`);
|
|
3061
|
+
_writeHostJson(configDir, {
|
|
3062
|
+
hostname: existing.hostname,
|
|
3063
|
+
publishedAt: existing.publishedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
3064
|
+
writtenAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3065
|
+
});
|
|
3066
|
+
await attachDashboard(existing.hostname);
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
} catch (probeErr) {
|
|
3070
|
+
const msg = probeErr instanceof Error ? probeErr.message : String(probeErr);
|
|
3071
|
+
if (msg.includes("anon-disabled")) {
|
|
3072
|
+
const { exitCode } = renderFailure(probeErr);
|
|
3073
|
+
process.exitCode = exitCode;
|
|
3074
|
+
return;
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3012
3078
|
if (!skipPreflight) {
|
|
3013
3079
|
const preflight = hsOverrides?.checkPortCollisions ?? ((d) => checkHsPortCollisions(d));
|
|
3014
3080
|
try {
|
|
@@ -3042,7 +3108,7 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3042
3108
|
resolvedPassword = await promptPassword("Wallet password: ");
|
|
3043
3109
|
} else {
|
|
3044
3110
|
console.error(
|
|
3045
|
-
"Wallet password required
|
|
3111
|
+
"Wallet password required, but no interactive terminal is available to prompt.\nPass --password <pw> or set TOWNHOUSE_WALLET_PASSWORD."
|
|
3046
3112
|
);
|
|
3047
3113
|
process.exitCode = 1;
|
|
3048
3114
|
return;
|
|
@@ -3067,29 +3133,6 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3067
3133
|
}
|
|
3068
3134
|
const ribbon = new OnboardingRibbon();
|
|
3069
3135
|
try {
|
|
3070
|
-
if (!force) {
|
|
3071
|
-
const adminClientFactory = hsOverrides?.createAdminClient ?? ((url, t) => new ConnectorAdminClient(url, t));
|
|
3072
|
-
const probe = adminClientFactory(HS_CONNECTOR_ADMIN_URL, 3e3);
|
|
3073
|
-
try {
|
|
3074
|
-
const existing = await probe.getHsHostname();
|
|
3075
|
-
if (existing.hostname !== null) {
|
|
3076
|
-
console.log(`Apex live at ${existing.hostname}`);
|
|
3077
|
-
_writeHostJson(configDir, {
|
|
3078
|
-
hostname: existing.hostname,
|
|
3079
|
-
publishedAt: existing.publishedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
3080
|
-
writtenAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3081
|
-
});
|
|
3082
|
-
return;
|
|
3083
|
-
}
|
|
3084
|
-
} catch (probeErr) {
|
|
3085
|
-
const msg = probeErr instanceof Error ? probeErr.message : String(probeErr);
|
|
3086
|
-
if (msg.includes("anon-disabled")) {
|
|
3087
|
-
const { exitCode } = renderFailure(probeErr);
|
|
3088
|
-
process.exitCode = exitCode;
|
|
3089
|
-
return;
|
|
3090
|
-
}
|
|
3091
|
-
}
|
|
3092
|
-
}
|
|
3093
3136
|
writeHsConnectorConfig(configDir, config, { force });
|
|
3094
3137
|
const materialize = hsOverrides?.materializeComposeTemplate ?? materializeComposeTemplate;
|
|
3095
3138
|
const { composePath } = materialize("hs", { townhouseHome: configDir });
|
|
@@ -3119,6 +3162,7 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3119
3162
|
ribbon.start("bootstrap");
|
|
3120
3163
|
}
|
|
3121
3164
|
});
|
|
3165
|
+
ribbon.stop();
|
|
3122
3166
|
if (typeof orch.pullImage === "function") {
|
|
3123
3167
|
try {
|
|
3124
3168
|
const apexImages = await collectApexImageRefs(configDir);
|
|
@@ -3132,11 +3176,18 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3132
3176
|
console.log(` [${pulled}/${apexImages.length}] ${ref}`);
|
|
3133
3177
|
await orch.pullImage(ref);
|
|
3134
3178
|
}
|
|
3179
|
+
} else {
|
|
3180
|
+
console.log(
|
|
3181
|
+
"No pinned image manifest found \u2014 Docker will pull images on demand."
|
|
3182
|
+
);
|
|
3183
|
+
console.log(
|
|
3184
|
+
"First start can take several minutes with limited progress output."
|
|
3185
|
+
);
|
|
3135
3186
|
}
|
|
3136
3187
|
} catch (pullErr) {
|
|
3137
3188
|
const detail = pullErr instanceof Error ? pullErr.message : String(pullErr);
|
|
3138
|
-
console.
|
|
3139
|
-
`
|
|
3189
|
+
console.log(
|
|
3190
|
+
`Could not pre-pull images (${detail}). Docker will pull them during startup \u2014 this is normal and may take a few minutes.`
|
|
3140
3191
|
);
|
|
3141
3192
|
}
|
|
3142
3193
|
}
|
|
@@ -3157,6 +3208,10 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3157
3208
|
resolve(config.wallet.encrypted_path)
|
|
3158
3209
|
);
|
|
3159
3210
|
process.env["TOWNHOUSE_DOCKER_GID"] = String(dockerSockGid);
|
|
3211
|
+
if (!bootstrapStarted) {
|
|
3212
|
+
bootstrapStarted = true;
|
|
3213
|
+
ribbon.start("bootstrap");
|
|
3214
|
+
}
|
|
3160
3215
|
const MAX_ANON_RETRIES = 3;
|
|
3161
3216
|
try {
|
|
3162
3217
|
for (let attempt = 1; attempt <= MAX_ANON_RETRIES; attempt++) {
|
|
@@ -3230,13 +3285,7 @@ async function handleHsUp(_configPath, configDir, config, docker, options) {
|
|
|
3230
3285
|
writtenAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3231
3286
|
});
|
|
3232
3287
|
ribbon.start("live", hostname);
|
|
3233
|
-
|
|
3234
|
-
const { mountTui } = await import("./tui-OIFXGBTL.js");
|
|
3235
|
-
const apiUrlOverride = process.env["HS_TOWNHOUSE_API_URL"];
|
|
3236
|
-
const mountOpts = apiUrlOverride !== void 0 ? { apiUrl: apiUrlOverride } : {};
|
|
3237
|
-
const instance = mountTui(mountOpts);
|
|
3238
|
-
await instance.waitUntilExit();
|
|
3239
|
-
}
|
|
3288
|
+
await attachDashboard(hostname);
|
|
3240
3289
|
} catch (err) {
|
|
3241
3290
|
const { exitCode } = renderFailure(err);
|
|
3242
3291
|
process.exitCode = exitCode;
|
|
@@ -3672,7 +3721,14 @@ async function main(argv, dockerInstance, browserOpener, hsOverrides, nodeComman
|
|
|
3672
3721
|
}
|
|
3673
3722
|
}
|
|
3674
3723
|
var invokedFile = process.argv[1];
|
|
3675
|
-
var invokedDirectly =
|
|
3724
|
+
var invokedDirectly = false;
|
|
3725
|
+
if (typeof invokedFile === "string") {
|
|
3726
|
+
try {
|
|
3727
|
+
invokedDirectly = import.meta.url === pathToFileURL(realpathSync(invokedFile)).href;
|
|
3728
|
+
} catch {
|
|
3729
|
+
invokedDirectly = import.meta.url === pathToFileURL(invokedFile).href;
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3676
3732
|
if (invokedDirectly) {
|
|
3677
3733
|
main(process.argv.slice(2)).catch((error) => {
|
|
3678
3734
|
if (error instanceof CliHelpRequested) {
|