@secondlayer/cli 19.4.3 → 20.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/dist/cli.js CHANGED
@@ -29360,11 +29360,10 @@ function parseFilterArg(input) {
29360
29360
  return {
29361
29361
  field,
29362
29362
  operator,
29363
- value,
29364
- explicitOperator: true
29363
+ value
29365
29364
  };
29366
29365
  }
29367
- return { field: key, operator: "eq", value, explicitOperator: false };
29366
+ return { field: key, operator: "eq", value };
29368
29367
  }
29369
29368
  function parseFilterArgs(args) {
29370
29369
  return (args ?? []).map(parseFilterArg);
@@ -29377,25 +29376,6 @@ function parseQueryFilters(args) {
29377
29376
  }
29378
29377
  return Object.keys(filters).length > 0 ? filters : undefined;
29379
29378
  }
29380
- function parseWebhookFilter(args) {
29381
- const filters = {};
29382
- const seenFields = new Set;
29383
- for (const filter of parseFilterArgs(args)) {
29384
- if (filter.operator === "like") {
29385
- throw new Error(`Webhook filters do not support ".like". Supported operators: ${FILTER_OPERATORS.join(", ")}.`);
29386
- }
29387
- if (seenFields.has(filter.field)) {
29388
- throw new Error(`Webhook filters support one condition per field; got multiple filters for "${filter.field}".`);
29389
- }
29390
- seenFields.add(filter.field);
29391
- if (!filter.explicitOperator || filter.operator === "eq") {
29392
- filters[filter.field] = filter.value;
29393
- } else {
29394
- filters[filter.field] = { [filter.operator]: filter.value };
29395
- }
29396
- }
29397
- return Object.keys(filters).length > 0 ? filters : undefined;
29398
- }
29399
29379
  var FILTER_OPERATORS, QUERY_ONLY_OPERATORS, ALL_OPERATORS, ALL_OPERATOR_LABELS;
