@secondlayer/cli 15.0.1 → 16.0.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 CHANGED
@@ -82,7 +82,7 @@ No account. Writes `.env.local`, restores history, prints the Stacks observer st
82
82
  | `secondlayer setup [--network …] [--node-mode external\|stacks\|full] [--api-port <spec>] [--dir <path>] [--against <manifest>] [--skip-bootstrap] [--skip-verify] [--yes] [--force]` | Guided self-host onboarding — secrets, compose + `.env`, docker up, observer stanza, bootstrap, verify. TUI when interactive; flags-only (no prompts) with `--yes` or no TTY |
83
83
  | `secondlayer init [--network mainnet\|testnet\|devnet] [--api-url <url>] [--force]` | Write `.env.local` (token, secrets key, webhook signing key). `--network` and `--api-url` are the global flags. Idempotent |
84
84
  | `secondlayer bootstrap --against <manifest> [--from-block <n>] [--to-block <n>] [--verify all\|blocks] [--public-key <pem>] [-y] [--json]` | Restore chain history from a verified archive into an empty database. A run that died mid-way resumes per dataset on re-run. After the load, digests for blocks, transactions, and events are checked over the restored range (`--verify blocks` skips the child datasets and the minutes they cost). Partition fetches retry three times with backoff on resets, timeouts, 429 (honoring `Retry-After`) and 5xx; a link that stays down exits `1` with a re-run hint, and the re-run resumes. Exit `0` restored, `1` diverged or interrupted, `2` refused |
