@secondlayer/cli 10.1.0 → 10.2.1
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 +1 -0
- package/dist/cli.js +113 -139
- package/dist/cli.js.map +14 -13
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -69,6 +69,7 @@ No account. Writes `.env.local`, restores history, prints the Stacks observer st
|
|
|
69
69
|
| Command | What it does |
|
|
70
70
|
|---|---|
|
|
71
71
|
| `sl init [--network mainnet\|testnet\|devnet] [--api-url <url>] [--force]` | Write `.env.local` (token, secrets key, webhook signing key). Idempotent |
|
|
72
|
+
| `sl start [--print]` | Validate one-box config and print `docker compose up` |
|
|
72
73
|
| `sl bootstrap --against <manifest> [--to-block <n>] [--public-key <pem>] [-y] [--json]` | Restore chain history from a verified archive into an empty database. Exit `0` restored, `1` diverged, `2` refused |
|
|
73
74
|
| `sl observer [--mode indexer\|signer-shared] [--endpoint host:port] [--recovery journal\|archive] [--network …]` | Print the `[[events_observer]]` stanza. Signer-shared requires `--recovery` |
|
|
74
75
|
| `sl verify [all\|raw\|decode:<name>\|subgraph:<name>] --against <manifest> [--quick\|--deep\|--anchor]` | Compare local data to a signed archive. Default target `raw`. Exit `0` clean, `1` diverged, `2` unanchored |
|
package/dist/cli.js
CHANGED
|
@@ -2551,7 +2551,7 @@ var init_session = __esm(() => {
|
|
|
2551
2551
|
|
|
2552
2552
|
// src/lib/resolve-auth.ts
|
|
2553
2553
|
function resolveApiUrl() {
|
|
2554
|
-
return process.env.SL_API_URL ?? process.env.SL_PLATFORM_API_URL ??
|
|
2554
|
+
return (process.env.SL_API_URL ?? process.env.SL_PLATFORM_API_URL ?? LOCAL_API_URL).replace(/\/+$/, "");
|
|
2555
2555
|
}
|
|
2556
2556
|
function resolveEnvKey() {
|
|
2557
2557
|
return process.env.SL_API_KEY;
|
|
@@ -2574,9 +2574,13 @@ async function resolveAuth() {
|
|
|
2574
2574
|
return { apiUrl, ephemeralKey: session.token, fromEnv: false };
|
|
2575
2575
|
}
|
|
2576
2576
|
function isOssMode() {
|
|
2577
|
-
|
|
2577
|
+
try {
|
|
2578
|
+
return new URL(resolveApiUrl()).hostname !== "api.secondlayer.tools";
|
|
2579
|
+
} catch {
|
|
2580
|
+
return true;
|
|
2581
|
+
}
|
|
2578
2582
|
}
|
|
2579
|
-
var
|
|
2583
|
+
var LOCAL_API_URL = "http://127.0.0.1:3800";
|
|
2580
2584
|
var init_resolve_auth = __esm(() => {
|
|
2581
2585
|
init_session();
|
|
2582
2586
|
});
|
|
@@ -30902,7 +30906,7 @@ import { resolve as resolve4 } from "node:path";
|
|
|
30902
30906
|
import { Index as Index2 } from "@secondlayer/sdk";
|
|
30903
30907
|
function client() {
|
|
30904
30908
|
return new Index2({
|
|
30905
|
-
baseUrl:
|
|
30909
|
+
baseUrl: resolveApiUrl(),
|
|
30906
30910
|
apiKey: resolveEnvKey()
|
|
30907
30911
|
});
|
|
30908
30912
|
}
|
|
@@ -30910,7 +30914,7 @@ function fail(action2, err) {
|
|
|
30910
30914
|
const message = err instanceof Error ? err.message : String(err);
|
|
30911
30915
|
error(`Failed to ${action2}: ${message}`);
|
|
30912
30916
|
if (/\b403\b/.test(message) || /forbidden/i.test(message)) {
|
|
30913
|
-
note("The
|
|
30917
|
+
note("The local API refused this read. Check INSTANCE_TOKEN / SL_API_KEY.");
|
|
30914
30918
|
}
|
|
30915
30919
|
process.exit(1);
|
|
30916
30920
|
}
|
|
@@ -31101,7 +31105,6 @@ async function runIndexCodegen(o3) {
|
|
|
31101
31105
|
process.exit(1);
|
|
31102
31106
|
}
|
|
31103
31107
|
}
|
|
31104
|
-
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
31105
31108
|
var init_index_api = __esm(() => {
|
|
31106
31109
|
init_fs();
|
|
31107
31110
|
init_output();
|
|
@@ -34784,7 +34787,7 @@ init_esm();
|
|
|
34784
34787
|
// package.json
|
|
34785
34788
|
var package_default = {
|
|
34786
34789
|
name: "@secondlayer/cli",
|
|
34787
|
-
version: "10.1
|
|
34790
|
+
version: "10.2.1",
|
|
34788
34791
|
repository: {
|
|
34789
34792
|
type: "git",
|
|
34790
34793
|
url: "git+https://github.com/ryanwaits/secondlayer.git",
|
|
@@ -34827,8 +34830,8 @@ var package_default = {
|
|
|
34827
34830
|
"@inquirer/prompts": "^8.2.0",
|
|
34828
34831
|
"@secondlayer/bundler": "^0.5.0",
|
|
34829
34832
|
"@secondlayer/scaffold": "^1.5.1",
|
|
34830
|
-
"@secondlayer/sdk": "^6.
|
|
34831
|
-
"@secondlayer/shared": "^7.
|
|
34833
|
+
"@secondlayer/sdk": "^6.54.0",
|
|
34834
|
+
"@secondlayer/shared": "^7.11.0",
|
|
34832
34835
|
"@secondlayer/stacks": "^3.3.1",
|
|
34833
34836
|
"@secondlayer/subgraphs": "^3.26.4",
|
|
34834
34837
|
esbuild: "^0.27.4",
|
|
@@ -35383,12 +35386,11 @@ async function validateDatabaseConnection(url) {
|
|
|
35383
35386
|
init_output();
|
|
35384
35387
|
init_resolve_auth();
|
|
35385
35388
|
import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
|
|
35386
|
-
var DEFAULT_BASE_URL2 = "https://api.secondlayer.tools";
|
|
35387
35389
|
function registerContextCommand(program2) {
|
|
35388
35390
|
program2.command("context").description("Print an agent orientation snapshot: account, live Streams/Index tips, your subgraphs/subscriptions, and in-flight reindex operations").option("--json", "Print as JSON (default)").action(async (o3) => {
|
|
35389
35391
|
try {
|
|
35390
35392
|
const sl = new SecondLayer2({
|
|
35391
|
-
baseUrl:
|
|
35393
|
+
baseUrl: resolveApiUrl(),
|
|
35392
35394
|
apiKey: resolveEnvKey()
|
|
35393
35395
|
});
|
|
35394
35396
|
const snapshot = await sl.context();
|
|
@@ -35404,93 +35406,71 @@ function registerContextCommand(program2) {
|
|
|
35404
35406
|
});
|
|
35405
35407
|
}
|
|
35406
35408
|
// src/commands/status.ts
|
|
35407
|
-
init_config2();
|
|
35408
35409
|
init_http();
|
|
35409
35410
|
init_output();
|
|
35411
|
+
init_resolve_auth();
|
|
35410
35412
|
function registerStatusCommand(program2) {
|
|
35411
|
-
program2.command("status").description("Show
|
|
35412
|
-
const config = await loadConfig2();
|
|
35413
|
+
program2.command("status").description("Show local instance status").option("--json", "Output as JSON").action(async (options3) => {
|
|
35413
35414
|
try {
|
|
35414
|
-
const status = await
|
|
35415
|
+
const status = await httpPlatformAnon("/public/status");
|
|
35415
35416
|
output({
|
|
35416
35417
|
json: options3.json,
|
|
35417
35418
|
data: status,
|
|
35418
|
-
human: () =>
|
|
35419
|
+
human: () => printPublicStatus(status)
|
|
35419
35420
|
});
|
|
35420
|
-
} catch
|
|
35421
|
-
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
|
|
35422
|
-
console.error("Not logged in. Run: sl login");
|
|
35423
|
-
process.exit(1);
|
|
35424
|
-
}
|
|
35421
|
+
} catch {
|
|
35425
35422
|
console.log("");
|
|
35426
35423
|
console.log(blue("System Status"));
|
|
35427
35424
|
console.log(` ${red("NOT RUNNING")}`);
|
|
35428
35425
|
console.log("");
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
console.log(dim(" Start with: sl local start"));
|
|
35432
|
-
} else {
|
|
35433
|
-
console.log(dim(" Can't reach the platform API."));
|
|
35434
|
-
console.log(dim(" Check your connection or try again."));
|
|
35435
|
-
}
|
|
35426
|
+
console.log(dim(` Can't reach ${resolveApiUrl()}/public/status.`));
|
|
35427
|
+
console.log(dim(" Start with: docker compose up -d"));
|
|
35436
35428
|
console.log("");
|
|
35437
35429
|
process.exit(1);
|
|
35438
35430
|
}
|
|
35439
35431
|
});
|
|
35440
35432
|
}
|
|
35441
|
-
function
|
|
35433
|
+
function printPublicStatus(status) {
|
|
35434
|
+
const overall = String(status.status ?? "unknown");
|
|
35435
|
+
const color = overall === "healthy" ? green : red;
|
|
35442
35436
|
console.log("");
|
|
35443
|
-
const statusColor = status.status === "healthy" ? green : red;
|
|
35444
35437
|
console.log(blue("System Status"));
|
|
35445
|
-
console.log(` ${
|
|
35446
|
-
console.log("");
|
|
35447
|
-
console.log(blue("Database"));
|
|
35448
|
-
const dbColor = status.database.status === "ok" ? green : red;
|
|
35449
|
-
console.log(` Status: ${dbColor(status.database.status)}`);
|
|
35438
|
+
console.log(` ${color(overall.toUpperCase())}`);
|
|
35450
35439
|
console.log("");
|
|
35451
|
-
|
|
35452
|
-
if (
|
|
35453
|
-
console.log(
|
|
35454
|
-
|
|
35455
|
-
|
|
35456
|
-
|
|
35457
|
-
|
|
35458
|
-
console.log(` ${p2.network}: block ${p2.lastIndexedBlock}${behindStr}`);
|
|
35459
|
-
if (status.chainTip && status.chainTip > 0) {
|
|
35460
|
-
const pct = Math.min(p2.lastIndexedBlock / status.chainTip * 100, 100);
|
|
35461
|
-
const barWidth = 30;
|
|
35462
|
-
const filled = Math.round(pct / 100 * barWidth);
|
|
35463
|
-
const empty = barWidth - filled;
|
|
35464
|
-
const bar = `${"█".repeat(filled)}${"░".repeat(empty)}`;
|
|
35465
|
-
const pctStr = `${pct.toFixed(1)}%`;
|
|
35466
|
-
const color = pct >= 99.9 ? green : pct >= 50 ? yellow : red;
|
|
35467
|
-
console.log(` ${dim("chain:")} ${color(bar)} ${color(pctStr)} ${dim(`(tip: ${status.chainTip.toLocaleString()})`)}`);
|
|
35468
|
-
}
|
|
35469
|
-
const contiguous = p2.lastContiguousBlock ?? 0;
|
|
35470
|
-
if (status.integrity === "complete") {
|
|
35471
|
-
console.log(` ${dim("contiguous:")} ${contiguous} ${green("(complete)")}`);
|
|
35472
|
-
} else {
|
|
35473
|
-
const gapCount = status.gaps?.length ?? 0;
|
|
35474
|
-
const missing = status.totalMissingBlocks ?? 0;
|
|
35475
|
-
console.log(` ${dim("contiguous:")} ${contiguous} ${yellow(`(${gapCount} gaps, ${missing} missing blocks)`)}`);
|
|
35476
|
-
if (status.gaps) {
|
|
35477
|
-
for (const gap of status.gaps.slice(0, 5)) {
|
|
35478
|
-
const range = gap.gapStart === gap.gapEnd ? `${gap.gapStart}` : `${gap.gapStart}-${gap.gapEnd}`;
|
|
35479
|
-
console.log(` ${dim("gap:")} ${range} ${dim(`(${gap.size} block${gap.size > 1 ? "s" : ""})`)}`);
|
|
35480
|
-
}
|
|
35481
|
-
}
|
|
35482
|
-
}
|
|
35440
|
+
const tip = status.chainTip;
|
|
35441
|
+
if (typeof tip === "number") {
|
|
35442
|
+
console.log(blue("Chain"));
|
|
35443
|
+
console.log(` tip: ${tip.toLocaleString()}`);
|
|
35444
|
+
const integrity = status.chainIntegrity;
|
|
35445
|
+
if (integrity) {
|
|
35446
|
+
console.log(` integrity: ${integrity.ok ? green("ok") : yellow("check")}`);
|
|
35483
35447
|
}
|
|
35448
|
+
console.log("");
|
|
35484
35449
|
}
|
|
35485
|
-
|
|
35486
|
-
if (
|
|
35487
|
-
console.log(blue("
|
|
35488
|
-
console.log(
|
|
35489
|
-
|
|
35490
|
-
|
|
35450
|
+
const streams = status.streams;
|
|
35451
|
+
if (streams) {
|
|
35452
|
+
console.log(blue("Streams"));
|
|
35453
|
+
console.log(` ${streams.status ?? "unknown"}`);
|
|
35454
|
+
if (typeof streams.tip?.lag_seconds === "number") {
|
|
35455
|
+
console.log(` lag: ${streams.tip.lag_seconds}s`);
|
|
35456
|
+
}
|
|
35491
35457
|
console.log("");
|
|
35492
35458
|
}
|
|
35493
|
-
|
|
35459
|
+
const index = status.index;
|
|
35460
|
+
if (index) {
|
|
35461
|
+
console.log(blue("Index"));
|
|
35462
|
+
console.log(` ${index.status ?? "unknown"}`);
|
|
35463
|
+
const bad = (index.decoders ?? []).filter((d2) => d2.status !== "ok");
|
|
35464
|
+
if (bad.length > 0) {
|
|
35465
|
+
for (const d2 of bad.slice(0, 8)) {
|
|
35466
|
+
console.log(` ${yellow(d2.decoder)} ${d2.status}`);
|
|
35467
|
+
}
|
|
35468
|
+
}
|
|
35469
|
+
console.log("");
|
|
35470
|
+
}
|
|
35471
|
+
if (typeof status.timestamp === "string") {
|
|
35472
|
+
console.log(dim(`Last updated: ${status.timestamp}`));
|
|
35473
|
+
}
|
|
35494
35474
|
}
|
|
35495
35475
|
// src/commands/subscriptions.ts
|
|
35496
35476
|
init_api_client();
|
|
@@ -37065,20 +37045,11 @@ import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
|
37065
37045
|
import { dirname as dirname9, join as join10 } from "node:path";
|
|
37066
37046
|
import { createStreamsClient } from "@secondlayer/sdk";
|
|
37067
37047
|
import { STREAMS_EVENT_TYPES } from "@secondlayer/shared";
|
|
37068
|
-
var DEFAULT_BASE_URL3 = "https://api.secondlayer.tools";
|
|
37069
37048
|
var VALID_TYPES = STREAMS_EVENT_TYPES;
|
|
37070
|
-
function readApiKey() {
|
|
37071
|
-
const key = resolveEnvKey();
|
|
37072
|
-
if (!key) {
|
|
37073
|
-
error("No API key set. Export SL_API_KEY (issue one at https://www.secondlayer.tools/platform/api-keys).");
|
|
37074
|
-
process.exit(1);
|
|
37075
|
-
}
|
|
37076
|
-
return key;
|
|
37077
|
-
}
|
|
37078
37049
|
function client2() {
|
|
37079
37050
|
return createStreamsClient({
|
|
37080
|
-
baseUrl:
|
|
37081
|
-
apiKey:
|
|
37051
|
+
baseUrl: resolveApiUrl(),
|
|
37052
|
+
apiKey: resolveEnvKey() ?? ""
|
|
37082
37053
|
});
|
|
37083
37054
|
}
|
|
37084
37055
|
function dumpsClient(dumpsUrl) {
|
|
@@ -37088,7 +37059,7 @@ function dumpsClient(dumpsUrl) {
|
|
|
37088
37059
|
process.exit(1);
|
|
37089
37060
|
}
|
|
37090
37061
|
return createStreamsClient({
|
|
37091
|
-
baseUrl:
|
|
37062
|
+
baseUrl: resolveApiUrl(),
|
|
37092
37063
|
apiKey: resolveEnvKey() ?? "",
|
|
37093
37064
|
dumpsBaseUrl
|
|
37094
37065
|
});
|
|
@@ -37131,7 +37102,7 @@ function parseHeight(value, name) {
|
|
|
37131
37102
|
return n3;
|
|
37132
37103
|
}
|
|
37133
37104
|
function registerStreamsCommand(program2) {
|
|
37134
|
-
const streams = program2.command("streams").description("Read raw chain events from Streams
|
|
37105
|
+
const streams = program2.command("streams").description("Read raw chain events from Streams");
|
|
37135
37106
|
streams.command("tip").description("Print current canonical tip").option("--json", "Output as JSON (streams always emits JSON)").action(async () => {
|
|
37136
37107
|
try {
|
|
37137
37108
|
const tip = await client2().tip();
|
|
@@ -37285,7 +37256,6 @@ init_index_api();
|
|
|
37285
37256
|
init_output();
|
|
37286
37257
|
init_resolve_auth();
|
|
37287
37258
|
import { SecondLayer as SecondLayer4 } from "@secondlayer/sdk";
|
|
37288
|
-
var DEFAULT_BASE_URL4 = "https://api.secondlayer.tools";
|
|
37289
37259
|
function registerKeysCommand(program2) {
|
|
37290
37260
|
const keys = program2.command("keys", { hidden: true }).description("Manage API keys");
|
|
37291
37261
|
keys.command("create").description("Mint a scoped streams/index read key (requires an account-level key)").option("--product <product>", "Key scope: streams or index", "streams").option("--name <name>", "Optional label for the key").option("--json", "Print the full response as JSON").action(async (o3) => {
|
|
@@ -37300,7 +37270,7 @@ function registerKeysCommand(program2) {
|
|
|
37300
37270
|
}
|
|
37301
37271
|
try {
|
|
37302
37272
|
const sl = new SecondLayer4({
|
|
37303
|
-
baseUrl:
|
|
37273
|
+
baseUrl: resolveApiUrl(),
|
|
37304
37274
|
apiKey
|
|
37305
37275
|
});
|
|
37306
37276
|
const minted = await sl.apiKeys.create({
|
|
@@ -37323,7 +37293,6 @@ function registerKeysCommand(program2) {
|
|
|
37323
37293
|
});
|
|
37324
37294
|
}
|
|
37325
37295
|
// src/commands/doctor.ts
|
|
37326
|
-
init_api_client();
|
|
37327
37296
|
init_config2();
|
|
37328
37297
|
|
|
37329
37298
|
// src/lib/health.ts
|
|
@@ -37469,50 +37438,31 @@ async function checkHealth() {
|
|
|
37469
37438
|
init_http();
|
|
37470
37439
|
init_network();
|
|
37471
37440
|
init_output();
|
|
37441
|
+
init_resolve_auth();
|
|
37472
37442
|
function registerDoctorCommand(program2) {
|
|
37473
37443
|
program2.command("doctor").description("Run diagnostics on the full stack").option("--json", "Output as JSON").action(async (options3) => {
|
|
37474
37444
|
const config = await loadConfig2();
|
|
37475
37445
|
if (config.network === "local") {
|
|
37476
37446
|
await runLocalDoctor(options3.json);
|
|
37477
|
-
|
|
37478
|
-
await runHostedDoctor(options3.json);
|
|
37447
|
+
return;
|
|
37479
37448
|
}
|
|
37449
|
+
await runInstanceDoctor(options3.json);
|
|
37480
37450
|
});
|
|
37481
37451
|
}
|
|
37482
|
-
async function
|
|
37452
|
+
async function runInstanceDoctor(jsonOutput) {
|
|
37483
37453
|
const config = await loadConfig2();
|
|
37484
|
-
const apiUrl =
|
|
37454
|
+
const apiUrl = resolveApiUrl();
|
|
37485
37455
|
const issues = [];
|
|
37486
37456
|
const results = { network: config.network, apiUrl };
|
|
37487
37457
|
let apiHealthy = false;
|
|
37488
37458
|
let statusData = null;
|
|
37489
37459
|
try {
|
|
37490
|
-
statusData = await
|
|
37460
|
+
statusData = await httpPlatformAnon("/public/status");
|
|
37491
37461
|
apiHealthy = true;
|
|
37492
|
-
} catch
|
|
37493
|
-
|
|
37494
|
-
if (err.code === "SESSION_EXPIRED") {
|
|
37495
|
-
issues.push("Not authenticated. Run: sl login");
|
|
37496
|
-
} else {
|
|
37497
|
-
issues.push(`API error: ${err.code}`);
|
|
37498
|
-
}
|
|
37499
|
-
} else {
|
|
37500
|
-
issues.push(`Cannot reach API at ${apiUrl}`);
|
|
37501
|
-
}
|
|
37462
|
+
} catch {
|
|
37463
|
+
issues.push(`Cannot reach ${apiUrl}/public/status`);
|
|
37502
37464
|
}
|
|
37503
37465
|
results.apiHealthy = apiHealthy;
|
|
37504
|
-
let authOk = false;
|
|
37505
|
-
let account = null;
|
|
37506
|
-
try {
|
|
37507
|
-
account = await getAccountProfile();
|
|
37508
|
-
authOk = true;
|
|
37509
|
-
} catch (err) {
|
|
37510
|
-
if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
|
|
37511
|
-
issues.push("Not authenticated. Run: sl login");
|
|
37512
|
-
}
|
|
37513
|
-
}
|
|
37514
|
-
results.authOk = authOk;
|
|
37515
|
-
results.account = account;
|
|
37516
37466
|
if (jsonOutput) {
|
|
37517
37467
|
console.log(JSON.stringify({ ...results, status: statusData, issues }, null, 2));
|
|
37518
37468
|
return;
|
|
@@ -37524,28 +37474,18 @@ async function runHostedDoctor(jsonOutput) {
|
|
|
37524
37474
|
console.log(blue("API"));
|
|
37525
37475
|
console.log(` ${apiHealthy ? green("✓") : red("✗")} ${apiHealthy ? green("reachable") : red("unreachable")}`);
|
|
37526
37476
|
console.log("");
|
|
37527
|
-
console.log(blue("Auth"));
|
|
37528
|
-
if (authOk && account) {
|
|
37529
|
-
console.log(` ${green("✓")} Authenticated`);
|
|
37530
|
-
console.log(formatKeyValue([
|
|
37531
|
-
[" Email", account.email ?? dim("unknown")],
|
|
37532
|
-
[" Plan", account.plan ?? dim("unknown")]
|
|
37533
|
-
]));
|
|
37534
|
-
} else {
|
|
37535
|
-
console.log(` ${red("✗")} Not authenticated`);
|
|
37536
|
-
}
|
|
37537
|
-
console.log("");
|
|
37538
37477
|
if (statusData) {
|
|
37539
|
-
const
|
|
37540
|
-
|
|
37541
|
-
|
|
37542
|
-
|
|
37543
|
-
|
|
37544
|
-
|
|
37545
|
-
|
|
37546
|
-
}
|
|
37547
|
-
|
|
37548
|
-
|
|
37478
|
+
const tip = statusData.chainTip;
|
|
37479
|
+
const streams = statusData.streams;
|
|
37480
|
+
const index = statusData.index;
|
|
37481
|
+
console.log(blue("Instance"));
|
|
37482
|
+
if (typeof tip === "number")
|
|
37483
|
+
console.log(` tip: ${tip.toLocaleString()}`);
|
|
37484
|
+
if (streams?.status)
|
|
37485
|
+
console.log(` streams: ${streams.status}`);
|
|
37486
|
+
if (index?.status)
|
|
37487
|
+
console.log(` index: ${index.status}`);
|
|
37488
|
+
console.log("");
|
|
37549
37489
|
}
|
|
37550
37490
|
console.log(blue("Issues"));
|
|
37551
37491
|
if (issues.length === 0) {
|
|
@@ -39801,6 +39741,39 @@ function registerObserverCommand(program2) {
|
|
|
39801
39741
|
writeData(renderObserverStanza({ mode, endpoint, network, recovery }));
|
|
39802
39742
|
});
|
|
39803
39743
|
}
|
|
39744
|
+
// src/commands/start.ts
|
|
39745
|
+
init_output();
|
|
39746
|
+
import { parseRuntimeConfig } from "@secondlayer/shared/runtime";
|
|
39747
|
+
function registerStartCommand(program2) {
|
|
39748
|
+
program2.command("start").description("Validate one-box runtime config and print the compose command").option("--print", "print the compose invocation only").action((opts) => {
|
|
39749
|
+
const parsed = parseRuntimeConfig({
|
|
39750
|
+
NETWORK: process.env.NETWORK ?? process.env.STACKS_NETWORK,
|
|
39751
|
+
DATABASE_URL: process.env.DATABASE_URL,
|
|
39752
|
+
NODE_MODE: process.env.NODE_MODE ?? "external",
|
|
39753
|
+
DATA_DIR: process.env.DATA_DIR ?? "/data",
|
|
39754
|
+
API_PORT: process.env.API_PORT ?? "3800",
|
|
39755
|
+
INDEXER_PORT: process.env.INDEXER_PORT ?? "3700",
|
|
39756
|
+
STACKS_NODE_RPC_URL: process.env.STACKS_NODE_RPC_URL,
|
|
39757
|
+
LISTEN_HOST: process.env.LISTEN_HOST,
|
|
39758
|
+
LOG_LEVEL: process.env.LOG_LEVEL,
|
|
39759
|
+
BITCOIN_RPC_PASSWORD: process.env.BITCOIN_RPC_PASSWORD
|
|
39760
|
+
});
|
|
39761
|
+
if (!parsed.ok) {
|
|
39762
|
+
printError(parsed.errors.join("; "), {
|
|
39763
|
+
hint: "Set NETWORK, DATABASE_URL, and NODE_MODE (external | stacks | full)."
|
|
39764
|
+
});
|
|
39765
|
+
process.exit(1);
|
|
39766
|
+
}
|
|
39767
|
+
const extra = parsed.config.NODE_MODE === "full" ? " --profile full-node" : parsed.config.NODE_MODE === "stacks" ? " --profile stacks-node" : "";
|
|
39768
|
+
const cmd = `docker compose -f docker/oss/docker-compose.yml${extra} up -d`;
|
|
39769
|
+
if (opts.print) {
|
|
39770
|
+
console.log(cmd);
|
|
39771
|
+
return;
|
|
39772
|
+
}
|
|
39773
|
+
success(`config ok (${parsed.config.NETWORK}, ${parsed.config.NODE_MODE})`);
|
|
39774
|
+
console.log(cmd);
|
|
39775
|
+
});
|
|
39776
|
+
}
|
|
39804
39777
|
// src/cli.ts
|
|
39805
39778
|
var { version } = package_default;
|
|
39806
39779
|
program.name("secondlayer").alias("sl").description("Secondlayer CLI — self-hosted Stacks data runtime").version(version).option("--network <network>", "Override network (local, testnet, mainnet)").option("--api-key <key>", "API credential (overrides SL_API_KEY)").option("--api-url <url>", "API endpoint (overrides SL_API_URL)").showSuggestionAfterError(true).showHelpAfterError("(run `sl --help` to see available commands)");
|
|
@@ -39824,6 +39797,7 @@ program.commandsGroup("Getting started:");
|
|
|
39824
39797
|
registerInitCommand(program);
|
|
39825
39798
|
registerBootstrapCommand(program);
|
|
39826
39799
|
registerObserverCommand(program);
|
|
39800
|
+
registerStartCommand(program);
|
|
39827
39801
|
registerLoginCommand(program);
|
|
39828
39802
|
registerLogoutCommand(program);
|
|
39829
39803
|
registerWhoamiCommand(program);
|
|
@@ -39863,5 +39837,5 @@ registerAccountCommand(program);
|
|
|
39863
39837
|
registerKeysCommand(program);
|
|
39864
39838
|
program.parse();
|
|
39865
39839
|
|
|
39866
|
-
//# debugId=
|
|
39840
|
+
//# debugId=60FAFC7C2FFCA95764756E2164756E21
|
|
39867
39841
|
//# sourceMappingURL=cli.js.map
|