29400
29380
  var init_filter_params = __esm(() => {
29401
29381
  FILTER_OPERATORS = ["eq", "neq", "gt", "gte", "lt", "lte"];
@@ -29443,7 +29423,7 @@ var init_git_status = () => {};
29443
29423
 
29444
29424
  // ../../node_modules/typescript/lib/typescript.js
29445
29425
  var require_typescript = __commonJS(function(exports, module) {
29446
- var __dirname = "/Users/ryan/projects/secondlayer/.claude/worktrees/agent-af556fe64d015cdf5/node_modules/typescript/lib", __filename = "/Users/ryan/projects/secondlayer/.claude/worktrees/agent-af556fe64d015cdf5/node_modules/typescript/lib/typescript.js";
29426
+ var __dirname = "/Users/ryan/projects/secondlayer/node_modules/typescript/lib", __filename = "/Users/ryan/projects/secondlayer/node_modules/typescript/lib/typescript.js";
29447
29427
  /*! *****************************************************************************
29448
29428
  Copyright (c) Microsoft Corporation. All rights reserved.
29449
29429
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
@@ -198809,11 +198789,6 @@ import {
198809
198789
  deriveVerification as deriveVerification2,
198810
198790
  isDeterminismViolation
198811
198791
  } from "@secondlayer/subgraphs/verification";
198812
- function webhookHint(apiUrl, name, firstTable) {
198813
- if (!firstTable || isMerchantUrl(apiUrl))
198814
- return null;
198815
- return `secondlayer webhooks create ${name}-hook --subgraph ${name} --table ${firstTable} --url <your-endpoint>`;
198816
- }
198817
198792
  async function loadSubgraphWithDepCheck(absPath) {
198818
198793
  try {
198819
198794
  return await import(absPath);
@@ -199604,9 +199579,6 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
199604
199579
  info(` Reindex: ${denom} started in the background — check status in ~30s for an ETA`);
199605
199580
  }
199606
199581
  info(` Watch: secondlayer subgraphs status ${effectiveDef.name}`);
199607
- const hint = webhookHint(apiUrl, effectiveDef.name, firstTable);
199608
- if (hint)
199609
- info(` Webhook: ${hint}`);
199610
199582
  } catch {}
199611
199583
  };
199612
199584
  if (result.action === "unchanged") {
@@ -200273,7 +200245,6 @@ var init_subgraphs2 = __esm(() => {
200273
200245
  init_subgraphs();
200274
200246
  init_api_client();
200275
200247
  init_derive_abi();
200276
- init_api_url();
200277
200248
  init_config2();
200278
200249
  init_filter_params();
200279
200250
  init_fs();
@@ -202507,7 +202478,7 @@ var init_src = __esm(() => {
202507
202478
 
202508
202479
  // src/lib/dev-state.ts
202509
202480
  import { homedir as homedir4 } from "node:os";
202510
- import { join as join13 } from "node:path";
202481
+ import { join as join12 } from "node:path";
202511
202482
  function getLogsDir() {
202512
202483
  return LOGS_DIR;
202513
202484
  }
@@ -202532,9 +202503,9 @@ function isProcessRunning(pid) {
202532
202503
  }
202533
202504
  var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
202534
202505
  var init_dev_state = __esm(() => {
202535
- STATE_DIR = join13(homedir4(), ".secondlayer");
202536
- DEV_STATE_PATH = join13(STATE_DIR, "dev.json");
202537
- LOGS_DIR = join13(STATE_DIR, "logs");
202506
+ STATE_DIR = join12(homedir4(), ".secondlayer");
202507
+ DEV_STATE_PATH = join12(STATE_DIR, "dev.json");
202508
+ LOGS_DIR = join12(STATE_DIR, "logs");
202538
202509
  });
202539
202510
 
202540
202511
  // ../../node_modules/commander/index.js
@@ -202598,7 +202569,7 @@ var {
202598
202569
  // package.json
202599
202570
  var package_default = {
202600
202571
  name: "@secondlayer/cli",
202601
- version: "19.4.3",
202572
+ version: "20.0.1",
202602
202573
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
202603
202574
  repository: {
202604
202575
  type: "git",
@@ -202619,7 +202590,7 @@ var package_default = {
202619
202590
  import: "./dist/index.js"
202620
202591
  }
202621
202592
  },
202622
- files: ["dist", "templates", "README.md"],
202593
+ files: ["dist", "README.md"],
202623
202594
  scripts: {
202624
202595
  build: "bunup",
202625
202596
  dev: "bunup --watch",
@@ -202635,15 +202606,15 @@ var package_default = {
202635
202606
  "@biomejs/wasm-nodejs": "^1.9.0",
202636
202607
  "@dsnp/parquetjs": "~1.8.8",
202637
202608
  "@inquirer/prompts": "^8.2.0",
202638
- "@secondlayer/bundler": "^0.7.0",
202639
- "@secondlayer/scaffold": "^1.6.1",
202640
- "@secondlayer/sdk": "^14.5.1",
202641
- "@secondlayer/shared": "^11.24.1",
202609
+ "@secondlayer/bundler": "^0.7.1",
202610
+ "@secondlayer/scaffold": "^1.6.2",
202611
+ "@secondlayer/sdk": "^15.0.0",
202612
+ "@secondlayer/shared": "^12.0.0",
202642
202613
  "@secondlayer/stacks": "^6.2.0",
202643
- "@secondlayer/subgraphs": "^6.6.2",
202644
- "@secondlayer/verify": "^0.4.0",
202614
+ "@secondlayer/subgraphs": "^7.0.1",
202615
+ "@secondlayer/verify": "^0.5.0",
202645
202616
  esbuild: "^0.28.2",
202646
- "smol-toml": "^1.8.0",
202617
+ "smol-toml": "^1.9.1",
202647
202618
  zod: "^4.3.6"
202648
202619
  },
202649
202620
  peerDependencies: {
@@ -204080,24 +204051,12 @@ init_resolve_auth();
204080
204051
  import { readFile as readFile3 } from "node:fs/promises";
204081
204052
  import {
204082
204053
  BlockVerifier,
204054
+ LINKS,
204083
204055
  MAINNET_CHECKPOINT,
204084
204056
  NodeRpcProofSource,
204085
204057
  SecondlayerProofSource,
204086
- parseNakamotoHeader,
204087
- unhex
204058
+ describeLinks
204088
204059
  } from "@secondlayer/verify";
204089
- var LINKS = [
204090
- { step: "ancestry", label: "ancestry" },
204091
- { step: "block", label: "block" },
204092
- { step: "bitcoin", label: "bitcoin" },
204093
- { step: "burn", label: "burn" },
204094
- { step: "signer-set", label: "cycle" },
204095
- { step: "signatures", label: "signatures" },
204096
- { step: "txs", label: "txs" },
204097
- { step: "witness", label: "state root" },
204098
- { step: "names", label: "diff" },
204099
- { step: "rows", label: "rows" }
204100
- ];
204101
204060
  var LABEL_WIDTH = Math.max(...LINKS.map((l) => l.label.length));
204102
204061
  var n = (v) => v.toLocaleString("en-US");
204103
204062
  function parseBlockRef(raw) {
@@ -204151,81 +204110,20 @@ function prepareSource(src) {
204151
204110
  };
204152
204111
  return out;
204153
204112
  }
204154
- function linkDetail(step, r, cp) {
204155
- switch (step) {
204156
- case "ancestry": {
204157
- const a = r.ancestry;
204158
- if (!a)
204159
- return "";
204160
- const checkpoint = parseNakamotoHeader(unhex(cp.stacks.header));
204161
- const start = a.fromHeight === Number(checkpoint.chainLength) ? `the checkpoint ${n(a.fromHeight)}` : `block ${n(a.fromHeight)}`;
204162
- return a.via === "marf" ? `${n(r.height ?? 0)} proven in the state of ${start} (one MARF proof)` : `${n(r.height ?? 0)} reached from ${start} by parent links`;
204163
- }
204164
- case "block":
204165
- return `${n(r.height ?? 0)} ${r.blockId}`;
204166
- case "bitcoin":
204167
- return `headers ${n(cp.bitcoin.height)}..${n(r.burnHeight ?? 0)}, proof-of-work and retargets checked`;
204168
- case "burn":
204169
- return `height ${n(r.burnHeight ?? 0)} ${r.bitcoinBlockHash}`;
204170
- case "signer-set":
204171
- return r.cycle === cp.stacks.cycle ? `${r.cycle}, the checkpoint's own signer set` : `${r.cycle}, signer set proven forward from checkpoint cycle ${cp.stacks.cycle}`;
204172
- case "signatures":
204173
- return `${n(r.signerWeight ?? 0n)} / ${n(r.totalWeight ?? 0n)} weight signed, threshold ${n(r.threshold ?? 0n)}`;
204174
- case "txs":
204175
- return `${n(r.transactions?.length ?? 0)} transactions match the tx merkle root`;
204176
- case "witness":
204177
- return `${r.stateRoot} matches the witness`;
204178
- case "names": {
204179
- const d = r.diff;
204180
- if (!d)
204181
- return "";
204182
- const named = d.writes.filter((w) => w.named).length;
204183
- const written = named ? `${d.writes.length} written (${named} named, ${d.writes.length - named} unnamed)` : `${d.writes.length} written (unnamed)`;
204184
- return `${written}, ${d.carried.length} carried, ${d.internal.length} internal`;
204185
- }
204186
- case "rows":
204187
- return `${n(r.rowsChecked ?? 0)} vm_events rows match the diff`;
204188
- }
204189
- }
204190
- function notNeeded(step, r) {
204191
- if (!r.ancestry)
204192
- return false;
204193
- if (step === "bitcoin" || step === "burn")
204194
- return r.burnHeight === undefined;
204195
- return step === "signer-set" || step === "signatures";
204196
- }
204197
204113
  function report(r, cp, rows) {
204198
- const first = r.failures[0];
204199
- const broken = first ? LINKS.findIndex((l) => l.step === first.step) : LINKS.length;
204200
- for (const [i, link] of LINKS.entries()) {
204201
- const label = link.label.padEnd(LABEL_WIDTH);
204202
- const failure = r.failures.find((f) => f.step === link.step);
204203
- if (link.step === "ancestry" && !failure && !r.ancestry)
204204
- continue;
204205
- if (failure)
204206
- writeData(`${red("✗")} ${label} ${failure.message}`);
204207
- else if (link.step === "rows" && !rows)
204208
- writeData(dim(`· ${label} not checked (pass --rows)`));
204209
- else if (i > broken)
204210
- writeData(dim(`· ${label} not checked: an earlier link is broken`));
204211
- else if (notNeeded(link.step, r))
204212
- writeData(dim(`· ${label} not needed: the block is hash-chained to the checkpoint`));
204213
- else if (link.step === "rows" && r.rowsChecked === undefined)
204214
- writeData(dim(`· ${label} not checked: the source serves no indexed rows`));
204215
- else if (link.step === "txs" && r.transactions === undefined)
204216
- writeData(dim(`· ${label} not checked: no transaction bytes (epoch 2.x, or the source served the header only)`));
204114
+ const { lines, verdict } = describeLinks(r, cp, { rows });
204115
+ for (const line of lines) {
204116
+ const label = line.label.padEnd(LABEL_WIDTH);
204117
+ if (line.status === "failed")
204118
+ writeData(`${red("✗")} ${label} ${line.detail}`);
204119
+ else if (line.status === "skipped")
204120
+ writeData(dim(`· ${label} ${line.detail}`));
204217
204121
  else
204218
- writeData(`${green("✓")} ${label} ${linkDetail(link.step, r, cp)}`);
204122
+ writeData(`${green("✓")} ${label} ${line.detail}`);
204219
204123
  }
204220
204124
  for (const line of r.notes)
204221
204125
  note(` note: ${line}`);
204222
- if (!first) {
204223
- const from = n(parseNakamotoHeader(unhex(cp.stacks.header)).chainLength);
204224
- writeData(green(`✓ Block ${n(r.height ?? 0)} is proven. Trusted: only the checkpoint (Stacks ${from}, Bitcoin ${n(cp.bitcoin.height)}).`));
204225
- return;
204226
- }
204227
- const label = LINKS[broken]?.label ?? first.step;
204228
- writeData(red(first.code === "unavailable" ? `✗ Could not check the ${label} link: the source could not serve it.` : `✗ Not proven: the ${label} link is broken.`));
204126
+ writeData(verdict.ok ? green(`✓ ${verdict.text}`) : red(`✗ ${verdict.text}`));
204229
204127
  }
204230
204128
  function verificationJson(r) {
204231
204129
  const { transactions, ...rest } = r;
@@ -204309,8 +204207,8 @@ import {
204309
204207
  } from "@secondlayer/subgraphs/verify";
204310
204208
  import {
204311
204209
  MAINNET_CHECKPOINT as MAINNET_CHECKPOINT2,
204312
- parseNakamotoHeader as parseNakamotoHeader2,
204313
- unhex as unhex2
204210
+ parseNakamotoHeader,
204211
+ unhex
204314
204212
  } from "@secondlayer/verify";
204315
204213
  var LINKS2 = [
204316
204214
  { step: "pin", label: "pin" },
@@ -204335,13 +204233,13 @@ function parseHeight2(raw, flag) {
204335
204233
  throw new InputError(`${flag} must be a block height, got "${raw}"`);
204336
204234
  return Number(raw);
204337
204235
  }
204338
- async function readTable(fetchRows, name, table) {
204236
+ async function readTable(fetchRows, name, table, pageSize = PAGE) {
204339
204237
  const out = [];
204340
204238
  let cursor;
204341
204239
  for (;; ) {
204342
204240
  const page = await fetchRows(name, table, cursor);
204343
204241
  out.push(...page.rows);
204344
- if (!page.next_cursor || page.rows.length === 0)
204242
+ if (!page.next_cursor || page.rows.length < pageSize)
204345
204243
  return out;
204346
204244
  cursor = page.next_cursor;
204347
204245
  }
@@ -204398,7 +204296,7 @@ function report2(r, from, to) {
204398
204296
  return VERIFY_EXIT.UNANCHORED;
204399
204297
  }
204400
204298
  const cp = MAINNET_CHECKPOINT2;
204401
- const stacks = n2(Number(parseNakamotoHeader2(unhex2(cp.stacks.header)).chainLength));
204299
+ const stacks = n2(Number(parseNakamotoHeader(unhex(cp.stacks.header)).chainLength));
204402
204300
  writeData(green(`✓ ${r.name} ${n2(from)}..${n2(to)} recomputed from proven inputs. Trusted: only the checkpoint (Stacks ${stacks}, Bitcoin ${n2(cp.bitcoin.height)}).`));
204403
204301
  writeData(dim(` unproven, so not compared: ${[...r.unproven, "rows compare declared columns and _block_height only"].join("; ")}`));
204404
204302
  return VERIFY_EXIT.CLEAN;
@@ -205574,84 +205472,19 @@ function printPublicStatus(status, diagnosis) {
205574
205472
  }
205575
205473
  // src/commands/webhooks.ts
205576
205474
  init_api_client();
205577
- init_filter_params();
205578
205475
  init_output();
205579
205476
  init_resolve_auth();
205580
205477
  import { buildDoctorReport, isSuccessDelivery } from "@secondlayer/sdk";
205581
205478
  import { sign } from "@secondlayer/shared/crypto/standard-webhooks";
205582
205479
 
205583
- // src/lib/webhook-validation.ts
205584
- import {
205585
- validateWebhookFilterForTable
205586
- } from "@secondlayer/shared/schemas/webhooks";
205587
- async function validateWebhookTargetFromApi(client, input) {
205588
- const subgraph = await client.subgraphs.status(input.subgraphName);
205589
- const errors = validateWebhookFilterForTable({
205590
- subgraphName: input.subgraphName,
205591
- tableName: input.tableName,
205592
- filter: input.filter,
205593
- tables: subgraph.tables
205594
- });
205595
- if (errors.length > 0) {
205596
- throw new Error(errors.join(`
205597
- `));
205598
- }
205599
- }
205600
-
205601
205480
  // src/commands/create.ts
205602
- init_filter_params();
205603
205481
  init_output();
205604
205482
  init_resolve_auth();
205605
- import {
205606
- chmodSync,
205607
- copyFileSync,
205608
- existsSync as existsSync5,
205609
- mkdirSync as mkdirSync3,
205610
- readFileSync as readFileSync5,
205611
- readdirSync,
205612
- statSync as statSync2,
205613
- writeFileSync as writeFileSync4
205614
- } from "node:fs";
205615
- import { dirname as dirname6, join as join9, relative as relative2, resolve as resolve7 } from "node:path";
205616
- import { fileURLToPath as fileURLToPath4 } from "node:url";
205617
- import { input, select as select3 } from "@inquirer/prompts";
205483
+ import { readFileSync as readFileSync5 } from "node:fs";
205618
205484
  import { SecondLayer as SecondLayer4 } from "@secondlayer/sdk";
205619
205485
  import {
205620
205486
  ChainTriggerSchema
205621
205487
  } from "@secondlayer/shared/schemas/webhooks";
205622
- var RUNTIMES = ["inngest", "trigger", "cloudflare", "node"];
205623
- var FORMAT_BY_RUNTIME = {
205624
- inngest: "inngest",
205625
- trigger: "trigger",
205626
- cloudflare: "cloudflare",
205627
- node: "standard-webhooks"
205628
- };
205629
- function templatesRoot() {
205630
- const here = dirname6(fileURLToPath4(import.meta.url));
205631
- const candidateDist = resolve7(here, "..", "templates", "webhooks");
205632
- if (existsSync5(candidateDist))
205633
- return candidateDist;
205634
- return resolve7(here, "..", "..", "templates", "webhooks");
205635
- }
205636
- function copyTemplate(src, dest, vars) {
205637
- if (!existsSync5(src)) {
205638
- throw new Error(`template dir missing: ${src}`);
205639
- }
205640
- mkdirSync3(dest, { recursive: true });
205641
- const entries = readdirSync(src);
205642
- for (const entry of entries) {
205643
- const from = join9(src, entry);
205644
- const to = join9(dest, entry);
205645
- const st = statSync2(from);
205646
- if (st.isDirectory()) {
205647
- copyTemplate(from, to, vars);
205648
- } else {
205649
- const raw = readFileSync5(from, "utf8");
205650
- const rendered = raw.replace(/\{\{([A-Z_]+)\}\}/g, (match, key) => vars[key] ?? match);
205651
- writeFileSync4(to, rendered);
205652
- }
205653
- }
205654
- }
205655
205488
  function parseTriggersInput(opts) {
205656
205489
  const raw = [];
205657
205490
  if (opts.triggersFile) {
@@ -205684,53 +205517,6 @@ function parseTriggersInput(opts) {
205684
205517
  return result.data;
205685
205518
  });
205686
205519
  }
205687
- function resolveRuntime(opts) {
205688
- if (opts.runtime)
205689
- return opts.runtime;
205690
- const scripted = opts.subgraph !== undefined || opts.table !== undefined || opts.url !== undefined || opts.scaffold === false;
205691
- return scripted ? "node" : undefined;
205692
- }
205693
- function requireTtyFor(flag) {
205694
- if (process.stdin.isTTY)
205695
- return;
205696
- error(`${flag} is required when stdin is not a TTY (no prompt can run). Pass it, or run from a terminal.`);
205697
- process.exit(1);
205698
- }
205699
- async function promptFor(_name, opts) {
205700
- let runtime = resolveRuntime(opts);
205701
- if (runtime === undefined) {
205702
- requireTtyFor("--runtime");
205703
- runtime = await select3({
205704
- message: "Runtime?",
205705
- choices: RUNTIMES.map((r) => ({ name: r, value: r }))
205706
- });
205707
- }
205708
- let subgraph = opts.subgraph;
205709
- if (subgraph === undefined) {
205710
- requireTtyFor("--subgraph");
205711
- subgraph = await input({
205712
- message: "Subgraph name (must already be deployed):",
205713
- validate: (v) => v.trim().length > 0 ? true : "required"
205714
- });
205715
- }
205716
- let table = opts.table;
205717
- if (table === undefined) {
205718
- requireTtyFor("--table");
205719
- table = await input({
205720
- message: "Table to subscribe to:",
205721
- validate: (v) => v.trim().length > 0 ? true : "required"
205722
- });
205723
- }
205724
- let url = opts.url;
205725
- if (url === undefined) {
205726
- requireTtyFor("--url");
205727
- url = await input({
205728
- message: runtime === "inngest" ? "Inngest event endpoint URL (e.g. https://inn.gs/e/<KEY> or http://localhost:8288/e/<KEY>):" : runtime === "trigger" ? "Trigger.dev task URL (e.g. https://api.trigger.dev/api/v1/tasks/<TASK_ID>/trigger):" : runtime === "cloudflare" ? "Cloudflare Workflows instances URL:" : "Your HTTP receiver URL (e.g. https://yourapp.example/webhook):",
205729
- validate: (v) => v.startsWith("http://") || v.startsWith("https://") ? true : "must be http(s) URL"
205730
- });
205731
- }
205732
- return { runtime, subgraph, table, url };
205733
- }
205734
205520
  function buildWebhookAuthConfig(authToken) {
205735
205521
  if (authToken === undefined)
205736
205522
  return;
@@ -205740,139 +205526,9 @@ function buildWebhookAuthConfig(authToken) {
205740
205526
  }
205741
205527
  return { authType: "bearer", token };
205742
205528
  }
205743
- function writeSigningSecretEnv(targetDir, signingSecret) {
205744
- const envTarget = join9(targetDir, ".env");
205745
- const envExample = join9(targetDir, ".env.example");
205746
- if (existsSync5(envExample) && !existsSync5(envTarget)) {
205747
- copyFileSync(envExample, envTarget);
205748
- chmodSync(envTarget, 384);
205749
- }
205750
- if (!existsSync5(envTarget)) {
205751
- writeFileSync4(envTarget, `SIGNING_SECRET=${signingSecret}
205752
- `, {
205753
- mode: 384
205754
- });
205755
- } else {
205756
- const cur = readFileSync5(envTarget, "utf8");
205757
- writeFileSync4(envTarget, cur.match(/^SIGNING_SECRET=/m) ? cur.replace(/^SIGNING_SECRET=.*/m, `SIGNING_SECRET=${signingSecret}`) : `${cur}
205758
- SIGNING_SECRET=${signingSecret}
205759
- `, { mode: 384 });
205760
- chmodSync(envTarget, 384);
205761
- }
205762
- return envTarget;
205763
- }
205764
- async function createWebhook(name, opts) {
205765
- if (opts.runtime && !RUNTIMES.includes(opts.runtime)) {
205766
- error(`Unknown --runtime "${opts.runtime}". Valid: ${RUNTIMES.join(", ")}`);
205767
- process.exit(1);
205768
- }
205769
- const { runtime, subgraph, table, url } = await promptFor(name, opts);
205770
- let filter;
205771
- let authConfig;
205772
- try {
205773
- filter = parseWebhookFilter(opts.filter);
205774
- authConfig = buildWebhookAuthConfig(opts.authToken);
205775
- } catch (err) {
205776
- error(err instanceof Error ? err.message : String(err));
205777
- process.exit(1);
205778
- }
205779
- let sl = null;
205780
- if (!opts.skipApi) {
205781
- try {
205782
- sl = await getWebhookClient();
205783
- await validateWebhookTargetFromApi(sl, {
205784
- subgraphName: subgraph,
205785
- tableName: table,
205786
- filter
205787
- });
205788
- } catch (err) {
205789
- error(err instanceof Error ? err.message : String(err));
205790
- process.exit(1);
205791
- }
205792
- }
205793
- const eventName = `${subgraph}.${table}.created`;
205794
- const targetDir = resolve7(process.cwd(), name);
205795
- if (opts.scaffold !== false) {
205796
- if (existsSync5(targetDir)) {
205797
- error(`Directory already exists: ${relative2(process.cwd(), targetDir)}`);
205798
- process.exit(1);
205799
- }
205800
- const tplRoot = templatesRoot();
205801
- const tplDir = join9(tplRoot, runtime);
205802
- info(`Scaffolding ${blue(runtime)} template at ${blue(targetDir)}`);
205803
- copyTemplate(tplDir, targetDir, {
205804
- NAME: name,
205805
- EVENT_NAME: eventName,
205806
- TASK_ID: `${subgraph}-${table}`
205807
- });
205808
- }
205809
- let signingSecret = null;
205810
- let provisioningFailed = false;
205811
- if (!opts.skipApi) {
205812
- try {
205813
- if (!sl)
205814
- sl = await getWebhookClient();
205815
- const res = await sl.webhooks.create({
205816
- name,
205817
- subgraphName: subgraph,
205818
- tableName: table,
205819
- url,
205820
- format: FORMAT_BY_RUNTIME[runtime],
205821
- runtime,
205822
- ...filter ? { filter } : {},
205823
- ...authConfig ? { authConfig } : {}
205824
- });
205825
- signingSecret = res.signingSecret;
205826
- success(`Webhook provisioned: ${blue(res.webhook.id)}`);
205827
- } catch (err) {
205828
- provisioningFailed = true;
205829
- warn(`Webhook provisioning failed: ${err instanceof Error ? err.message : String(err)}`);
205830
- info("Template copied, but the webhook was not created. Fix the API error, remove the template directory, and rerun.");
205831
- }
205832
- }
205833
- let webhookStatus;
205834
- if (sl) {
205835
- try {
205836
- const list = await sl.webhooks.list();
205837
- const rows = list.data ?? [];
205838
- const created = rows.find((s) => s.name === name);
205839
- webhookStatus = created?.status;
205840
- } catch {}
205841
- }
205842
- if (signingSecret && opts.scaffold !== false) {
205843
- const envTarget = writeSigningSecretEnv(targetDir, signingSecret);
205844
- success(`Signing secret written to ${relative2(process.cwd(), envTarget)}`);
205845
- } else if (signingSecret && opts.scaffold === false) {
205846
- info(`Signing secret (store securely): ${signingSecret}`);
205847
- }
205848
- console.log();
205849
- if (provisioningFailed) {
205850
- error("Webhook was not created.");
205851
- process.exit(1);
205852
- }
205853
- const pausedLine = webhookStatus === "paused" ? `Webhook is paused. Resume:
205854
- secondlayer webhooks resume ${name}
205855
- ` : "";
205856
- const runHint = opts.scaffold === false ? `View deliveries:
205857
- secondlayer webhooks get ${name}` : `cd ${name}
205858
- bun install
205859
- bun run dev`;
205860
- success(`Done. Next:
205861
- ${pausedLine}${runHint}`);
205862
- }
205863
205529
  async function createChainWebhook(name, opts) {
205864
- for (const [flag, value] of [
205865
- ["--subgraph", opts.subgraph],
205866
- ["--table", opts.table],
205867
- ["--runtime", opts.runtime]
205868
- ]) {
205869
- if (value !== undefined) {
205870
- error(`${flag} is not valid with --trigger/--triggers-file (chain mode)`);
205871
- process.exit(1);
205872
- }
205873
- }
205874
205530
  if (!opts.url) {
205875
- error("--url is required when creating a chain webhook");
205531
+ error("--url is required");
205876
205532
  process.exit(1);
205877
205533
  }
205878
205534
  let triggers;
@@ -205897,7 +205553,7 @@ async function createChainWebhook(name, opts) {
205897
205553
  });