85
- | `secondlayer observer [--mode indexer\|signer-shared] [--endpoint host:port] [--recovery journal\|archive] [--network …]` | Print the `[[events_observer]]` stanza. Signer-shared requires `--recovery` |
85
+ | `secondlayer observer [--mode indexer\|signer-shared] [--endpoint host:port] [--network …]` | Print the `[[events_observer]]` stanza. Signer-shared skips retries; a missed block stays a gap until `repair` |
86
86
  | `secondlayer 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 |
87
87
  | `secondlayer repair --against <archive> [--apply] [-y]` | Plan (default) or apply an archive repair. A fixed block is rewritten with its transactions and events from the archive; when the reference has no child partition for a height, the block is rewritten alone, the height is named with a `bootstrap --from-block H --to-block H` remedy, and the exit is `1`. Partition fetches retry like `bootstrap`; a link that stays down exits `1` with a re-run hint, and heights already repaired are kept |
88
88
 
package/dist/cli.js CHANGED
@@ -197993,7 +197993,8 @@ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3, wr
197993
197993
  import { dirname as dirname4, resolve as resolve3 } from "node:path";
197994
197994
  import { Index, resolveApiKey as resolveApiKey3, resolveBaseUrl } from "@secondlayer/sdk";
197995
197995
  import {
197996
- DECODED_EVENT_TYPES
197996
+ DECODED_EVENT_TYPES,
197997
+ VM_EVENT_TYPES
197997
197998
  } from "@secondlayer/stacks/filters";
197998
197999
  import {
197999
198000
  runSubgraphTest as applySubgraphTest,
@@ -198030,7 +198031,13 @@ function eventTypeFor(filter) {
198030
198031
  return null;
198031
198032
  }
198032
198033
  const candidate = filter.type === "print_event" ? "print" : filter.type;
198033
- return DECODED_EVENT_TYPES.includes(candidate) ? candidate : null;
198034
+ if (DECODED_EVENT_TYPES.includes(candidate)) {
198035
+ return candidate;
198036
+ }
198037
+ if (VM_EVENT_TYPES.includes(candidate)) {
198038
+ return candidate;
198039
+ }
198040
+ return null;
198034
198041
  }
198035
198042
  function indexApiUrl() {
198036
198043
  return resolveBaseUrl();
@@ -202446,13 +202453,6 @@ function parseObserverMode(value) {
202446
202453
  }
202447
202454
  throw new UnsupportedObserverError(`observer mode must be indexer or signer-shared (got ${value})`);
202448
202455
  }
202449
- function parseRecoverySource(value) {
202450
- const source = value.trim().toLowerCase();
202451
- if (RECOVERY_SOURCES.includes(source)) {
202452
- return source;
202453
- }
202454
- throw new UnsupportedObserverError(`recovery source must be journal or archive (got ${value})`);
202455
- }
202456
202456
  function parseObserverEndpoint(value) {
202457
202457
  const trimmed = value.trim();
202458
202458
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) || trimmed.startsWith("unix:")) {
@@ -202474,9 +202474,6 @@ function validateObserverStanza(input3) {
202474
202474
  if (input3.network !== "devnet" && LOOPBACK_HOSTS.has(host.toLowerCase())) {
202475
202475
  throw new UnsupportedObserverError(`loopback observer endpoint is not container-visible on ${input3.network}; use a docker DNS name such as indexer:3700`);
202476
202476
  }
202477
- if (input3.mode === "signer-shared" && !input3.recovery) {
202478
- throw new UnsupportedObserverError("signer-shared mode requires --recovery journal or --recovery archive");
202479
- }
202480
202477
  return { endpoint };
202481
202478
  }
202482
202479
  function renderObserverStanza(input3) {
@@ -202484,7 +202481,7 @@ function renderObserverStanza(input3) {
202484
202481
  const indexer = input3.mode === "indexer";
202485
202482
  const timeoutMs = indexer ? 2000 : 500;
202486
202483
  const disableRetries = !indexer;
202487
- const comment = indexer ? "# Pure indexer: retry delivery. A slow observer can stall the node." : "# Signer-shared: do not retry. Missed blocks refill from the journal/archive.";
202484
+ const comment = indexer ? "# Pure indexer: retry delivery. A slow observer can stall the node." : "# Signer-shared: do not retry. A missed block stays a gap until `secondlayer repair`.";
202488
202485
  return [
202489
202486
  comment,
202490
202487
  "[[events_observer]]",
@@ -202501,10 +202498,9 @@ function defaultObserverEndpoint(network) {
202501
202498
  return "127.0.0.1:3700";
202502
202499
  return "indexer:3700";
202503
202500
  }
202504
- var OBSERVER_MODES, RECOVERY_SOURCES, UnsupportedObserverError, LOOPBACK_HOSTS;
202501
+ var OBSERVER_MODES, UnsupportedObserverError, LOOPBACK_HOSTS;
202505
202502
  var init_observer_stanza = __esm(() => {
202506
202503
  OBSERVER_MODES = ["indexer", "signer-shared"];
202507
- RECOVERY_SOURCES = ["journal", "archive"];
202508
202504
  UnsupportedObserverError = class UnsupportedObserverError extends Error {
202509
202505
  name = "UnsupportedObserverError";
202510
202506
  };
@@ -202706,7 +202702,7 @@ function resolveNonInteractiveConfig(flags) {
202706
202702
  throw new MissingSetupFlagError("--node-mode", "Missing --node-mode <external|stacks|full>. Non-interactive setup requires it explicitly — there is no safe default.");
202707
202703
  }
202708
202704
  if (!flags.against && !flags.skipBootstrap) {
202709
- throw new MissingSetupFlagError("--against", "Missing --against <manifest-url>. Pass an archive manifest to bootstrap from, or --skip-bootstrap to sync from genesis instead.");
202705
+ throw new MissingSetupFlagError("--against", "Missing --against <manifest-url>. Pass an archive manifest to bootstrap from, or --skip-bootstrap to index only what your node sends from now on.");
202710
202706
  }
202711
202707
  const network = parseInstanceNetwork(flags.network);
202712
202708
  const nodeMode = parseSetupNodeMode(flags.nodeMode);
@@ -202733,8 +202729,8 @@ function guardrailPreview(nodeMode, network) {
202733
202729
  diskFloorGb: diskFloorGb(nodeMode, network)
202734
202730
  };
202735
202731
  }
202736
- function isBunRuntime() {
202737
- return typeof process !== "undefined" && typeof process.versions === "object" && process.versions !== null && typeof process.versions.bun === "string";
202732
+ function isBunRuntime(versions = typeof process !== "undefined" ? process.versions : undefined) {
202733
+ return typeof versions === "object" && versions !== null && typeof versions.bun === "string";
202738
202734
  }
202739
202735
  async function checkDocker() {
202740
202736
  const probe = spawnSync5("docker", ["info"], { stdio: "ignore" });
@@ -203894,7 +203890,7 @@ var {
203894
203890
  // package.json
203895
203891
  var package_default = {
203896
203892
  name: "@secondlayer/cli",
203897
- version: "15.0.1",
203893
+ version: "16.0.1",
203898
203894
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
203899
203895
  repository: {
203900
203896
  type: "git",
@@ -203935,10 +203931,10 @@ var package_default = {
203935
203931
  "@opentui/react": "^0.5.3",
203936
203932
  "@secondlayer/bundler": "^0.5.3",
203937
203933
  "@secondlayer/scaffold": "^1.5.7",
203938
- "@secondlayer/sdk": "^10.4.2",
203939
- "@secondlayer/shared": "^11.6.1",
203940
- "@secondlayer/stacks": "^6.0.0",
203941
- "@secondlayer/subgraphs": "^4.3.4",
203934
+ "@secondlayer/sdk": "^10.5.0",
203935
+ "@secondlayer/shared": "^11.7.1",
203936
+ "@secondlayer/stacks": "^6.1.0",
203937
+ "@secondlayer/subgraphs": "^4.4.1",
203942
203938
  esbuild: "^0.28.2",
203943
203939
  react: "^19.1.0",
203944
203940
  "smol-toml": "^1.8.0",
@@ -204515,10 +204511,13 @@ Exit codes:
204515
204511
  console.error(dim(` Scope starts at ${startHeight.toLocaleString()} — earlier history is declared out of scope, not missing.`));
204516
204512
  }
204517
204513
  if (seam) {
204518
- console.error(dim(`The chain advanced to ${seam.nodeTip.toLocaleString()} while restoring — ${seam.gap.toLocaleString()} blocks to catch up.`));
204519
- console.error(dim(" Start the indexer; it backfills that range before following the tip."));
204514
+ console.error(dim(`Your node was at ${seam.nodeTip.toLocaleString()} when the restore started, ${seam.gap.toLocaleString()} blocks past the archive tip.`));
204515
+ console.error(dim(` The index has a gap from ${(tipHeight + 1).toLocaleString()} to ${seam.nodeTip.toLocaleString()}. Blocks your node sent during the restore are ingested; nothing fills the gap on its own.`));
204516
+ console.error(dim(` After the next archive publish covers it: secondlayer repair --against ${opts.against} --from-block ${tipHeight + 1} --to-block ${seam.nodeTip} --apply`));
204517
+ } else if (nodeTipAtStart === null) {
204518
+ console.error(dim(" Start the indexer to continue from there. Node unreachable, so any gap past the archive tip is unknown; `secondlayer verify` finds it once the archive covers it."));
204520
204519
  } else {
204521
- console.error(dim(" Start the indexer to continue from there. (Node unreachable — catch-up range unknown.)"));
204520
+ console.error(dim(" Start the indexer to continue from there."));
204522
204521
  }
204523
204522
  } else {
204524
204523
  const byDataset = verifyDatasets.map((d) => `${divergentRanges.filter((r) => r.dataset === d).length} ${d}`).join(", ");
@@ -208961,7 +208960,7 @@ init_observer_stanza();
208961
208960
  init_output();
208962
208961
  init_resolve_auth();
208963
208962
  function registerObserverCommand(program2) {
208964
- program2.command("observer").description("Print the Stacks events_observer stanza for this node mode").option("--mode <mode>", "indexer (retry) or signer-shared (no retry)", "indexer").option("--endpoint <host:port>", "Observer callback the node will POST to").option("--recovery <source>", "Required for signer-shared: journal or archive").addHelpText("after", `
208963
+ program2.command("observer").description("Print the Stacks events_observer stanza for this node mode").option("--mode <mode>", "indexer (retry) or signer-shared (no retry)", "indexer").option("--endpoint <host:port>", "Observer callback the node will POST to").addHelpText("after", `
208965
208964
  --network <mainnet|testnet|devnet> is the top-level global flag (see
208966
208965
  \`secondlayer --help\`) — default mainnet, same as before.
208967
208966
  `).action((opts) => {
@@ -208969,11 +208968,10 @@ function registerObserverCommand(program2) {
208969
208968
  const mode = parseObserverMode(opts.mode);
208970
208969
  const network = instanceNetworkFromEnv();
208971
208970
  const endpoint = opts.endpoint ?? defaultObserverEndpoint(network);
208972
- const recovery = opts.recovery ? parseRecoverySource(opts.recovery) : undefined;
208973
208971
  if (mode === "signer-shared") {
208974
- note("Signer-shared nodes skip observer retries. Pair with a journal or archive for completeness.");
208972
+ note("Signer-shared nodes skip observer retries. A missed block stays a gap until `secondlayer repair` fills it from the archive.");
208975
208973
  }
208976
- writeData(renderObserverStanza({ mode, endpoint, network, recovery }));
208974
+ writeData(renderObserverStanza({ mode, endpoint, network }));
208977
208975
  });
208978
208976
  }
