@secondlayer/cli 23.2.1 → 23.4.0

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
@@ -29357,6 +29357,12 @@ function inspectSourceGitState(absPath) {
29357
29357
  }
29358
29358
  return { kind: "clean" };
29359
29359
  }
29360
+ function uncommittedSourceWarning(state, file) {
29361
+ if (state.kind !== "untracked" && state.kind !== "modified")
29362
+ return;
29363
+ const reason = state.kind === "untracked" ? "not tracked by git" : "modified with uncommitted changes";
29364
+ return `${file} is ${reason}, so this deploy's only copy is the database row. Commit it to keep a copy.`;
29365
+ }
29360
29366
  var init_git_status = () => {};
29361
29367
 
29362
29368
  // src/lib/merge-print-subgraph.ts
@@ -29990,7 +29996,6 @@ import {
29990
29996
  } from "node:fs";
29991
29997
  import { basename, dirname as dirname5, extname, join as join7, relative, resolve as resolve5 } from "node:path";
29992
29998
  import { fileURLToPath as fileURLToPath3 } from "node:url";
29993
- import { confirm as confirm2 } from "@inquirer/prompts";
29994
29999
  import {
29995
30000
  generatePrintPayloadTypes,
29996
30001
  generatePrintSchemaSubgraph as generatePrintSchemaSubgraph2,
@@ -30004,31 +30009,11 @@ import {
30004
30009
  deriveVerification as deriveVerification2,
30005
30010
  isDeterminismViolation
30006
30011
  } from "@secondlayer/subgraphs/verification";
30007
- async function loadSubgraphWithDepCheck(absPath) {
30008
- try {
30009
- return await import(absPath);
30010
- } catch (err) {
30011
- const msg = err instanceof Error ? err.message : String(err);
30012
- const code = err?.code;
30013
- const missingSdk = (code === "ERR_MODULE_NOT_FOUND" || msg.includes("ERR_MODULE_NOT_FOUND")) && msg.includes("@secondlayer/subgraphs");
30014
- if (!missingSdk)
30015
- throw err;
30016
- warn("Missing dependency: @secondlayer/subgraphs");
30017
- const install = await confirm2({
30018
- message: "Install with `bun add @secondlayer/subgraphs`?",
30019
- default: true
30020
- });
30021
- if (!install)
30022
- throw err;
30023
- await new Promise((res, rej) => {
30024
- const child = spawn2("bun", ["add", "@secondlayer/subgraphs"], {
30025
- stdio: "inherit"
30026
- });
30027
- child.on("error", rej);
30028
- child.on("exit", (c) => c === 0 ? res() : rej(new Error(`bun add exit ${c}`)));
30029
- });
30030
- return await import(absPath);
30031
- }
30012
+ async function loadSubgraphDefinition(source, fileName) {
30013
+ const { bundleSubgraphCode } = await import("@secondlayer/bundler");
30014
+ const bundled = await bundleSubgraphCode(source, { fileName });
30015
+ const url = `data:text/javascript;base64,${Buffer.from(bundled.handlerCode, "utf8").toString("base64")}`;
30016
+ return { mod: await import(url), bundled };
30032
30017
  }
30033
30018
  async function typecheckHandler(absPath) {
30034
30019
  await new Promise((res, rej) => {
@@ -30542,8 +30527,7 @@ Try --trait sip-010 or \`subgraphs scaffold ${opts.fromContract}\` for ABI calls
30542
30527
  if (opts.fromContract) {
30543
30528
  info(`Schema inferred from ${opts.fromContract} print events (${opts.tablePerTopic ? "table per topic" : "single wide table"})`);
30544
30529
  }
30545
- info(`Next: git add subgraphs/${name}.ts && secondlayer subgraphs deploy subgraphs/${name}.ts`);
30546
- note(" deploy refuses an unstaged file unless you pass --allow-uncommitted: a staged copy is the one git can recover.");
30530
+ info(`Next: secondlayer subgraphs deploy subgraphs/${name}.ts`);
30547
30531
  });
30548
30532
  subgraphs.command("add <file>").description("Merge another contract's observed print sources into an existing subgraph file").requiredOption("--from-contract <contractId>", "Contract whose print schema to merge (requires network)").option("--table-per-topic", "One table per print topic instead of a single wide table for the added contract").addHelpText("after", `
30549
30533
  Adds sources/schema/handlers for a second (or Nth) contract into an existing
@@ -30650,10 +30634,10 @@ Stopped watching.`);
30650
30634
  });
30651
30635
  await new Promise(() => {});
30652
30636
  });
30653
- subgraphs.command("deploy <file>").alias("update").description("Deploy a subgraph definition file (alias: update — deploy is create-or-update)").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--tip-first", "Go live at chain tip immediately; history backfills in the background (handlers may only insert, upsert and delete; update, increment and row reads are refused)").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").option("--allow-uncommitted", "Deploy even though the source file is not staged or committed in git (the deployed definition will exist only in the database)").addHelpText("after", `
30654
- By default the source file must be staged or committed in git (\`git add <file>\`),
30655
- otherwise the deployed definition's only copy is the row in the database. Pass
30656
- --allow-uncommitted to deploy anyway.
30637
+ subgraphs.command("deploy <file>").alias("update").description("Deploy a subgraph definition file (alias: update — deploy is create-or-update)").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--tip-first", "Go live at chain tip immediately; history backfills in the background (handlers may only insert, upsert and delete; update, increment and row reads are refused)").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").option("--allow-uncommitted", "Don't warn when the source file isn't committed in git").addHelpText("after", `
30638
+ If the source file isn't committed in git, deploy warns that the deployed
30639
+ definition's only copy is the row in the database. It never blocks; pass
30640
+ --allow-uncommitted to silence the warning.
30657
30641
 
30658
30642
  Hosted: set SECONDLAYER_API_KEY and SECONDLAYER_API_URL=https://api.secondlayer.tools.
30659
30643
  Hostable sources are event filters and contract_call/contract_deploy; anything else
@@ -30662,28 +30646,10 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
30662
30646
  try {
30663
30647
  const absPath = resolve5(file);
30664
30648
  if (!options.dryRun) {
30665
- if (options.allowUncommitted) {
30666
- info("--allow-uncommitted: skipping the git commit check for the source file.");
30667
- } else {
30668
- const gitState = inspectSourceGitState(absPath);
30669
- if (gitState.kind === "untracked" || gitState.kind === "modified") {
30670
- const reason = gitState.kind === "untracked" ? "not tracked by git" : "modified with uncommitted changes";
30671
- const message = `${file} is ${reason}. Deploy it and the only copy of this definition is a row in the database.`;
30672
- if (process.stdin.isTTY) {
30673
- warn(message);
30674
- const confirmed = await confirm2({
30675
- message: "Deploy anyway?",
30676
- default: false
30677
- });
30678
- if (!confirmed) {
30679
- info("Nothing was deployed.");
30680
- process.exit(0);
30681
- }
30682
- } else {
30683
- error(`${message} Stage it with \`git add ${file}\`, or pass --allow-uncommitted.`);
30684
- process.exit(1);
30685
- }
30686
- }
30649
+ if (!options.allowUncommitted) {
30650
+ const advice = uncommittedSourceWarning(inspectSourceGitState(absPath), file);
30651
+ if (advice)
30652
+ warn(advice);
30687
30653
  }
30688
30654
  }
30689
30655
  const config = await loadConfig2();
@@ -30697,18 +30663,28 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
30697
30663
  await typecheckHandler(absPath);
30698
30664
  }
30699
30665
  info(`Loading subgraph from ${absPath}`);
30700
- const mod = await loadSubgraphWithDepCheck(absPath);
30701
- const def = mod.default ?? mod;
30702
- const effectiveDef = {
30703
- ...startBlock === undefined ? def : { ...def, startBlock },
30704
- ...options.tipFirst ? { backfillMode: "concurrent" } : {}
30705
- };
30706
30666
  const { validateSubgraphDefinition } = await import("@secondlayer/subgraphs/validate");
30707
30667
  const { readFile } = await import("node:fs/promises");
30708
30668
  const derived = config.network !== "local" ? await withDerivedAbis(await readFile(absPath, "utf8")) : undefined;
30709
30669
  for (const name of Object.keys(derived?.abis ?? {})) {
30710
30670
  info(`Using the deployed contract's abi for source "${name}"`);
30711
30671
  }
30672
+ const source = derived?.source ?? await readFile(absPath, "utf8");
30673
+ const { mod, bundled } = await loadSubgraphDefinition(source, relative(process.cwd(), absPath));
30674
+ const def = mod.default ?? mod;
30675
+ const authored = {
30676
+ ...def,
30677
+ sources: Object.fromEntries(Object.entries(def.sources ?? {}).map(([k, v]) => {
30678
+ if (!derived?.abis[k])
30679
+ return [k, v];
30680
+ const { abi: _abi, ...rest } = v;
30681
+ return [k, rest];
30682
+ }))
30683
+ };
30684
+ const effectiveDef = {
30685
+ ...startBlock === undefined ? authored : { ...authored, startBlock },
30686
+ ...options.tipFirst ? { backfillMode: "concurrent" } : {}
30687
+ };
30712
30688
  const validated = validateSubgraphDefinition(derived && Object.keys(derived.abis).length > 0 ? {
30713
30689
  ...effectiveDef,
30714
30690
  sources: Object.fromEntries(Object.entries(effectiveDef.sources).map(([k, v]) => [
@@ -30721,11 +30697,6 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
30721
30697
  }
30722
30698
  if (config.network !== "local") {
30723
30699
  info(`${dryRun ? "Bundling for remote deploy dry run" : "Bundling for remote deploy"} (${config.network})...`);
30724
- const source = derived?.source ?? await readFile(absPath, "utf8");
30725
- const { bundleSubgraphCode } = await import("@secondlayer/bundler");
30726
- const bundled = await bundleSubgraphCode(source, {
30727
- fileName: relative(process.cwd(), absPath)
30728
- });
30729
30700
  const handlerCode = bundled.handlerCode;
30730
30701
  const localVerification = checkDeterminism(effectiveDef, bundled.findings);
30731
30702
  if (dryRun) {
@@ -30840,16 +30811,7 @@ deploy does not backfill from genesis.`).action(async (file, options) => {
30840
30811
  await printDeployFooter();
30841
30812
  }
30842
30813
  } else {
30843
- let findings;
30844
- try {
30845
- const { bundleSubgraphCode } = await import("@secondlayer/bundler");
30846
- findings = (await bundleSubgraphCode(await readFile(absPath, "utf8"), {
30847
- fileName: relative(process.cwd(), absPath)
30848
- })).findings;
30849
- } catch {
30850
- findings = undefined;
30851
- }
30852
- const verification = findings ? checkDeterminism(effectiveDef, findings) : undefined;
30814
+ const verification = checkDeterminism(effectiveDef, bundled.findings);
30853
30815
  if (dryRun) {
30854
30816
  printSubgraphDeployPreview(createSubgraphDeployPreview(validated), {
30855
30817
  network: config.network,
@@ -31892,7 +31854,7 @@ var {
31892
31854
  // package.json
31893
31855
  var package_default = {
31894
31856
  name: "@secondlayer/cli",
31895
- version: "23.2.1",
31857
+ version: "23.4.0",
31896
31858
  description: "Run a Stacks index on your own hardware — set it up, restore verified history, and keep it current.",
31897
31859
  repository: {
31898
31860
  type: "git",
@@ -31918,7 +31880,7 @@ var package_default = {
31918
31880
  build: "bunup",
31919
31881
  dev: "bunup --watch",
31920
31882
  test: "bun test",
31921
- typecheck: "tsc --noEmit",
31883
+ typecheck: "bun check",
31922
31884
  prepublishOnly: "bun run build"
31923
31885
  },
31924
31886
  keywords: [
@@ -31942,8 +31904,8 @@ var package_default = {
31942
31904
  "@secondlayer/bundler": "^0.7.3",
31943
31905
  "@secondlayer/scaffold": "^1.6.3",
31944
31906
  "@secondlayer/sdk": "^16.2.0",
31945
- "@secondlayer/shared": "^15.0.0",
31946
- "@secondlayer/stacks": "^6.5.3",
31907
+ "@secondlayer/shared": "^15.0.1",
31908
+ "@secondlayer/stacks": "^6.6.0",
31947
31909
  "@secondlayer/subgraphs": "^8.0.1",
31948
31910
  "@secondlayer/verify": "^0.6.1",
31949
31911
  esbuild: "^0.28.2",
@@ -35611,14 +35573,14 @@ import { dirname as dirname7, join as join10 } from "node:path";
35611
35573
  var DEFAULT_IMAGE_OWNER = "ryanwaits";
35612
35574
  var DEFAULT_IMAGE_TAG = "latest";
35613
35575
  var DEV_INSTANCE_TOKEN = "dev-instance-token";
35576
+ var DEV_WEBHOOK_SIGNING_KEY = "-----BEGIN PRIVATE KEY-----\\nMC4CAQAwBQYDK2VwBCIEIIczaKV9CBblFKXjqGwrA3A1FOJxY2HiST7++XGea/jX\\n-----END PRIVATE KEY-----";
35614
35577
  function buildDevnetCompose(opts = {}) {
35615
35578
  const owner = opts.owner ?? DEFAULT_IMAGE_OWNER;
35616
35579
  const tag = opts.imageTag ?? DEFAULT_IMAGE_TAG;
35617
35580
  const apiPort = opts.apiPort ?? 3800;
35618
35581
  const indexerPort = opts.indexerPort ?? 3700;
35619
35582
  const apiPublish = `127.0.0.1:${apiPort}`;
35620
- const apiImage = `ghcr.io/${owner}/secondlayer-api:${tag}`;
35621
- const indexerImage = `ghcr.io/${owner}/secondlayer-indexer:${tag}`;
35583
+ const runtimeImage = `ghcr.io/${owner}/secondlayer-runtime:${tag}`;
35622
35584
  const dbUrl = "postgres://secondlayer:secondlayer@postgres:5432/secondlayer";
35623
35585
  const DEV_SECRETS_KEY = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
35624
35586
  return `# Generated by \`secondlayer devnet connect\` — do not edit by hand.
@@ -35641,22 +35603,24 @@ services:
35641
35603
  retries: 10
35642
35604
  restart: unless-stopped
35643
35605
 
35644
- migrate:
35645
- image: ${apiImage}
35646
- command: ["bun", "run", "packages/shared/src/db/migrate.ts"]
35647
- environment:
35648
- DATABASE_URL: ${dbUrl}
35649
- depends_on:
35650
- postgres:
35651
- condition: service_healthy
35652
- restart: "no"
35653
-
35654
- api:
35655
- image: ${apiImage}
35606
+ secondlayer:
35607
+ image: ${runtimeImage}
35656
35608
  environment:
35657
35609
  INSTANCE_MODE: oss
35610
+ # Keep every network key aligned: the indexer writes index_progress under
35611
+ # STACKS_NETWORK, the subgraph processor reads it under NETWORK. If they
35612
+ # differ, catch-up finds no progress row and subgraphs never advance.
35613
+ NETWORKS: testnet
35614
+ STACKS_NETWORK: testnet
35615
+ NETWORK: testnet
35616
+ NODE_MODE: external
35617
+ # A devnet index is tiny; the runtime's RAM/disk floors target real
35618
+ # networks and a laptop's Docker VM often has less than 80 GB free.
35619
+ SECONDLAYER_ALLOW_UNDERSIZED: "true"
35658
35620
  DATABASE_URL: ${dbUrl}
35659
- PORT: 3800
35621
+ DATA_DIR: /data
35622
+ API_PORT: "3800"
35623
+ INDEXER_PORT: "3700"
35660
35624
  # 0.0.0.0 is forced: a container process that binds loopback is
35661
35625
  # unreachable through a published port. The real reach is the publish
35662
35626
  # spec below, handed over verbatim so /v1 reads stay keyless on devnet.
@@ -35665,93 +35629,48 @@ services:
35665
35629
  # Boot guard reads LISTEN_HOST, so a token is required to start at all.
35666
35630
  # It gates writes only — reads are open on this loopback publish.
35667
35631
  INSTANCE_TOKEN: ${DEV_INSTANCE_TOKEN}
35668
- NODE_ENV: production
35669
- DATA_DIR: /data
35670
- # Shared across api + subgraph-processor so the secret the api encrypts
35671
- # (e.g. a webhook's signing secret) can be decrypted by the emitter.
35672
- # OSS auto-generates a per-process key when unset — that splits them.
35673
- # Local-dev fixed value; not a production secret.
35632
+ # Fixed so the secret the api encrypts (e.g. a webhook's signing secret)
35633
+ # can be decrypted by the emitter across restarts. Not a production secret.
35674
35634
  SECONDLAYER_SECRETS_KEY: ${DEV_SECRETS_KEY}
35675
- ports:
35676
- - "${apiPublish}:3800"
35677
- volumes:
35678
- - subgraphs_data:/data/subgraphs
35679
- depends_on:
35680
- migrate:
35681
- condition: service_completed_successfully
35682
- postgres:
35683
- condition: service_healthy
35684
- healthcheck:
35685
- test: ["CMD", "curl", "-f", "http://localhost:3800/health"]
35686
- interval: 10s
35687
- timeout: 3s
35688
- start_period: 10s
35689
- retries: 5
35690
- restart: unless-stopped
35691
-
35692
- indexer:
35693
- image: ${indexerImage}
35694
- environment:
35695
- DATABASE_URL: ${dbUrl}
35696
- PORT: 3700
35697
- NODE_ENV: production
35698
- # Keep every network key aligned: the indexer writes index_progress under
35699
- # STACKS_NETWORK, the subgraph processor reads it under NETWORK. If they
35700
- # differ, catch-up finds no progress row and subgraphs never advance.
35701
- NETWORKS: testnet
35702
- STACKS_NETWORK: testnet
35703
- NETWORK: testnet
35635
+ # Signed deliveries, so receivers can test verification. Publicly known.
35636
+ SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY: "${DEV_WEBHOOK_SIGNING_KEY}"
35637
+ # The emitter blocks webhook delivery to private/loopback IPs by default.
35638
+ # On a local devnet you deliver to your own localhost receiver, so allow it.
35639
+ SECONDLAYER_ALLOW_PRIVATE_EGRESS: "true"
35640
+ # An OSS indexer with no index_progress spools observer blocks until an
35641
+ # archive import finishes. A devnet has no archive, so ingest live.
35642
+ INGEST_MODE: live
35704
35643
  # Fed by the devnet node's event observer — never reach out to Hiro mainnet.
35705
35644
  AUTO_BACKFILL_ENABLED: "false"
35706
35645
  TIP_FOLLOWER_ENABLED: "false"
35707
- # Deliberately published on every interface, unlike the api: the devnet's
35708
- # stacks-node runs in its own container and POSTs events to
35709
- # host.docker.internal:3700, which resolves to the host gateway address,
35710
- # not 127.0.0.1. A loopback publish here would drop every block.
35646
+ # clarinet publishes the devnet node RPC on the host's 20443.
35647
+ STACKS_NODE_RPC_URL: http://host.docker.internal:20443
35648
+ STREAMS_API_URL: http://127.0.0.1:3800
35649
+ SUBGRAPH_SOURCE: streams-index
35650
+ SUBGRAPH_INDEX_API_URL: http://127.0.0.1:3800
35651
+ NODE_ENV: production
35652
+ # The api is loopback-only; the indexer is deliberately published on every
35653
+ # interface: the devnet's stacks-node runs in its own container and POSTs
35654
+ # events to host.docker.internal:3700, which resolves to the host gateway
35655
+ # address, not 127.0.0.1. A loopback publish would drop every block.
35711
35656
  ports:
35657
+ - "${apiPublish}:3800"
35712
35658
  - "${indexerPort}:3700"
35713
35659
  extra_hosts:
35714
35660
  - "host.docker.internal:host-gateway"
35661
+ volumes:
35662
+ - subgraphs_data:/data/subgraphs
35715
35663
  depends_on:
35716
- migrate:
35717
- condition: service_completed_successfully
35718
35664
  postgres:
35719
35665
  condition: service_healthy
35720
35666
  healthcheck:
35721
- test: ["CMD", "curl", "-f", "http://localhost:3700/health"]
35667
+ test: ["CMD", "curl", "-f", "http://localhost:3800/health"]
35722
35668
  interval: 10s
35723
35669
  timeout: 3s
35724
- start_period: 10s
35670
+ start_period: 40s
35725
35671
  retries: 5
35726
35672
  restart: unless-stopped
35727
35673
 
35728
- subgraph-processor:
35729
- image: ${apiImage}
35730
- command: ["bun", "run", "packages/subgraphs/src/service.ts"]
35731
- environment:
35732
- DATABASE_URL: ${dbUrl}
35733
- NODE_ENV: production
35734
- DATA_DIR: /data
35735
- # Must match the indexer's network key (see indexer note) — catch-up reads
35736
- # index_progress under NETWORK.
35737
- NETWORK: testnet
35738
- STACKS_NETWORK: testnet
35739
- # The emitter blocks webhook delivery to private/loopback IPs by default.
35740
- # On a local devnet you deliver to your own localhost receiver, so allow it.
35741
- SECONDLAYER_ALLOW_PRIVATE_EGRESS: "true"
35742
- # Must match the api's key so the emitter can decrypt signing secrets.
35743
- SECONDLAYER_SECRETS_KEY: ${DEV_SECRETS_KEY}
35744
- volumes:
35745
- - subgraphs_data:/data/subgraphs
35746
- depends_on:
35747
- migrate:
35748
- condition: service_completed_successfully
35749
- postgres:
35750
- condition: service_healthy
35751
- healthcheck:
35752
- disable: true
35753
- restart: unless-stopped
35754
-
35755
35674
  volumes:
35756
35675
  postgres_data:
35757
35676
  subgraphs_data:
@@ -35910,7 +35829,7 @@ is what makes minting possible without Bitcoin.`).action(async (opts) => {
35910
35829
  const txid = await client.callContract({
35911
35830
  contract,
35912
35831
  functionName: "complete-deposit-wrapper",
35913
- functionArgs: [
35832
+ args: [
35914
35833
  Cl.bufferFromHex(depositTxid),
35915
35834
  Cl.uint(0),
35916
35835
  Cl.uint(amount),
@@ -35966,13 +35885,7 @@ function dockerCompose(composePath, args) {
35966
35885
  }
35967
35886
  var API_URL = (process.env.SECONDLAYER_API_URL || LOCAL_API_URL).replace(/\/+$/, "");
35968
35887
  var INDEXER_URL = process.env.INDEXER_URL ?? "http://localhost:3700";
35969
- var SERVICES = [
35970
- "indexer",
35971
- "api",
35972
- "subgraph-processor",
35973
- "postgres",
35974
- "migrate"
35975
- ];
35888
+ var SERVICES = ["secondlayer", "postgres"];
35976
35889
  function registerDevnetCommand(program) {
35977
35890
  const devnet = program.command("devnet").description("Run Secondlayer services against a local Clarinet devnet");
35978
35891
  registerFaucetCommand(devnet);
@@ -35985,7 +35898,7 @@ function registerDevnetCommand(program) {
35985
35898
  devnet.command("status").description("Snapshot of the local stack: ingest, subgraphs, and recent activity").option("-w, --watch", "Refresh every 2s until Ctrl-C").option("--limit <n>", "Recent activity rows to show", "12").action(async (options) => {
35986
35899
  await status(options);
35987
35900
  });
35988
- devnet.command("logs [service]").description("Tail stack logs — all services, or one of: indexer, api, subgraph-processor, postgres").option("--project <dir>", "Clarinet project directory").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Lines to show from the end of each log").action(async (service, options) => {
35901
+ devnet.command("logs [service]").description("Tail stack logs — all services, or one of: secondlayer, postgres").option("--project <dir>", "Clarinet project directory").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Lines to show from the end of each log").action(async (service, options) => {
35989
35902
  await logs(service, options);
35990
35903
  });
35991
35904
  }
@@ -36029,6 +35942,11 @@ Skipped docker. Start it with:
36029
35942
  }
36030
35943
  ensureDocker();
36031
35944
  console.log(dim(`
35945
+ Pulling latest images…`));
35946
+ if (dockerCompose(composePath, ["pull"]) !== 0) {
35947
+ console.log(yellow("couldn't pull the latest images — starting with what's cached"));
35948
+ }
35949
+ console.log(dim(`
36032
35950
  Starting Secondlayer stack (docker compose up -d)…`));
36033
35951
  if (dockerCompose(composePath, ["up", "-d"]) !== 0) {
36034
35952
  error("docker compose up failed — see output above.");
@@ -36105,7 +36023,7 @@ var SYS_COLS = new Set([
36105
36023
  "tx_id"
36106
36024
  ]);
36107
36025
  function shortVal(v) {
36108
- const s = String(v);
36026
+ const s = typeof v === "object" && v !== null ? JSON.stringify(v) : String(v);
36109
36027
  return s.length > 18 ? `${s.slice(0, 6)}…${s.slice(-4)}` : s;
36110
36028
  }
36111
36029
  async function renderStatus(limit) {
@@ -36912,7 +36830,7 @@ init_api_url();
36912
36830
  init_http();
36913
36831
  import { hostname } from "node:os";
36914
36832
  import { createInterface } from "node:readline";
36915
- import { confirm as confirm3, input } from "@inquirer/prompts";
36833
+ import { confirm as confirm2, input } from "@inquirer/prompts";
36916
36834
 
36917
36835
  // src/lib/open-browser.ts
36918
36836
  import { spawn as spawn3 } from "node:child_process";
@@ -36995,7 +36913,7 @@ async function shouldContinueLogin(target, options, deps = defaultLoginCheckDeps
36995
36913
  return false;
36996
36914
  }
36997
36915
  try {
36998
- const proceed = await confirm3({
36916
+ const proceed = await confirm2({
36999
36917
  message: "Log in as a different user?",
37000
36918
  default: false
37001
36919
  });
@@ -37742,8 +37660,7 @@ program.hook("preAction", (thisCommand) => {
37742
37660
  program.addHelpText("after", `
37743
37661
  Quickstart:
37744
37662
  $ secondlayer subgraphs create my-watcher --from-contract SP....my-contract
37745
- $ git add subgraphs/my-watcher.ts
37746
- $ secondlayer subgraphs deploy subgraphs/my-watcher.ts # or --allow-uncommitted
37663
+ $ secondlayer subgraphs deploy subgraphs/my-watcher.ts
37747
37664
 
37748
37665
  Self-host, from docker/oss in a checkout:
37749
37666
  $ secondlayer init --network mainnet
@@ -37781,5 +37698,5 @@ registerCreditsCommand(program);
37781
37698
  registerArchiveCommand(program);
37782
37699
  program.parse();
37783
37700
 
37784
- //# debugId=F92A663889BDE04D64756E2164756E21
37701
+ //# debugId=C1922C0758B86D1064756E2164756E21
37785
37702
  //# sourceMappingURL=cli.js.map