205898
205554
  webhookId = res.webhook.id;
205899
205555
  signingSecret = res.signingSecret;
205900
- success(`Chain webhook provisioned: ${blue(webhookId)}`);
205556
+ success(`Webhook provisioned: ${blue(webhookId)}`);
205901
205557
  } catch (err) {
205902
205558
  error(`Webhook provisioning failed: ${err instanceof Error ? err.message : String(err)}`);
205903
205559
  process.exit(1);
@@ -205912,24 +205568,11 @@ async function getWebhookClient() {
205912
205568
  const { apiUrl, ephemeralKey } = await resolveHostedAuth();
205913
205569
  return new SecondLayer4({ baseUrl: apiUrl, apiKey: ephemeralKey });
205914
205570
  }
205915
- function addWebhookScaffold(parent, commandSpec, opts) {
205916
- parent.command(commandSpec).description(opts.description).option("-r, --runtime <runtime>", "inngest | trigger | cloudflare | node (default: node once -s/-t/-u or --no-scaffold is given; prompts only in a terminal with no flags)").option("-s, --subgraph <name>", "Subgraph to subscribe to").option("-t, --table <name>", "Table to subscribe to").option("-u, --url <url>", "Webhook URL").option("--auth-token <token>", "Bearer token for receiver API auth; a flag lands in shell history and ps, so set it in the receiver's env and pass it here only for a throwaway token").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--trigger <json...>", `Chain-webhook trigger as JSON (repeatable), e.g. '{"type":"sbtc_deposit"}'`).option("--triggers-file <path>", "Chain-webhook triggers as a JSON array file").option("--format <format>", "Chain mode delivery format (default standard-webhooks)").option("--skip-api", "Copy template only, don't call the API").option("--no-scaffold", "Skip the local runtime template directory (webhook-only setups)").addHelpText("after", `
205917
- Examples:
205918
- $ ${opts.examplePrefix} my-sub -s my-graph -t transfers -u https://example.com/webhook
205919
- $ ${opts.examplePrefix} my-sub -s my-graph -t balances -r inngest --filter amount.gte=1000
205920
- $ ${opts.examplePrefix} my-hook -u https://example.com/webhook --trigger '{"type":"sbtc_deposit"}'`).action(async (name, options) => {
205921
- if (options.trigger?.length || options.triggersFile) {
205922
- await createChainWebhook(name, options);
205923
- return;
205924
- }
205925
- await createWebhook(name, options);
205926
- });
205927
- }
205928
205571
  function addWebhooksCreateCommand(parent) {
205929
- addWebhookScaffold(parent, "create <name>", {
205930
- description: "Create a webhook receiver for a runtime",
205931
- examplePrefix: "secondlayer webhooks create"
205932
- });
205572
+ parent.command("create <name>").description("Create a webhook on raw chain events").option("-u, --url <url>", "Webhook URL").option("--auth-token <token>", "Bearer token for receiver API auth; a flag lands in shell history and ps, so set it in the receiver's env and pass it here only for a throwaway token").option("--trigger <json...>", `Chain trigger as JSON (repeatable), e.g. '{"type":"sbtc_deposit"}'`).option("--triggers-file <path>", "Chain triggers as a JSON array file").option("--format <format>", "Delivery format (default standard-webhooks)").addHelpText("after", `
205573
+ Examples:
205574
+ $ secondlayer webhooks create my-hook -u https://example.com/webhook --trigger '{"type":"sbtc_deposit"}'
205575
+ $ secondlayer webhooks create my-hook -u https://example.com/webhook --triggers-file triggers.json`).action(createChainWebhook);
205933
205576
  }