208979
208977
  // src/commands/setup.ts
@@ -209056,9 +209054,9 @@ async function promptSetupConfig(flags) {
209056
209054
  description: "Enter your own"
209057
209055
  },
209058
209056
  {
209059
- name: "Sync from genesis",
209057
+ name: "Skip the archive",
209060
209058
  value: "skip",
209061
- description: "Skip bootstrap — slower, no download"
209059
+ description: "Index only what your node sends from now on"
209062
209060
  }
209063
209061
  ]
209064
209062
  });
@@ -209093,7 +209091,7 @@ async function promptSetupConfig(flags) {
209093
209091
  console.error(` node mode ${config.nodeMode}`);
209094
209092
  console.error(` dir ${config.dir}`);
209095
209093
  console.error(` api port ${config.apiPort}`);
209096
- console.error(` bootstrap ${config.skipBootstrap ? "skip (sync from genesis)" : config.against}`);
209094
+ console.error(` bootstrap ${config.skipBootstrap ? "skip (from the node's tip)" : config.against}`);
209097
209095
  console.error("");
209098
209096
  const proceed = await confirm4({ message: "Start setup?", default: true });
209099
209097
  if (!proceed)
@@ -209172,7 +209170,7 @@ async function runPromptedInteractive(flags) {
209172
209170
  await executeAndRender(config);
209173
209171
  }
209174
209172
  function registerSetupCommand(program2) {
209175
- program2.command("setup").description("Guided self-host onboarding: secrets, config, docker, bootstrap, verify — one command").option("--node-mode <mode>", "external, stacks, or full (required)").option("--api-port <spec>", "API publish spec", "127.0.0.1:3800").option("--dir <path>", "Target directory for compose + .env", ".").option("--against <manifest>", `Archive manifest to bootstrap from (suggested default: ${DEFAULT_ARCHIVE_MANIFEST})`).option("--skip-bootstrap", "Sync from genesis instead of restoring an archive").option("--skip-verify", "Skip the post-bootstrap verify pass").option("--yes", "Non-interactive: skip the TUI, require flags, never prompt").option("--force", "Regenerate secrets even if a .env already exists in --dir").option("--owner <owner>", "ghcr image owner (namespace) to pull from").option("--image-tag <tag>", "Published image tag to run").addHelpText("after", `
209173
+ program2.command("setup").description("Guided self-host onboarding: secrets, config, docker, bootstrap, verify — one command").option("--node-mode <mode>", "external, stacks, or full (required)").option("--api-port <spec>", "API publish spec", "127.0.0.1:3800").option("--dir <path>", "Target directory for compose + .env", ".").option("--against <manifest>", `Archive manifest to bootstrap from (suggested default: ${DEFAULT_ARCHIVE_MANIFEST})`).option("--skip-bootstrap", "Skip the archive restore; index only what your node sends from now on").option("--skip-verify", "Skip the post-bootstrap verify pass").option("--yes", "Non-interactive: skip the TUI, require flags, never prompt").option("--force", "Regenerate secrets even if a .env already exists in --dir").option("--owner <owner>", "ghcr image owner (namespace) to pull from").option("--image-tag <tag>", "Published image tag to run").addHelpText("after", `
209176
209174
  --network <mainnet|testnet|devnet> is the top-level global flag (see
209177
209175
  \`secondlayer --help\`) — required here too, just parsed one level up.
209178
209176
 
@@ -209266,5 +209264,5 @@ registerCreditsCommand(program);
209266
209264
  registerArchiveCommand(program);
209267
209265
  program.parse();
209268
209266
 
209269
- //# debugId=83D336B04841B78A64756E2164756E21
209267
+ //# debugId=88F920E6247C2F2664756E2164756E21
209270
209268
  //# sourceMappingURL=cli.js.map