205934
205577
 
205935
205578
  // src/commands/webhooks.ts
@@ -205999,17 +205642,6 @@ function buildWebhookUpdatePatch(options) {
205999
205642
  if (options.format) {
206000
205643
  patch.format = options.format;
206001
205644
  }
206002
- if (options.runtime !== undefined) {
206003
- patch.runtime = options.runtime === "none" || options.runtime === "null" ? null : options.runtime;
206004
- }
206005
- if (options.clearFilter)
206006
- patch.filter = {};
206007
- if (options.filter) {
206008
- if (options.clearFilter) {
206009
- throw new Error("Use either --filter or --clear-filter, not both");
206010
- }
206011
- patch.filter = parseWebhookFilter(options.filter) ?? {};
206012
- }
206013
205645
  const maxRetries = parseIntegerOption(options.maxRetries, "--max-retries", 0);
206014
205646
  if (maxRetries !== undefined)
206015
205647
  patch.maxRetries = maxRetries;
@@ -206025,11 +205657,8 @@ function buildWebhookUpdatePatch(options) {
206025
205657
  return patch;
206026
205658
  }
206027
205659
  function formatWebhookTarget(sub) {
206028
- if (sub.kind === "chain") {
206029
- const types = sub.triggers?.map((t) => t.type);
206030
- return types && types.length > 0 ? `chain.${types.join(",")}` : "chain";
206031
- }
206032
- return `${sub.subgraphName}.${sub.tableName}`;
205660
+ const types = "triggers" in sub ? sub.triggers.map((t) => t.type) : [];
205661
+ return types.length > 0 ? `chain.${types.join(",")}` : "chain";
206033
205662
  }
206034
205663
  function formatAuthLine(auth) {
206035
205664
  const scheme = auth.type === "bearer" ? auth.hasSecret ? "bearer token (set, hidden)" : "bearer (no token set)" : auth.type === "basic" ? auth.hasSecret ? "basic auth (set, hidden)" : "basic (no credentials set)" : "none";
@@ -206042,7 +205671,6 @@ function printWebhookDetail(sub) {
206042
205671
  ["Status", sub.status],
206043
205672
  ["Target", formatWebhookTarget(sub)],
206044
205673
  ["Format", sub.format],
206045
- ["Runtime", sub.runtime ?? "none"],
206046
205674
  ["URL", sub.url],
206047
205675
  ["Auth", formatAuthLine(sub.auth)],
206048
205676
  ["Last Delivery", sub.lastDeliveryAt ?? "none"],
@@ -206058,8 +205686,8 @@ function printWebhookDetail(sub) {
206058
205686
  ["Updated", sub.updatedAt]
206059
205687
  ]));
206060
205688
  console.log(dim(`
206061
- Filter:`));
206062
- console.log(JSON.stringify(sub.filter, null, 2));
205689
+ Triggers:`));
205690
+ console.log(JSON.stringify(sub.triggers, null, 2));
206063
205691
  }
206064
205692
  var DOCTOR_ISSUE_TITLES = {
206065
205693
  warning: "This webhook can't fire yet",
@@ -206067,8 +205695,6 @@ var DOCTOR_ISSUE_TITLES = {
206067
205695
  last_error: "The last delivery failed",
206068
205696
  circuit: "Your receiver is failing",
206069
205697
  dead_letters: "Some events exhausted every retry",
206070
- subgraph_gaps: "The linked subgraph has gaps",
206071
- subgraph_catching_up: "The linked subgraph is still catching up",
206072
205698
  no_deliveries: "No deliveries yet",
206073
205699
  receiver_rate_limited: "Your receiver is rate-limiting us",
206074
205700
  receiver_down: "Your receiver looks down",
@@ -206100,7 +205726,6 @@ function formatDoctorReport(report) {
206100
205726
  ["Status", sub.status],
206101
205727
  ["Target", formatWebhookTarget(sub)],
206102
205728
  ["Format", sub.format],
206103
- ["Runtime", sub.runtime ?? "none"],
206104
205729
  ["URL", sub.url],
206105
205730
  [
206106
205731
  "Circuit",
@@ -206126,24 +205751,6 @@ Delivery summary:`),
206126
205751
  ].join(`
206127
205752
  `)
206128
205753
  ];
206129
- if (report.subgraph) {
206130
- sections.push([
206131
- dim(`
206132
- Linked subgraph:`),
206133
- formatKeyValue([
206134
- ["Name", report.subgraph.name],
206135
- ["Status", report.subgraph.status],
206136
- ["Sync", report.subgraph.syncStatus],
206137
- [
206138
- "Blocks",
206139
- `${report.subgraph.lastProcessedBlock} / ${report.subgraph.chainTip}`
206140
- ],
206141
- ["Integrity", report.subgraph.integrity],
206142
- ["Gaps", String(report.subgraph.gapCount)]
206143
- ])
206144
- ].join(`
206145
- `));
206146
- }
206147
205754
  if (report.primary)
206148
205755
  sections.push(formatPrimaryInsight(report.primary));
206149
205756
  const primaryIndex = report.primary ? report.issues.indexOf(report.primary) : -1;
@@ -206159,35 +205766,6 @@ Next steps:`), ...rest.map((hint) => ` - ${hint}`)].join(`
206159
205766
  function printDoctorReport(report) {
206160
205767
  console.log(formatDoctorReport(report));
206161
205768
  }
206162
- function syntheticValue(type) {
206163
- switch (type) {
206164
- case "uint":
206165
- case "int":
206166
- return "1000";
206167
- case "boolean":
206168
- return true;
206169
- case "timestamp":
206170
- return new Date(0).toISOString();
206171
- case "jsonb":
206172
- return {};
206173
- case "principal":
206174
- return "SP000000000000000000002Q6VF78";
206175
- default:
206176
- return "example";
206177
- }
206178
- }
206179
- function buildSyntheticRow(subgraph, tableName) {
206180
- const table = subgraph?.tables[tableName];
206181
- if (!table)
206182
- return { id: "example", value: "example" };
206183
- const row = {};
206184
- for (const [column, def] of Object.entries(table.columns)) {
206185
- if (column.startsWith("_"))
206186
- continue;
206187
- row[column] = syntheticValue(def.type);
206188
- }
206189
- return Object.keys(row).length > 0 ? row : { id: "example", value: "example" };
206190
- }
206191
205769
  function resolveSigningSecret(options, env = process.env) {
206192
205770
  const secret = options.signingSecret ?? env.SIGNING_SECRET;
206193
205771
  if (!secret) {
@@ -206201,17 +205779,16 @@ function shellQuote(value) {
206201
205779
  function buildWebhookTestFixture(input) {
206202
205780
  const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);
206203
205781
  const sub = input.webhook;
206204
- const isChain = sub.kind === "chain";
206205
- const type = isChain ? `chain.${sub.triggers?.[0]?.type ?? "event"}.apply` : `${sub.subgraphName}.${sub.tableName}.created`;
206206
- const data = isChain ? {
205782
+ const type = `chain.${sub.triggers[0]?.type ?? "event"}.apply`;
205783
+ const data = {
206207
205784
  action: "apply",
206208
205785
  canonical: true,
206209
205786
  block_hash: "0xexampleblock",
206210
205787
  block_height: 0,
206211
205788
  tx_id: input.row.tx_id ?? "0xexampletransaction",
206212
- trigger: sub.triggers?.[0]?.type ?? "event",
205789
+ trigger: sub.triggers[0]?.type ?? "event",
206213
205790
  event: input.row
206214
- } : input.row;
205791
+ };
206215
205792
  const body = JSON.stringify({
206216
205793
  type,
206217
205794
  timestamp: new Date(nowSeconds * 1000).toISOString(),
@@ -206234,25 +205811,12 @@ function buildWebhookTestFixture(input) {
206234
205811
  `);
206235
205812
  return { body, headers, curl };
206236
205813
  }
206237
- async function representativeRow(client, sub, subgraph) {
206238
- if (sub.kind === "chain" || !sub.subgraphName || !sub.tableName) {
206239
- return {
206240
- tx_id: "0xexampletransaction",
206241
- contract_id: "SP000000000000000000002Q6VF78.example",
206242
- ...sub.triggers?.[0]?.type === "contract_call" ? { function_name: "example-fn" } : {}
206243
- };
206244
- }
206245
- try {
206246
- const { rows } = await client.subgraphs.rows(sub.subgraphName, sub.tableName, {
206247
- sort: "_block_height",
206248
- order: "desc",
206249
- limit: 1
206250
- });
206251
- const row = rows[0];
206252
- if (row && typeof row === "object")
206253
- return row;
206254
- } catch {}
206255
- return buildSyntheticRow(subgraph, sub.tableName);
205814
+ function representativeRow(sub) {
205815
+ return {
205816
+ tx_id: "0xexampletransaction",
205817
+ contract_id: "SP000000000000000000002Q6VF78.example",
205818
+ ...sub.triggers[0]?.type === "contract_call" ? { function_name: "example-fn" } : {}
205819
+ };
206256
205820
  }
206257
205821
  function printDeliveries(rows) {
206258
205822
  if (rows.length === 0) {
@@ -206329,22 +205893,14 @@ ${data.length} webhook(s) total`));
206329
205893
  handleApiError(err, "get webhook");
206330
205894
  }
206331
205895
  });
206332
- parent.command("update <idOrName>").description("Update webhook config").option("--name <name>", "Rename webhook").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config; a flag lands in shell history and ps, so pass it here only for a throwaway token").option("--format <format>", "standard-webhooks | inngest | trigger | cloudflare | cloudevents | raw").option("--runtime <runtime>", "inngest | trigger | cloudflare | node | none").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--clear-filter", "Replace filter with {}").option("--max-retries <n>", "Maximum delivery retries").option("--timeout-ms <n>", "Delivery timeout in milliseconds").option("--concurrency <n>", "Per-webhook delivery concurrency").option("--json", "Output as JSON").addHelpText("after", `
205896
+ parent.command("update <idOrName>").description("Update webhook config").option("--name <name>", "Rename webhook").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config; a flag lands in shell history and ps, so pass it here only for a throwaway token").option("--format <format>", "standard-webhooks | inngest | trigger | cloudflare | cloudevents | raw").option("--max-retries <n>", "Maximum delivery retries").option("--timeout-ms <n>", "Delivery timeout in milliseconds").option("--concurrency <n>", "Per-webhook delivery concurrency").option("--json", "Output as JSON").addHelpText("after", `
206333
205897
  Examples:
206334
205898
  $ secondlayer webhooks update my-sub --url https://example.com/hook
206335
- $ secondlayer webhooks update my-sub --filter amount.gte=1000 --max-retries 5
206336
- $ secondlayer webhooks update my-sub --clear-filter`).action(async (idOrName, options) => {
205899
+ $ secondlayer webhooks update my-sub --max-retries 5 --timeout-ms 20000`).action(async (idOrName, options) => {
206337
205900
  try {
206338
205901
  const client = await getWebhookClient();
206339
205902
  const patch = buildWebhookUpdatePatch(options);
206340
- const { id, detail } = await resolveWebhookRef(client, idOrName);
206341
- if (patch.filter !== undefined && detail.subgraphName && detail.tableName) {
206342
- await validateWebhookTargetFromApi(client, {
206343
- subgraphName: detail.subgraphName,
206344
- tableName: detail.tableName,
206345
- filter: patch.filter
206346
- });
206347
- }
205903
+ const { id } = await resolveWebhookRef(client, idOrName);
206348
205904
  const updated = await client.webhooks.update(id, patch);
206349
205905
  if (options.json)
206350
205906
  printJson(updated);
@@ -206495,16 +206051,14 @@ Examples:
206495
206051
  try {
206496
206052
  const client = await getWebhookClient();
206497
206053
  const { id, detail } = await resolveWebhookRef(client, idOrName);
206498
- const [deliveries, dead, subgraph] = await Promise.allSettled([
206054
+ const [deliveries, dead] = await Promise.allSettled([
206499
206055
  client.webhooks.deliveries(id),
206500
- client.webhooks.dead(id),
206501
- detail.subgraphName ? client.subgraphs.status(detail.subgraphName) : Promise.resolve(null)
206056
+ client.webhooks.dead(id)
206502
206057
  ]);
206503
206058
  const report = buildDoctorReport({
206504
206059
  webhook: detail,
206505
206060
  deliveries: deliveries.status === "fulfilled" ? deliveries.value.data : [],
206506
- dead: dead.status === "fulfilled" ? dead.value.data : [],
206507
- subgraph: subgraph.status === "fulfilled" ? subgraph.value : null
206061
+ dead: dead.status === "fulfilled" ? dead.value.data : []
206508
206062
  });
206509
206063
  if (options.json)
206510
206064
  printJson(report);
@@ -206519,8 +206073,7 @@ Examples:
206519
206073
  const signingSecret = resolveSigningSecret(options);
206520
206074
  const client = await getWebhookClient();
206521
206075
  const { detail } = await resolveWebhookRef(client, idOrName);
206522
- const subgraph = detail.subgraphName ? await client.subgraphs.status(detail.subgraphName).catch(() => null) : null;
206523
- const row = await representativeRow(client, detail, subgraph);
206076
+ const row = representativeRow(detail);
206524
206077
  const fixture = buildWebhookTestFixture({
206525
206078
  webhook: detail,
206526
206079
  row,
@@ -206580,8 +206133,8 @@ function registerWebhooksCommand(program) {
206580
206133
  }
206581
206134
  // src/commands/devnet.ts
206582
206135
  import { spawnSync as spawnSync3 } from "node:child_process";
206583
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6 } from "node:fs";
206584
- import { dirname as dirname8, join as join12 } from "node:path";
206136
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "node:fs";
206137
+ import { dirname as dirname7, join as join11 } from "node:path";
206585
206138
 
206586
206139
  // src/lib/devnet-compose.ts
206587
206140
  var DEFAULT_IMAGE_OWNER = "ryanwaits";
@@ -206735,23 +206288,23 @@ volumes:
206735
206288
  }
206736
206289
 
206737
206290
  // src/lib/devnet-config.ts
206738
- import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
206739
- import { dirname as dirname7, join as join10, parse as parsePath } from "node:path";
206291
+ import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
206292
+ import { dirname as dirname6, join as join9, parse as parsePath } from "node:path";
206740
206293
  import { parse as parseToml } from "smol-toml";
206741
206294
  var DEFAULT_INDEXER_OBSERVER = "host.docker.internal:3700";
206742
206295
  function findClarinetProject(startDir) {
206743
206296
  let dir = startDir;
206744
206297
  const { root } = parsePath(dir);
206745
206298
  while (true) {
206746
- if (existsSync6(join10(dir, "Clarinet.toml")))
206299
+ if (existsSync5(join9(dir, "Clarinet.toml")))
206747
206300
  return dir;
206748
206301
  if (dir === root)
206749
206302
  return null;
206750
- dir = dirname7(dir);
206303
+ dir = dirname6(dir);
206751
206304
  }
206752
206305
  }
206753
206306
  function ensureEventObserver(devnetTomlPath, endpoint = DEFAULT_INDEXER_OBSERVER) {
206754
- const exists = existsSync6(devnetTomlPath);
206307
+ const exists = existsSync5(devnetTomlPath);
206755
206308
  const original = exists ? readFileSync6(devnetTomlPath, "utf8") : "";
206756
206309
  if (original.trim()) {
206757
206310
  const parsed = parseToml(original);
@@ -206766,7 +206319,7 @@ function ensureEventObserver(devnetTomlPath, endpoint = DEFAULT_INDEXER_OBSERVER
206766
206319
  const at = (arrayStart.index ?? 0) + arrayStart[0].length;
206767
206320
  const next = original.slice(at).trimStart().startsWith("]") ? entry : `${entry}, `;
206768
206321
  const patched = original.slice(0, at) + next + original.slice(at);
206769
- writeFileSync5(devnetTomlPath, patched);
206322
+ writeFileSync4(devnetTomlPath, patched);
206770
206323
  return { status: "added" };
206771
206324
  }
206772
206325
  const header = original.match(/^\[devnet\]\s*$/m);
@@ -206774,7 +206327,7 @@ function ensureEventObserver(devnetTomlPath, endpoint = DEFAULT_INDEXER_OBSERVER
206774
206327
  const at = (header.index ?? 0) + header[0].length;
206775
206328
  const patched = `${original.slice(0, at)}
206776
206329
  stacks_node_events_observers = [${entry}]${original.slice(at)}`;
206777
- writeFileSync5(devnetTomlPath, patched);
206330
+ writeFileSync4(devnetTomlPath, patched);
206778
206331
  return { status: "added" };
206779
206332
  }
206780
206333
  const prefix = original && !original.endsWith(`
@@ -206784,7 +206337,7 @@ stacks_node_events_observers = [${entry}]${original.slice(at)}`;
206784
206337
  ` : ""}[devnet]
206785
206338
  stacks_node_events_observers = [${entry}]
206786
206339
  `;
206787
- writeFileSync5(devnetTomlPath, block);
206340
+ writeFileSync4(devnetTomlPath, block);
206788
206341
  return { status: exists ? "added" : "created" };
206789
206342
  }
206790
206343
 
@@ -206795,7 +206348,7 @@ init_resolve_auth();
206795
206348
  // src/commands/faucet.ts
206796
206349
  import { randomBytes as randomBytes2 } from "node:crypto";
206797
206350
  import { readFile as readFile5 } from "node:fs/promises";
206798
- import { join as join11 } from "node:path";
206351
+ import { join as join10 } from "node:path";
206799
206352
  import { http as http3, createWalletClient } from "@secondlayer/stacks";
206800
206353
  import { mnemonicToAccount } from "@secondlayer/stacks/accounts";
206801
206354
  import { devnet } from "@secondlayer/stacks/chains";
@@ -206805,7 +206358,7 @@ init_output();
206805
206358
  var DUST_LIMIT_SATS = 546n;
206806
206359
  var DEFAULT_AMOUNT_SATS = 1000000n;
206807
206360
  async function readDeployerMnemonic(projectDir) {
206808
- const path = join11(projectDir, "settings", "Devnet.toml");
206361
+ const path = join10(projectDir, "settings", "Devnet.toml");
206809
206362
  let raw;
206810
206363
  try {
206811
206364
  raw = await readFile5(path, "utf8");
@@ -206922,7 +206475,7 @@ is what makes minting possible without Bitcoin.`).action(async (opts) => {
206922
206475
  }
206923
206476
 
206924
206477
  // src/commands/devnet.ts
206925
- var COMPOSE_REL = join12(".secondlayer", "docker-compose.yml");
206478
+ var COMPOSE_REL = join11(".secondlayer", "docker-compose.yml");
206926
206479
  function ensureDocker() {
206927
206480
  const probe = spawnSync3("docker", ["info"], { stdio: "ignore" });
206928
206481
  if (probe.error || probe.status !== 0) {
@@ -206967,7 +206520,7 @@ function registerDevnetCommand(program) {
206967
206520
  }
206968
206521
  function resolveProject(explicit) {
206969
206522
  if (explicit) {
206970
- if (!existsSync7(join12(explicit, "Clarinet.toml"))) {
206523
+ if (!existsSync6(join11(explicit, "Clarinet.toml"))) {
206971
206524
  error(`No Clarinet.toml in ${explicit}`);
206972
206525
  process.exit(1);
206973
206526
  }
@@ -206983,8 +206536,8 @@ function resolveProject(explicit) {
206983
206536
  }
206984
206537
  async function connect(options) {
206985
206538
  const project = resolveProject(options.project);
206986
- const devnetToml = join12(project, "settings", "Devnet.toml");
206987
- mkdirSync4(dirname8(devnetToml), { recursive: true });
206539
+ const devnetToml = join11(project, "settings", "Devnet.toml");
206540
+ mkdirSync3(dirname7(devnetToml), { recursive: true });
206988
206541
  const result = ensureEventObserver(devnetToml, DEFAULT_INDEXER_OBSERVER);
206989
206542
  console.log(`${green("✓")} found Clarinet.toml`);
206990
206543
  if (result.status === "present") {
@@ -206993,9 +206546,9 @@ async function connect(options) {
206993
206546
  console.log(`${green("✓")} ${result.status === "created" ? "created" : "patched"} settings/Devnet.toml`);
206994
206547
  console.log(dim(` + stacks_node_events_observers = ["${DEFAULT_INDEXER_OBSERVER}"]`));
206995
206548
  }
206996
- const composePath = join12(project, COMPOSE_REL);
206997
- mkdirSync4(dirname8(composePath), { recursive: true });
206998
- writeFileSync6(composePath, buildDevnetCompose({ owner: options.owner, imageTag: options.imageTag }));
206549
+ const composePath = join11(project, COMPOSE_REL);
206550
+ mkdirSync3(dirname7(composePath), { recursive: true });
206551
+ writeFileSync5(composePath, buildDevnetCompose({ owner: options.owner, imageTag: options.imageTag }));
206999
206552
  console.log(`${green("✓")} wrote ${COMPOSE_REL}`);
207000
206553
  if (!options.up) {
207001
206554
  console.log(dim(`
@@ -207026,8 +206579,8 @@ Stop with: secondlayer devnet down`));
207026
206579
  }
207027
206580
  async function down(options) {
207028
206581
  const project = resolveProject(options.project);
207029
- const composePath = join12(project, COMPOSE_REL);
207030
- if (!existsSync7(composePath)) {
206582
+ const composePath = join11(project, COMPOSE_REL);
206583
+ if (!existsSync6(composePath)) {
207031
206584
  error(`No ${COMPOSE_REL} in ${project} — nothing to stop. Run \`secondlayer devnet connect\` first.`);
207032
206585
  process.exit(1);
207033
206586
  }
@@ -207041,8 +206594,8 @@ async function down(options) {
207041
206594
  }
207042
206595
  async function logs(service, options) {
207043
206596
  const project = resolveProject(options.project);
207044
- const composePath = join12(project, COMPOSE_REL);
207045
- if (!existsSync7(composePath)) {
206597
+ const composePath = join11(project, COMPOSE_REL);
206598
+ if (!existsSync6(composePath)) {
207046
206599
  error(`No ${COMPOSE_REL} in ${project} — run \`secondlayer devnet connect\` first.`);
207047
206600
  process.exit(1);
207048
206601
  }
@@ -207174,7 +206727,7 @@ init_output();
207174
206727
  init_resolve_auth();
207175
206728
  import { createHash as createHash5 } from "node:crypto";
207176
206729
  import { mkdir as mkdir3, open as open2, rename as rename2 } from "node:fs/promises";
207177
- import { dirname as dirname9, isAbsolute, resolve as resolve8, sep as sep2 } from "node:path";
206730
+ import { dirname as dirname8, isAbsolute, resolve as resolve7, sep as sep2 } from "node:path";
207178
206731
  import { createStreamsClient } from "@secondlayer/sdk";
207179
206732
  import { STREAMS_EVENT_TYPES } from "@secondlayer/shared";
207180
206733
  var VALID_TYPES = STREAMS_EVENT_TYPES;
@@ -207197,12 +206750,12 @@ function dumpsClient(dumpsUrl) {
207197
206750
  });
207198
206751
  }
207199
206752
  function resolveDumpDest(to, filePath) {
207200
- const root = resolve8(to);
206753
+ const root = resolve7(to);
207201
206754
  const segments = filePath.split(/[\\/]/);
207202
206755
  if (filePath.length === 0 || isAbsolute(filePath) || filePath.includes("\\") || segments.some((s) => s === "..")) {
207203
206756
  throw new Error(`refusing dump path "${filePath}": paths must be relative and stay under ${root}`);
207204
206757
  }
207205
- const dest = resolve8(root, filePath);
206758
+ const dest = resolve7(root, filePath);
207206
206759
  if (!dest.startsWith(root + sep2)) {
207207
206760
  throw new Error(`refusing dump path "${filePath}": resolves outside ${root}`);
207208
206761
  }
@@ -207213,7 +206766,7 @@ async function downloadDumpTo(file, dest, fetchImpl, url) {
207213
206766
  if (!res.ok || !res.body) {
207214
206767
  throw new Error(`could not download dump ${file.path} (${res.status})`);
207215
206768
  }
207216
- await mkdir3(dirname9(dest), { recursive: true });
206769
+ await mkdir3(dirname8(dest), { recursive: true });
207217
206770
  const part = `${dest}.part`;
207218
206771
  const hash = createHash5("sha256");
207219
206772
  let bytes = 0;
@@ -207897,10 +207450,10 @@ init_output();
207897
207450
  import { resolveApiKey as resolveApiKey4 } from "@secondlayer/sdk";
207898
207451
 
207899
207452
  // src/lib/project-file.ts
207900
- import { existsSync as existsSync8 } from "node:fs";
207453
+ import { existsSync as existsSync7 } from "node:fs";
207901
207454
  import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
207902
207455
  import { homedir as homedir5 } from "node:os";
207903
- import { dirname as dirname10, join as join14, parse as parsePath2, resolve as resolve9 } from "node:path";
207456
+ import { dirname as dirname9, join as join13, parse as parsePath2, resolve as resolve8 } from "node:path";
207904
207457
  import { z as z4 } from "zod";
207905
207458
  var ProjectFileSchema = z4.object({
207906
207459
  slug: z4.string().min(1)
@@ -207908,23 +207461,23 @@ var ProjectFileSchema = z4.object({
207908
207461
  var FILENAME = "project";
207909
207462
  var DIRNAME = ".secondlayer";
207910
207463
  async function readActiveProject(cwd, globalDefault) {
207911
- let dir = resolve9(cwd);
207912
- const home = resolve9(homedir5());
207464
+ let dir = resolve8(cwd);
207465
+ const home = resolve8(homedir5());
207913
207466
  const fsRoot = parsePath2(dir).root;
207914
207467
  while (true) {
207915
- const candidate = join14(dir, DIRNAME, FILENAME);
207916
- if (existsSync8(candidate)) {
207468
+ const candidate = join13(dir, DIRNAME, FILENAME);
207469
+ if (existsSync7(candidate)) {
207917
207470
  try {
207918
207471
  const raw = await readFile6(candidate, "utf8");
207919
207472
  const parsed = ProjectFileSchema.parse(JSON.parse(raw));
207920
207473
  return { slug: parsed.slug, resolvedFrom: candidate };
207921
207474
  } catch {}
207922
207475
  }
207923
- if (existsSync8(join14(dir, ".git")))
207476
+ if (existsSync7(join13(dir, ".git")))
207924
207477
  break;
207925
207478
  if (dir === home || dir === fsRoot)
207926
207479
  break;
207927
- const parent = dirname10(dir);
207480
+ const parent = dirname9(dir);
207928
207481
  if (parent === dir)
207929
207482
  break;
207930
207483
  dir = parent;
@@ -207932,7 +207485,7 @@ async function readActiveProject(cwd, globalDefault) {
207932
207485
  if (globalDefault) {
207933
207486
  return {
207934
207487
  slug: globalDefault,
207935
- resolvedFrom: join14(homedir5(), ".secondlayer", "config.json")
207488
+ resolvedFrom: join13(homedir5(), ".secondlayer", "config.json")
207936
207489
  };
207937
207490
  }
207938
207491
  return null;
@@ -208005,7 +207558,7 @@ init_api_url();
208005
207558
  init_http();
208006
207559
  init_output();
208007
207560
  init_session();
208008
- import { confirm as confirm3, input as input2 } from "@inquirer/prompts";
207561
+ import { confirm as confirm3, input } from "@inquirer/prompts";
208009
207562
  function sessionExpiry() {
208010
207563
  return new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString();
208011
207564
  }
@@ -208065,7 +207618,7 @@ async function runLoginFlow(options = {}) {
208065
207618
  }
208066
207619
  }
208067
207620
  }
208068
- const email = await input2({
207621
+ const email = await input({
208069
207622
  message: "Email",
208070
207623
  validate: (v) => /^.+@.+\..+$/.test(v) ? true : "Invalid email"
208071
207624
  });
@@ -208086,7 +207639,7 @@ async function runLoginFlow(options = {}) {
208086
207639
  }
208087
207640
  process.exit(1);
208088
207641
  }
208089
- const code = await input2({
207642
+ const code = await input({
208090
207643
  message: "Enter the 6-digit code",
208091
207644
  validate: (v) => /^\d{6}$/.test(v) ? true : "Expected 6 digits"
208092
207645
  });
@@ -208147,15 +207700,15 @@ function registerLogoutCommand(program) {
208147
207700
  }
208148
207701
  // src/commands/uninstall.ts
208149
207702
  import { spawnSync as spawnSync4 } from "node:child_process";
208150
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
208151
- import { join as join15, resolve as resolve11 } from "node:path";
207703
+ import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
207704
+ import { join as join14, resolve as resolve10 } from "node:path";
208152
207705
  import { planUninstall, uninstallCommand } from "@secondlayer/shared/runtime";
208153
207706
 
208154
207707
  // src/lib/instance-init.ts
208155
207708
  init_output();
208156
207709
  import { randomBytes as randomBytes3 } from "node:crypto";
208157
- import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
208158
- import { resolve as resolve10 } from "node:path";
207710
+ import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
207711
+ import { resolve as resolve9 } from "node:path";
208159
207712
  import { ARCHIVE_ROOT_PUBLIC_KEY_PEM } from "@secondlayer/shared/archive/root-key";
208160
207713
  import { generateEd25519KeyPair } from "@secondlayer/shared/crypto/ed25519";
208161
207714
  import { INSTANCE_NETWORKS } from "@secondlayer/shared/db/queries/instance";
@@ -208204,7 +207757,7 @@ function unescapeEnvValue(raw) {
208204
207757
  `).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
208205
207758
  }
208206
207759
  function readEnvValue(envPath, key) {
208207
- if (!existsSync9(envPath))
207760
+ if (!existsSync8(envPath))
208208
207761
  return null;
208209
207762
  const match = readFileSync7(envPath, "utf8").match(new RegExp(`^${key}=(.*)$`, "m"));
208210
207763
  return match ? unescapeEnvValue(match[1]) : null;
@@ -208252,12 +207805,12 @@ function renderInstanceEnv(env) {
208252
207805
  `);
208253
207806
  }
208254
207807
  function writeInstanceEnv(cwd, env, file = INSTANCE_ENV_FILE) {
208255
- const path = resolve10(cwd, file);
208256
- writeFileSync7(path, renderInstanceEnv(env), { mode: 384 });
207808
+ const path = resolve9(cwd, file);
207809
+ writeFileSync6(path, renderInstanceEnv(env), { mode: 384 });
208257
207810
  return path;
208258
207811
  }
208259
207812
  function loadExistingInstanceEnv(cwd, file = INSTANCE_ENV_FILE) {
208260
- const path = resolve10(cwd, file);
207813
+ const path = resolve9(cwd, file);
208261
207814
  return {
208262
207815
  INSTANCE_TOKEN: readEnvValue(path, "INSTANCE_TOKEN"),
208263
207816
  SECONDLAYER_SECRETS_KEY: readEnvValue(path, "SECONDLAYER_SECRETS_KEY"),
@@ -208275,8 +207828,8 @@ init_resolve_auth();
208275
207828
  var UNINSTALL_EXIT = { OK: 0, FAILED: 1, REFUSED: 2 };
208276
207829
  var REPO_COMPOSE = "docker/oss/docker-compose.yml";
208277
207830
  function bundleHasKeys(bundleDir) {
208278
- const manifest = join15(bundleDir, "manifest.json");
208279
- if (!existsSync10(manifest))
207831
+ const manifest = join14(bundleDir, "manifest.json");
207832
+ if (!existsSync9(manifest))
208280
207833
  return false;
208281
207834
  try {
208282
207835
  const parsed = JSON.parse(readFileSync8(manifest, "utf8"));
@@ -208286,27 +207839,27 @@ function bundleHasKeys(bundleDir) {
208286
207839
  }
208287
207840
  }
208288
207841
  function resolveUninstallLayout(dir, composeOverride) {
208289
- const setupCompose = resolve11(dir, "docker-compose.yml");
208290
- const setupEnv = resolve11(dir, ".env");
208291
- const initEnv = resolve11(dir, ".env.local");
208292
- const secretsFile = [setupEnv, initEnv].find((file) => readEnvValue(file, "SECONDLAYER_SECRETS_KEY") !== null) ?? [setupEnv, initEnv].find((file) => existsSync10(file));
207842
+ const setupCompose = resolve10(dir, "docker-compose.yml");
207843
+ const setupEnv = resolve10(dir, ".env");
207844
+ const initEnv = resolve10(dir, ".env.local");
207845
+ const secretsFile = [setupEnv, initEnv].find((file) => readEnvValue(file, "SECONDLAYER_SECRETS_KEY") !== null) ?? [setupEnv, initEnv].find((file) => existsSync9(file));
208293
207846
  if (composeOverride) {
208294
- const composeFile = resolve11(dir, composeOverride);
208295
- const sibling = resolve11(composeFile, "..", ".env");
207847
+ const composeFile = resolve10(dir, composeOverride);
207848
+ const sibling = resolve10(composeFile, "..", ".env");
208296
207849
  return {
208297
207850
  composeFile,
208298
- envFile: existsSync10(sibling) ? sibling : undefined,
207851
+ envFile: existsSync9(sibling) ? sibling : undefined,
208299
207852
  secretsFile
208300
207853
  };
208301
207854
  }
208302
- if (existsSync10(setupCompose)) {
207855
+ if (existsSync9(setupCompose)) {
208303
207856
  return {
208304
207857
  composeFile: setupCompose,
208305
- envFile: existsSync10(setupEnv) ? setupEnv : undefined,
207858
+ envFile: existsSync9(setupEnv) ? setupEnv : undefined,
208306
207859
  secretsFile
208307
207860
  };
208308
207861
  }
208309
- return { composeFile: resolve11(dir, REPO_COMPOSE), secretsFile };
207862
+ return { composeFile: resolve10(dir, REPO_COMPOSE), secretsFile };
208310
207863
  }
208311
207864
  function composeDownArgs(plan, layout) {
208312
207865
  const base = uninstallCommand(plan, layout.composeFile);
@@ -208326,7 +207879,7 @@ function registerUninstallCommand(program) {
208326
207879
  const dataDir = process.env.DATA_DIR ?? "./data";
208327
207880
  const layout = resolveUninstallLayout(process.cwd(), opts.compose);
208328
207881
  const secretsPresent = !!process.env.SECONDLAYER_SECRETS_KEY || !!layout.secretsFile;
208329
- const keysBackedUp = opts.backup ? bundleHasKeys(resolve11(opts.backup)) : false;
207882
+ const keysBackedUp = opts.backup ? bundleHasKeys(resolve10(opts.backup)) : false;
208330
207883
  const decision = planUninstall({
208331
207884
  purge: opts.purge === true,
208332
207885
  confirmed: opts.yes === true,
@@ -208399,14 +207952,14 @@ init_fs();
208399
207952
  init_output();
208400
207953
  init_resolve_auth();
208401
207954
  import {
208402
- chmodSync as chmodSync2,
208403
- existsSync as existsSync11,
208404
- mkdirSync as mkdirSync5,
207955
+ chmodSync,
207956
+ existsSync as existsSync10,
207957
+ mkdirSync as mkdirSync4,
208405
207958
  readFileSync as readFileSync9,
208406
- statSync as statSync3,
208407
- writeFileSync as writeFileSync8
207959
+ statSync as statSync2,
207960
+ writeFileSync as writeFileSync7
208408
207961
  } from "node:fs";
208409
- import { join as join16, resolve as resolve12 } from "node:path";
207962
+ import { join as join15, resolve as resolve11 } from "node:path";
208410
207963
  import { closeDb, getDb as getDb4, sql as sql2 } from "@secondlayer/shared/db";
208411
207964
  import {
208412
207965
  decryptBundle,
@@ -208555,10 +208108,10 @@ async function runBackup(opts) {
208555
208108
  printError(plan.reason);
208556
208109
  process.exit(BACKUP_EXIT.REFUSED);
208557
208110
  }
208558
- const outDir = resolve12(opts.out);
208559
- mkdirSync5(outDir, { recursive: true });
208111
+ const outDir = resolve11(opts.out);
208112
+ mkdirSync4(outDir, { recursive: true });
208560
208113
  console.error("dumping database…");
208561
- const dumpPath = join16(outDir, DB_FILE);
208114
+ const dumpPath = join15(outDir, DB_FILE);
208562
208115
  const dumpCmd = pgDumpInvocation(databaseUrl, dumpPath);
208563
208116
  const dump = await runProcess(dumpCmd.cmd, "pg_dump", dumpCmd.env);
208564
208117
  if (!dump.ok) {
@@ -208570,7 +208123,7 @@ async function runBackup(opts) {
208570
208123
  db: {
208571
208124
  file: DB_FILE,
208572
208125
  sha256: await sha256File(dumpPath),
208573
- bytes: statSync3(dumpPath).size,
208126
+ bytes: statSync2(dumpPath).size,
208574
208127
  format: "pg_dump-custom"
208575
208128
  }
208576
208129
  };
@@ -208578,16 +208131,16 @@ async function runBackup(opts) {
208578
208131
  const lines = SECRET_ENV_KEYS.filter((k) => process.env[k]).map((k) => `${k}=${process.env[k]}`);
208579
208132
  const sealed = encryptBundle(lines.join(`
208580
208133
  `), passphrase);
208581
- const secretsPath = join16(outDir, SECRETS_FILE);
208582
- writeFileSync8(secretsPath, sealed);
208583
- chmodSync2(secretsPath, 384);
208134
+ const secretsPath = join15(outDir, SECRETS_FILE);
208135
+ writeFileSync7(secretsPath, sealed);
208136
+ chmodSync(secretsPath, 384);
208584
208137
  manifest.secrets = {
208585
208138
  file: SECRETS_FILE,
208586
208139
  encrypted: true,
208587
208140
  canary: sealKeyCanary(secretsKey)
208588
208141
  };
208589
208142
  }
208590
- writeFileSync8(join16(outDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
208143
+ writeFileSync7(join15(outDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
208591
208144
  `);
208592
208145
  output({
208593
208146
  json: opts.json,
@@ -208616,14 +208169,14 @@ function attachRestoreCommand(cmd) {
208616
208169
  }
208617
208170
  async function runRestore(opts) {
208618
208171
  const databaseUrl = requireDatabaseUrl();
208619
- const dir = resolve12(opts.from);
208620
- const manifestPath = join16(dir, MANIFEST_FILE);
208621
- if (!existsSync11(manifestPath)) {
208172
+ const dir = resolve11(opts.from);
208173
+ const manifestPath = join15(dir, MANIFEST_FILE);
208174
+ if (!existsSync10(manifestPath)) {
208622
208175
  printError(`no ${MANIFEST_FILE} in ${dir}`);
208623
208176
  process.exit(BACKUP_EXIT.REFUSED);
208624
208177
  }
208625
208178
  const manifest = JSON.parse(readFileSync9(manifestPath, "utf8"));
208626
- const dumpPath = join16(dir, manifest.db?.file ?? DB_FILE);
208179
+ const dumpPath = join15(dir, manifest.db?.file ?? DB_FILE);
208627
208180
  if (manifest.db && await sha256File(dumpPath) !== manifest.db.sha256) {
208628
208181
  printError("the database dump does not match the digest in the manifest; this bundle is corrupt or truncated");
208629
208182
  process.exit(BACKUP_EXIT.REFUSED);
@@ -208637,7 +208190,7 @@ async function runRestore(opts) {
208637
208190
  process.exit(BACKUP_EXIT.REFUSED);
208638
208191
  }
208639
208192
  try {
208640
- const env = decryptBundle(readFileSync9(join16(dir, manifest.secrets.file)), passphrase);
208193
+ const env = decryptBundle(readFileSync9(join15(dir, manifest.secrets.file)), passphrase);
208641
208194
  bundleKey = env.split(`
208642
208195
  `).find((l) => l.startsWith("SECONDLAYER_SECRETS_KEY="))?.slice("SECONDLAYER_SECRETS_KEY=".length).trim();
208643
208196
  } catch {
@@ -208827,7 +208380,7 @@ init_resolve_auth();
208827
208380
 
208828
208381
  // src/lib/setup-prompts.ts
208829
208382
  import { resolve as resolvePath3 } from "node:path";
208830
- import { confirm as confirm4, input as input3, select as select4 } from "@inquirer/prompts";
208383
+ import { confirm as confirm4, input as input2, select as select3 } from "@inquirer/prompts";
208831
208384
 
208832
208385
  // src/lib/oss-compose.ts
208833
208386
  function buildOssCompose(opts = {}) {
@@ -209005,10 +208558,10 @@ dbcache=4096
209005
208558
  // src/lib/setup-wizard.ts
209006
208559
  import { spawn as spawn3, spawnSync as spawnSync5 } from "node:child_process";
209007
208560
  import { randomBytes as randomBytes4 } from "node:crypto";
209008
- import { existsSync as existsSync12 } from "node:fs";
208561
+ import { existsSync as existsSync11 } from "node:fs";
209009
208562
  import { writeFile as writeFile6 } from "node:fs/promises";
209010
208563
  import { createServer } from "node:net";
209011
- import { join as join17, resolve as resolvePath2 } from "node:path";
208564
+ import { join as join16, resolve as resolvePath2 } from "node:path";
209012
208565
  import { closeDb as closeDb2, getRawClientFor } from "@secondlayer/shared/db";
209013
208566
  import { FLOORS, diskFloorGb } from "@secondlayer/shared/runtime";
209014
208567
  init_resolve_auth();
@@ -209108,8 +208661,8 @@ function randomHex(bytes) {
209108
208661
  return randomBytes4(bytes).toString("hex");
209109
208662
  }
209110
208663
  function resolveSecrets(config) {
209111
- const envPath = join17(config.dir, ".env");
209112
- const existing = config.force || !existsSync12(envPath) ? {} : readEnvFile(config.dir, envPath);
208664
+ const envPath = join16(config.dir, ".env");
208665
+ const existing = config.force || !existsSync11(envPath) ? {} : readEnvFile(config.dir, envPath);
209113
208666
  const instance = buildInstanceEnv({
209114
208667
  network: config.network,
209115
208668
  existing: {
@@ -209201,13 +208754,13 @@ function renderSetupEnv(config, secrets) {
209201
208754
  `);
209202
208755
  }
209203
208756
  async function writeSetupFiles(config, secrets) {
209204
- const composePath = join17(config.dir, "docker-compose.yml");
209205
- const envPath = join17(config.dir, ".env");
208757
+ const composePath = join16(config.dir, "docker-compose.yml");
208758
+ const envPath = join16(config.dir, ".env");
209206
208759
  await writeFile6(composePath, buildOssCompose({ owner: config.owner, imageTag: config.imageTag }));
209207
208760
  await writeFile6(envPath, renderSetupEnv(config, secrets), { mode: 384 });
209208
208761
  const result = { composePath, envPath };
209209
208762
  if (config.nodeMode === "full") {
209210
- const configTomlPath = join17(config.dir, "Config.toml");
208763
+ const configTomlPath = join16(config.dir, "Config.toml");
209211
208764
  await writeFile6(configTomlPath, buildOssStacksConfigToml({
209212
208765
  network: config.network,
209213
208766
  bitcoinRpcPassword: secrets.bitcoinRpcPassword ?? ""
@@ -209215,7 +208768,7 @@ async function writeSetupFiles(config, secrets) {
209215
208768
  result.configTomlPath = configTomlPath;
209216
208769
  }
209217
208770
  if (config.nodeMode === "full") {
209218
- const bitcoinConfPath = join17(config.dir, "bitcoin.conf");
208771
+ const bitcoinConfPath = join16(config.dir, "bitcoin.conf");
209219
208772
  await writeFile6(bitcoinConfPath, buildOssBitcoinConf({ rpcPassword: secrets.bitcoinRpcPassword ?? "" }));
209220
208773
  result.bitcoinConfPath = bitcoinConfPath;
209221
208774
  }
@@ -209593,7 +209146,7 @@ var NODE_MODE_DESCRIPTIONS = {
209593
209146
  full: "Bundled Stacks node + bitcoind."
209594
209147
  };
209595
209148
  async function promptSetupConfig(flags) {
209596
- const network = safeParse(flags.network, parseInstanceNetwork) ?? await select4({
209149
+ const network = safeParse(flags.network, parseInstanceNetwork) ?? await select3({
209597
209150
  message: "Network",
209598
209151
  choices: [
209599
209152
  {
@@ -209613,7 +209166,7 @@ async function promptSetupConfig(flags) {
209613
209166
  }
209614
209167
  ]
209615
209168
  });
209616
- const nodeMode = safeParse(flags.nodeMode, parseSetupNodeMode) ?? await select4({
209169
+ const nodeMode = safeParse(flags.nodeMode, parseSetupNodeMode) ?? await select3({
209617
209170
  message: "Node mode",
209618
209171
  choices: SETUP_NODE_MODES.map((mode) => {
209619
209172
  const floor = guardrailPreview(mode, network);
@@ -209627,7 +209180,7 @@ async function promptSetupConfig(flags) {
209627
209180
  let against = flags.against;
209628
209181
  let skipBootstrap = !!flags.skipBootstrap;
209629
209182
  if (!skipBootstrap && !against) {
209630
- const choice = await select4({
209183
+ const choice = await select3({
209631
209184
  message: "Bootstrap from",
209632
209185
  choices: [
209633
209186
  {
@@ -209652,7 +209205,7 @@ async function promptSetupConfig(flags) {
209652
209205
  } else if (choice === "skip") {
209653
209206
  skipBootstrap = true;
209654
209207
  } else {
209655
- against = (await input3({
209208
+ against = (await input2({
209656
209209
  message: "Manifest URL or local path",
209657
209210
  default: DEFAULT_ARCHIVE_MANIFEST
209658
209211
  })).trim();
@@ -209840,5 +209393,5 @@ registerCreditsCommand(program);
209840
209393
  registerArchiveCommand(program);
209841
209394
  program.parse();
209842
209395
 
209843
- //# debugId=2DB2F04CDE6074B264756E2164756E21
209396
+ //# debugId=255DFF8A4862FC7D64756E2164756E21
209844
209397
  //# sourceMappingURL=cli.js.map