@secondlayer/cli 5.10.1 → 7.0.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
@@ -100,7 +100,6 @@ async function getBiome() {
100
100
  enabled: true
101
101
  }
102
102
  });
103
- biome.registerProjectFolder();
104
103
  }
105
104
  return biome;
106
105
  }
@@ -2519,11 +2518,17 @@ var init_session = __esm(() => {
2519
2518
  });
2520
2519
 
2521
2520
  // src/lib/resolve-auth.ts
2521
+ function resolveApiUrl() {
2522
+ return process.env.SL_API_URL ?? process.env.SL_PLATFORM_API_URL ?? DEFAULT_API_URL;
2523
+ }
2524
+ function resolveEnvKey() {
2525
+ return process.env.SL_API_KEY;
2526
+ }
2522
2527
  async function resolveAuth() {
2523
- const envUrl = process.env.SL_API_URL;
2524
- const envKey = process.env.SL_SERVICE_KEY;
2525
- if (envUrl && envKey) {
2526
- return { apiUrl: envUrl, ephemeralKey: envKey, fromEnv: true };
2528
+ const apiUrl = resolveApiUrl();
2529
+ const envKey = resolveEnvKey();
2530
+ if (envKey) {
2531
+ return { apiUrl, ephemeralKey: envKey, fromEnv: true };
2527
2532
  }
2528
2533
  const session = await readSession();
2529
2534
  if (!session) {
@@ -2531,55 +2536,72 @@ async function resolveAuth() {
2531
2536
  err.code = "SESSION_EXPIRED";
2532
2537
  throw err;
2533
2538
  }
2534
- return {
2535
- apiUrl: PLATFORM_API_URL2,
2536
- ephemeralKey: session.token,
2537
- fromEnv: false
2538
- };
2539
+ return { apiUrl, ephemeralKey: session.token, fromEnv: false };
2539
2540
  }
2540
- var PLATFORM_API_URL2;
2541
+ var DEFAULT_API_URL = "https://api.secondlayer.tools";
2541
2542
  var init_resolve_auth = __esm(() => {
2542
2543
  init_session();
2543
- PLATFORM_API_URL2 = process.env.SL_PLATFORM_API_URL ?? "https://api.secondlayer.tools";
2544
2544
  });
2545
2545
 
2546
2546
  // src/lib/output.ts
2547
+ function paint(code, text) {
2548
+ return colorEnabled ? `${code}${text}${colors.reset}` : text;
2549
+ }
2547
2550
  function red(text) {
2548
- return `${colors.red}${text}${colors.reset}`;
2551
+ return paint(colors.red, text);
2549
2552
  }
2550
2553
  function green(text) {
2551
- return `${colors.green}${text}${colors.reset}`;
2554
+ return paint(colors.green, text);
2552
2555
  }
2553
2556
  function yellow(text) {
2554
- return `${colors.yellow}${text}${colors.reset}`;
2557
+ return paint(colors.yellow, text);
2555
2558
  }
2556
2559
  function blue(text) {
2557
- return `${colors.blue}${text}${colors.reset}`;
2560
+ return paint(colors.blue, text);
2558
2561
  }
2559
2562
  function magenta(text) {
2560
- return `${colors.magenta}${text}${colors.reset}`;
2563
+ return paint(colors.magenta, text);
2561
2564
  }
2562
2565
  function cyan(text) {
2563
- return `${colors.cyan}${text}${colors.reset}`;
2566
+ return paint(colors.cyan, text);
2564
2567
  }
2565
2568
  function dim(text) {
2566
- return `${colors.dim}${text}${colors.reset}`;
2569
+ return paint(colors.dim, text);
2567
2570
  }
2568
2571
  function bold(text) {
2569
- return `${colors.bold}${text}${colors.reset}`;
2572
+ return paint(colors.bold, text);
2570
2573
  }
2571
2574
  function success(message) {
2572
- console.log(green(`✓ ${message}`));
2575
+ console.error(green(`✓ ${message}`));
2573
2576
  }
2574
2577
  function error(message) {
2575
2578
  const text = message.trim() || "Command failed.";
2576
2579
  console.error(red(`✗ ${text}`));
2577
2580
  }
2578
2581
  function warn(message) {
2579
- console.log(yellow(`⚠ ${message}`));
2582
+ console.error(yellow(`⚠ ${message}`));
2580
2583
  }
2581
2584
  function info(message) {
2582
- console.log(blue(`ℹ ${message}`));
2585
+ console.error(blue(`ℹ ${message}`));
2586
+ }
2587
+ function note(message) {
2588
+ console.error(dim(message));
2589
+ }
2590
+ function printError(message, opts) {
2591
+ error(message);
2592
+ if (opts?.hint)
2593
+ console.error(dim(` → ${opts.hint}`));
2594
+ }
2595
+ function writeData(value) {
2596
+ process.stdout.write(`${value}
2597
+ `);
2598
+ }
2599
+ function output(opts) {
2600
+ if (opts.json) {
2601
+ writeData(JSON.stringify(opts.data, null, 2));
2602
+ return;
2603
+ }
2604
+ opts.human();
2583
2605
  }
2584
2606
  function stripAnsi(text) {
2585
2607
  return text.replace(ANSI_ESCAPE_PATTERN, "");
@@ -2604,8 +2626,16 @@ function formatKeyValue(pairs) {
2604
2626
  return pairs.map(([key, value]) => `${dim(key.padEnd(maxKeyLen))} ${value}`).join(`
2605
2627
  `);
2606
2628
  }
2607
- var colors, ANSI_ESCAPE_PATTERN;
2629
+ var colorEnabled, colors, ANSI_ESCAPE_PATTERN;
2608
2630
  var init_output = __esm(() => {
2631
+ colorEnabled = (() => {
2632
+ const { FORCE_COLOR, NO_COLOR } = process.env;
2633
+ if (FORCE_COLOR !== undefined && FORCE_COLOR !== "0")
2634
+ return true;
2635
+ if (NO_COLOR !== undefined && NO_COLOR !== "")
2636
+ return false;
2637
+ return Boolean(process.stdout.isTTY);
2638
+ })();
2609
2639
  colors = {
2610
2640
  reset: "\x1B[0m",
2611
2641
  red: "\x1B[31m",
@@ -4916,88 +4946,6 @@ var init_src = __esm(() => {
4916
4946
  src_default = Postgres;
4917
4947
  });
4918
4948
 
4919
- // src/lib/dev-state.ts
4920
- var exports_dev_state = {};
4921
- __export(exports_dev_state, {
4922
- saveDevState: () => saveDevState,
4923
- loadDevState: () => loadDevState,
4924
- isProcessRunning: () => isProcessRunning,
4925
- isDevRunning: () => isDevRunning,
4926
- getRunningServices: () => getRunningServices,
4927
- getLogsDir: () => getLogsDir,
4928
- getLogFile: () => getLogFile,
4929
- ensureDirs: () => ensureDirs,
4930
- clearLogs: () => clearLogs,
4931
- clearDevState: () => clearDevState
4932
- });
4933
- import { homedir as homedir4 } from "node:os";
4934
- import { join as join5 } from "node:path";
4935
- function getLogsDir() {
4936
- return LOGS_DIR;
4937
- }
4938
- function getLogFile(service) {
4939
- return join5(LOGS_DIR, `${service}.log`);
4940
- }
4941
- async function ensureDirs() {
4942
- await Bun.$`mkdir -p ${STATE_DIR}`.quiet();
4943
- await Bun.$`mkdir -p ${LOGS_DIR}`.quiet();
4944
- }
4945
- async function loadDevState() {
4946
- const file = Bun.file(DEV_STATE_PATH);
4947
- if (!await file.exists()) {
4948
- return null;
4949
- }
4950
- try {
4951
- return await file.json();
4952
- } catch {
4953
- return null;
4954
- }
4955
- }
4956
- async function saveDevState(state) {
4957
- await ensureDirs();
4958
- await Bun.write(DEV_STATE_PATH, `${JSON.stringify(state, null, 2)}
4959
- `);
4960
- }
4961
- async function clearDevState() {
4962
- const file = Bun.file(DEV_STATE_PATH);
4963
- if (await file.exists()) {
4964
- await Bun.$`rm ${DEV_STATE_PATH}`.quiet();
4965
- }
4966
- }
4967
- async function clearLogs() {
4968
- await Bun.$`rm -f ${LOGS_DIR}/*.log`.quiet().nothrow();
4969
- }
4970
- function isProcessRunning(pid) {
4971
- try {
4972
- process.kill(pid, 0);
4973
- return true;
4974
- } catch {
4975
- return false;
4976
- }
4977
- }
4978
- async function getRunningServices() {
4979
- const state = await loadDevState();
4980
- if (!state)
4981
- return {};
4982
- const running = {};
4983
- for (const [name, service] of Object.entries(state.services)) {
4984
- if (isProcessRunning(service.pid)) {
4985
- running[name] = service;
4986
- }
4987
- }
4988
- return running;
4989
- }
4990
- async function isDevRunning() {
4991
- const running = await getRunningServices();
4992
- return Object.keys(running).length > 0;
4993
- }
4994
- var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
4995
- var init_dev_state = __esm(() => {
4996
- STATE_DIR = join5(homedir4(), ".secondlayer");
4997
- DEV_STATE_PATH = join5(STATE_DIR, "dev.json");
4998
- LOGS_DIR = join5(STATE_DIR, "logs");
4999
- });
5000
-
5001
4949
  // src/utils/abi-compat.ts
5002
4950
  function normalizeAccess(access) {
5003
4951
  if (access === "read_only")
@@ -12960,6 +12908,88 @@ function inferNetwork(address) {
12960
12908
  return;
12961
12909
  }
12962
12910
 
12911
+ // src/lib/dev-state.ts
12912
+ var exports_dev_state = {};
12913
+ __export(exports_dev_state, {
12914
+ saveDevState: () => saveDevState,
12915
+ loadDevState: () => loadDevState,
12916
+ isProcessRunning: () => isProcessRunning,
12917
+ isDevRunning: () => isDevRunning,
12918
+ getRunningServices: () => getRunningServices,
12919
+ getLogsDir: () => getLogsDir,
12920
+ getLogFile: () => getLogFile,
12921
+ ensureDirs: () => ensureDirs,
12922
+ clearLogs: () => clearLogs,
12923
+ clearDevState: () => clearDevState
12924
+ });
12925
+ import { homedir as homedir4 } from "node:os";
12926
+ import { join as join8 } from "node:path";
12927
+ function getLogsDir() {
12928
+ return LOGS_DIR;
12929
+ }
12930
+ function getLogFile(service) {
12931
+ return join8(LOGS_DIR, `${service}.log`);
12932
+ }
12933
+ async function ensureDirs() {
12934
+ await Bun.$`mkdir -p ${STATE_DIR}`.quiet();
12935
+ await Bun.$`mkdir -p ${LOGS_DIR}`.quiet();
12936
+ }
12937
+ async function loadDevState() {
12938
+ const file = Bun.file(DEV_STATE_PATH);
12939
+ if (!await file.exists()) {
12940
+ return null;
12941
+ }
12942
+ try {
12943
+ return await file.json();
12944
+ } catch {
12945
+ return null;
12946
+ }
12947
+ }
12948
+ async function saveDevState(state) {
12949
+ await ensureDirs();
12950
+ await Bun.write(DEV_STATE_PATH, `${JSON.stringify(state, null, 2)}
12951
+ `);
12952
+ }
12953
+ async function clearDevState() {
12954
+ const file = Bun.file(DEV_STATE_PATH);
12955
+ if (await file.exists()) {
12956
+ await Bun.$`rm ${DEV_STATE_PATH}`.quiet();
12957
+ }
12958
+ }
12959
+ async function clearLogs() {
12960
+ await Bun.$`rm -f ${LOGS_DIR}/*.log`.quiet().nothrow();
12961
+ }
12962
+ function isProcessRunning(pid) {
12963
+ try {
12964
+ process.kill(pid, 0);
12965
+ return true;
12966
+ } catch {
12967
+ return false;
12968
+ }
12969
+ }
12970
+ async function getRunningServices() {
12971
+ const state = await loadDevState();
12972
+ if (!state)
12973
+ return {};
12974
+ const running = {};
12975
+ for (const [name, service] of Object.entries(state.services)) {
12976
+ if (isProcessRunning(service.pid)) {
12977
+ running[name] = service;
12978
+ }
12979
+ }
12980
+ return running;
12981
+ }
12982
+ async function isDevRunning() {
12983
+ const running = await getRunningServices();
12984
+ return Object.keys(running).length > 0;
12985
+ }
12986
+ var STATE_DIR, DEV_STATE_PATH, LOGS_DIR;
12987
+ var init_dev_state = __esm(() => {
12988
+ STATE_DIR = join8(homedir4(), ".secondlayer");
12989
+ DEV_STATE_PATH = join8(STATE_DIR, "dev.json");
12990
+ LOGS_DIR = join8(STATE_DIR, "logs");
12991
+ });
12992
+
12963
12993
  // src/lib/network.ts
12964
12994
  function getChainId(network) {
12965
12995
  return CHAIN_IDS[network].decimal.toString();
@@ -13175,15 +13205,15 @@ async function getNodeLogs(options2 = {}) {
13175
13205
  continue;
13176
13206
  if (options2.quiet && shouldFilterLine(line))
13177
13207
  continue;
13178
- const output = options2.format ? formatLogLine(line) : line;
13179
- if (output)
13180
- yield output;
13208
+ const output2 = options2.format ? formatLogLine(line) : line;
13209
+ if (output2)
13210
+ yield output2;
13181
13211
  }
13182
13212
  }
13183
13213
  if (buffer2) {
13184
- const output = options2.format ? formatLogLine(buffer2) : buffer2;
13185
- if (output)
13186
- yield output;
13214
+ const output2 = options2.format ? formatLogLine(buffer2) : buffer2;
13215
+ if (output2)
13216
+ yield output2;
13187
13217
  }
13188
13218
  } finally {
13189
13219
  reader.releaseLock();
@@ -14972,6 +15002,56 @@ var init_source4 = __esm(() => {
14972
15002
  source_default3 = chalk;
14973
15003
  });
14974
15004
 
15005
+ // src/commands/init.ts
15006
+ var exports_init = {};
15007
+ __export(exports_init, {
15008
+ init: () => init2
15009
+ });
15010
+ import { promises as fs4 } from "node:fs";
15011
+ import path2 from "node:path";
15012
+ async function init2() {
15013
+ const configPath = path2.join(process.cwd(), "secondlayer.config.ts");
15014
+ try {
15015
+ await fs4.access(configPath);
15016
+ console.log(source_default3.yellow("⚠ secondlayer.config.ts already exists"));
15017
+ return;
15018
+ } catch {}
15019
+ const hasClarinetProject = await fileExists2("./Clarinet.toml");
15020
+ let config;
15021
+ if (hasClarinetProject) {
15022
+ config = `import { defineConfig } from '@secondlayer/cli';
15023
+ import { clarinet } from '@secondlayer/cli/plugins';
15024
+
15025
+ export default defineConfig({
15026
+ out: './src/generated/contracts.ts',
15027
+ plugins: [
15028
+ clarinet() // Found Clarinet.toml in current directory
15029
+ ]
15030
+ });`;
15031
+ } else {
15032
+ config = `import { defineConfig } from '@secondlayer/cli';
15033
+
15034
+ export default defineConfig({
15035
+ out: './src/generated/contracts.ts',
15036
+ plugins: [],
15037
+ });`;
15038
+ }
15039
+ await fs4.writeFile(configPath, config);
15040
+ console.log(source_default3.green("✓ Created `secondlayer.config.ts`"));
15041
+ console.log("\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!");
15042
+ }
15043
+ async function fileExists2(filePath) {
15044
+ try {
15045
+ await fs4.access(filePath);
15046
+ return true;
15047
+ } catch {
15048
+ return false;
15049
+ }
15050
+ }
15051
+ var init_init = __esm(() => {
15052
+ init_source4();
15053
+ });
15054
+
14975
15055
  // ../../node_modules/fast-glob/out/utils/array.js
14976
15056
  var require_array = __commonJS((exports) => {
14977
15057
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -15034,7 +15114,7 @@ var require_path = __commonJS((exports) => {
15034
15114
  Object.defineProperty(exports, "__esModule", { value: true });
15035
15115
  exports.convertPosixPathToPattern = exports.convertWindowsPathToPattern = exports.convertPathToPattern = exports.escapePosixPath = exports.escapeWindowsPath = exports.escape = exports.removeLeadingDotSegment = exports.makeAbsolute = exports.unixify = undefined;
15036
15116
  var os4 = __require("os");
15037
- var path2 = __require("path");
15117
+ var path3 = __require("path");
15038
15118
  var IS_WINDOWS_PLATFORM = os4.platform() === "win32";
15039
15119
  var LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2;
15040
15120
  var POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
@@ -15046,7 +15126,7 @@ var require_path = __commonJS((exports) => {
15046
15126
  }
15047
15127
  exports.unixify = unixify;
15048
15128
  function makeAbsolute(cwd, filepath) {
15049
- return path2.resolve(cwd, filepath);
15129
+ return path3.resolve(cwd, filepath);
15050
15130
  }
15051
15131
  exports.makeAbsolute = makeAbsolute;
15052
15132
  function removeLeadingDotSegment(entry) {
@@ -15356,7 +15436,7 @@ var require_stringify = __commonJS((exports, module) => {
15356
15436
  const stringify2 = (node, parent = {}) => {
15357
15437
  const invalidBlock = options2.escapeInvalid && utils.isInvalidBrace(parent);
15358
15438
  const invalidNode = node.invalid === true && options2.escapeInvalid === true;
15359
- let output = "";
15439
+ let output2 = "";
15360
15440
  if (node.value) {
15361
15441
  if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
15362
15442
  return "\\" + node.value;
@@ -15368,10 +15448,10 @@ var require_stringify = __commonJS((exports, module) => {
15368
15448
  }
15369
15449
  if (node.nodes) {
15370
15450
  for (const child of node.nodes) {
15371
- output += stringify2(child);
15451
+ output2 += stringify2(child);
15372
15452
  }
15373
15453
  }
15374
- return output;
15454
+ return output2;
15375
15455
  };
15376
15456
  return stringify2(ast);
15377
15457
  };
@@ -15830,7 +15910,7 @@ var require_compile = __commonJS((exports, module) => {
15830
15910
  const invalidNode = node.invalid === true && options2.escapeInvalid === true;
15831
15911
  const invalid = invalidBlock === true || invalidNode === true;
15832
15912
  const prefix = options2.escapeInvalid === true ? "\\" : "";
15833
- let output = "";
15913
+ let output2 = "";
15834
15914
  if (node.isOpen === true) {
15835
15915
  return prefix + node.value;
15836
15916
  }
@@ -15859,10 +15939,10 @@ var require_compile = __commonJS((exports, module) => {
15859
15939
  }
15860
15940
  if (node.nodes) {
15861
15941
  for (const child of node.nodes) {
15862
- output += walk(child, node);
15942
+ output2 += walk(child, node);
15863
15943
  }
15864
15944
  }
15865
- return output;
15945
+ return output2;
15866
15946
  };
15867
15947
  return walk(ast);
15868
15948
  };
@@ -16249,23 +16329,23 @@ var require_braces = __commonJS((exports, module) => {
16249
16329
  var expand = require_expand();
16250
16330
  var parse2 = require_parse();
16251
16331
  var braces = (input5, options2 = {}) => {
16252
- let output = [];
16332
+ let output2 = [];
16253
16333
  if (Array.isArray(input5)) {
16254
16334
  for (const pattern of input5) {
16255
16335
  const result = braces.create(pattern, options2);
16256
16336
  if (Array.isArray(result)) {
16257
- output.push(...result);
16337
+ output2.push(...result);
16258
16338
  } else {
16259
- output.push(result);
16339
+ output2.push(result);
16260
16340
  }
16261
16341
  }
16262
16342
  } else {
16263
- output = [].concat(braces.create(input5, options2));
16343
+ output2 = [].concat(braces.create(input5, options2));
16264
16344
  }
16265
16345
  if (options2 && options2.expand === true && options2.nodupes === true) {
16266
- output = [...new Set(output)];
16346
+ output2 = [...new Set(output2)];
16267
16347
  }
16268
- return output;
16348
+ return output2;
16269
16349
  };
16270
16350
  braces.parse = (input5, options2 = {}) => parse2(input5, options2);
16271
16351
  braces.stringify = (input5, options2 = {}) => {
@@ -16304,7 +16384,7 @@ var require_braces = __commonJS((exports, module) => {
16304
16384
 
16305
16385
  // ../../node_modules/picomatch/lib/constants.js
16306
16386
  var require_constants2 = __commonJS((exports, module) => {
16307
- var path2 = __require("path");
16387
+ var path3 = __require("path");
16308
16388
  var WIN_SLASH = "\\\\/";
16309
16389
  var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
16310
16390
  var DOT_LITERAL = "\\.";
@@ -16426,7 +16506,7 @@ var require_constants2 = __commonJS((exports, module) => {
16426
16506
  CHAR_UNDERSCORE: 95,
16427
16507
  CHAR_VERTICAL_LINE: 124,
16428
16508
  CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
16429
- SEP: path2.sep,
16509
+ SEP: path3.sep,
16430
16510
  extglobChars(chars) {
16431
16511
  return {
16432
16512
  "!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` },
@@ -16444,7 +16524,7 @@ var require_constants2 = __commonJS((exports, module) => {
16444
16524
 
16445
16525
  // ../../node_modules/picomatch/lib/utils.js
16446
16526
  var require_utils2 = __commonJS((exports) => {
16447
- var path2 = __require("path");
16527
+ var path3 = __require("path");
16448
16528
  var win32 = process.platform === "win32";
16449
16529
  var {
16450
16530
  REGEX_BACKSLASH,
@@ -16473,7 +16553,7 @@ var require_utils2 = __commonJS((exports) => {
16473
16553
  if (options2 && typeof options2.windows === "boolean") {
16474
16554
  return options2.windows;
16475
16555
  }
16476
- return win32 === true || path2.sep === "\\";
16556
+ return win32 === true || path3.sep === "\\";
16477
16557
  };
16478
16558
  exports.escapeLast = (input5, char, lastIdx) => {
16479
16559
  const idx = input5.lastIndexOf(char, lastIdx);
@@ -16484,21 +16564,21 @@ var require_utils2 = __commonJS((exports) => {
16484
16564
  return `${input5.slice(0, idx)}\\${input5.slice(idx)}`;
16485
16565
  };
16486
16566
  exports.removePrefix = (input5, state = {}) => {
16487
- let output = input5;
16488
- if (output.startsWith("./")) {
16489
- output = output.slice(2);
16567
+ let output2 = input5;
16568
+ if (output2.startsWith("./")) {
16569
+ output2 = output2.slice(2);
16490
16570
  state.prefix = "./";
16491
16571
  }
16492
- return output;
16572
+ return output2;
16493
16573
  };
16494
16574
  exports.wrapOutput = (input5, state = {}, options2 = {}) => {
16495
16575
  const prepend = options2.contains ? "" : "^";
16496
16576
  const append = options2.contains ? "" : "$";
16497
- let output = `${prepend}(?:${input5})${append}`;
16577
+ let output2 = `${prepend}(?:${input5})${append}`;
16498
16578
  if (state.negated === true) {
16499
- output = `(?:^(?!${output}).*$)`;
16579
+ output2 = `(?:^(?!${output2}).*$)`;
16500
16580
  }
16501
- return output;
16581
+ return output2;
16502
16582
  };
16503
16583
  });
16504
16584
 
@@ -16976,14 +17056,14 @@ var require_parse2 = __commonJS((exports, module) => {
16976
17056
  token.prev = prev;
16977
17057
  token.parens = state.parens;
16978
17058
  token.output = state.output;
16979
- const output = (opts.capture ? "(" : "") + token.open;
17059
+ const output2 = (opts.capture ? "(" : "") + token.open;
16980
17060
  increment("parens");
16981
17061
  push({ type, value: value2, output: state.output ? "" : ONE_CHAR });
16982
- push({ type: "paren", extglob: true, value: advance(), output });
17062
+ push({ type: "paren", extglob: true, value: advance(), output: output2 });
16983
17063
  extglobs.push(token);
16984
17064
  };
16985
17065
  const extglobClose = (token) => {
16986
- let output = token.close + (opts.capture ? ")" : "");
17066
+ let output2 = token.close + (opts.capture ? ")" : "");
16987
17067
  let rest;
16988
17068
  if (token.type === "negate") {
16989
17069
  let extglobStar = star;
@@ -16991,22 +17071,22 @@ var require_parse2 = __commonJS((exports, module) => {
16991
17071
  extglobStar = globstar(opts);
16992
17072
  }
16993
17073
  if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
16994
- output = token.close = `)$))${extglobStar}`;
17074
+ output2 = token.close = `)$))${extglobStar}`;
16995
17075
  }
16996
17076
  if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
16997
17077
  const expression = parse2(rest, { ...options2, fastpaths: false }).output;
16998
- output = token.close = `)${expression})${extglobStar})`;
17078
+ output2 = token.close = `)${expression})${extglobStar})`;
16999
17079
  }
17000
17080
  if (token.prev.type === "bos") {
17001
17081
  state.negatedExtglob = true;
17002
17082
  }
17003
17083
  }
17004
- push({ type: "paren", extglob: true, value, output });
17084
+ push({ type: "paren", extglob: true, value, output: output2 });
17005
17085
  decrement("parens");
17006
17086
  };
17007
17087
  if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input5)) {
17008
17088
  let backslashes = false;
17009
- let output = input5.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
17089
+ let output2 = input5.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
17010
17090
  if (first === "\\") {
17011
17091
  backslashes = true;
17012
17092
  return m;
@@ -17033,18 +17113,18 @@ var require_parse2 = __commonJS((exports, module) => {
17033
17113
  });
17034
17114
  if (backslashes === true) {
17035
17115
  if (opts.unescape === true) {
17036
- output = output.replace(/\\/g, "");
17116
+ output2 = output2.replace(/\\/g, "");
17037
17117
  } else {
17038
- output = output.replace(/\\+/g, (m) => {
17118
+ output2 = output2.replace(/\\+/g, (m) => {
17039
17119
  return m.length % 2 === 0 ? "\\\\" : m ? "\\" : "";
17040
17120
  });
17041
17121
  }
17042
17122
  }
17043
- if (output === input5 && opts.contains === true) {
17123
+ if (output2 === input5 && opts.contains === true) {
17044
17124
  state.output = input5;
17045
17125
  return state;
17046
17126
  }
17047
- state.output = utils.wrapOutput(output, state, options2);
17127
+ state.output = utils.wrapOutput(output2, state, options2);
17048
17128
  return state;
17049
17129
  }
17050
17130
  while (!eos()) {
@@ -17214,7 +17294,7 @@ var require_parse2 = __commonJS((exports, module) => {
17214
17294
  push({ type: "text", value, output: value });
17215
17295
  continue;
17216
17296
  }
17217
- let output = ")";
17297
+ let output2 = ")";
17218
17298
  if (brace.dots === true) {
17219
17299
  const arr = tokens.slice();
17220
17300
  const range = [];
@@ -17227,20 +17307,20 @@ var require_parse2 = __commonJS((exports, module) => {
17227
17307
  range.unshift(arr[i].value);
17228
17308
  }
17229
17309
  }
17230
- output = expandRange(range, opts);
17310
+ output2 = expandRange(range, opts);
17231
17311
  state.backtrack = true;
17232
17312
  }
17233
17313
  if (brace.comma !== true && brace.dots !== true) {
17234
17314
  const out = state.output.slice(0, brace.outputIndex);
17235
17315
  const toks = state.tokens.slice(brace.tokensIndex);
17236
17316
  brace.value = brace.output = "\\{";
17237
- value = output = "\\}";
17317
+ value = output2 = "\\}";
17238
17318
  state.output = out;
17239
17319
  for (const t of toks) {
17240
17320
  state.output += t.output || t.value;
17241
17321
  }
17242
17322
  }
17243
- push({ type: "brace", value, output });
17323
+ push({ type: "brace", value, output: output2 });
17244
17324
  decrement("braces");
17245
17325
  braces.pop();
17246
17326
  continue;
@@ -17253,13 +17333,13 @@ var require_parse2 = __commonJS((exports, module) => {
17253
17333
  continue;
17254
17334
  }
17255
17335
  if (value === ",") {
17256
- let output = value;
17336
+ let output2 = value;
17257
17337
  const brace = braces[braces.length - 1];
17258
17338
  if (brace && stack[stack.length - 1] === "braces") {
17259
17339
  brace.comma = true;
17260
- output = "|";
17340
+ output2 = "|";
17261
17341
  }
17262
- push({ type: "comma", value, output });
17342
+ push({ type: "comma", value, output: output2 });
17263
17343
  continue;
17264
17344
  }
17265
17345
  if (value === "/") {
@@ -17300,14 +17380,14 @@ var require_parse2 = __commonJS((exports, module) => {
17300
17380
  }
17301
17381
  if (prev && prev.type === "paren") {
17302
17382
  const next = peek();
17303
- let output = value;
17383
+ let output2 = value;
17304
17384
  if (next === "<" && !utils.supportsLookbehinds()) {
17305
17385
  throw new Error("Node.js v10 or higher is required for regex lookbehinds");
17306
17386
  }
17307
17387
  if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) {
17308
- output = `\\${value}`;
17388
+ output2 = `\\${value}`;
17309
17389
  }
17310
- push({ type: "text", value, output });
17390
+ push({ type: "text", value, output: output2 });
17311
17391
  continue;
17312
17392
  }
17313
17393
  if (opts.dot !== true && (prev.type === "slash" || prev.type === "bos")) {
@@ -17585,8 +17665,8 @@ var require_parse2 = __commonJS((exports, module) => {
17585
17665
  }
17586
17666
  }
17587
17667
  };
17588
- const output = utils.removePrefix(input5, state);
17589
- let source = create2(output);
17668
+ const output2 = utils.removePrefix(input5, state);
17669
+ let source = create2(output2);
17590
17670
  if (source && opts.strictSlashes !== true) {
17591
17671
  source += `${SLASH_LITERAL}?`;
17592
17672
  }
@@ -17597,7 +17677,7 @@ var require_parse2 = __commonJS((exports, module) => {
17597
17677
 
17598
17678
  // ../../node_modules/picomatch/lib/picomatch.js
17599
17679
  var require_picomatch = __commonJS((exports, module) => {
17600
- var path2 = __require("path");
17680
+ var path3 = __require("path");
17601
17681
  var scan = require_scan();
17602
17682
  var parse2 = require_parse2();
17603
17683
  var utils = require_utils2();
@@ -17631,8 +17711,8 @@ var require_picomatch = __commonJS((exports, module) => {
17631
17711
  isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
17632
17712
  }
17633
17713
  const matcher = (input5, returnObject = false) => {
17634
- const { isMatch, match, output } = picomatch.test(input5, regex, options2, { glob, posix });
17635
- const result = { glob, state, regex, posix, input: input5, output, match, isMatch };
17714
+ const { isMatch, match, output: output2 } = picomatch.test(input5, regex, options2, { glob, posix });
17715
+ const result = { glob, state, regex, posix, input: input5, output: output2, match, isMatch };
17636
17716
  if (typeof opts.onResult === "function") {
17637
17717
  opts.onResult(result);
17638
17718
  }
@@ -17667,23 +17747,23 @@ var require_picomatch = __commonJS((exports, module) => {
17667
17747
  const opts = options2 || {};
17668
17748
  const format = opts.format || (posix ? utils.toPosixSlashes : null);
17669
17749
  let match = input5 === glob;
17670
- let output = match && format ? format(input5) : input5;
17750
+ let output2 = match && format ? format(input5) : input5;
17671
17751
  if (match === false) {
17672
- output = format ? format(input5) : input5;
17673
- match = output === glob;
17752
+ output2 = format ? format(input5) : input5;
17753
+ match = output2 === glob;
17674
17754
  }
17675
17755
  if (match === false || opts.capture === true) {
17676
17756
  if (opts.matchBase === true || opts.basename === true) {
17677
17757
  match = picomatch.matchBase(input5, regex, options2, posix);
17678
17758
  } else {
17679
- match = regex.exec(output);
17759
+ match = regex.exec(output2);
17680
17760
  }
17681
17761
  }
17682
- return { isMatch: Boolean(match), match, output };
17762
+ return { isMatch: Boolean(match), match, output: output2 };
17683
17763
  };
17684
17764
  picomatch.matchBase = (input5, glob, options2, posix = utils.isWindows(options2)) => {
17685
17765
  const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options2);
17686
- return regex.test(path2.basename(input5));
17766
+ return regex.test(path3.basename(input5));
17687
17767
  };
17688
17768
  picomatch.isMatch = (str, patterns, options2) => picomatch(patterns, options2)(str);
17689
17769
  picomatch.parse = (pattern, options2) => {
@@ -17904,7 +17984,7 @@ var require_micromatch = __commonJS((exports, module) => {
17904
17984
  var require_pattern = __commonJS((exports) => {
17905
17985
  Object.defineProperty(exports, "__esModule", { value: true });
17906
17986
  exports.isAbsolute = exports.partitionAbsoluteAndRelative = exports.removeDuplicateSlashes = exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.isPatternRelatedToParentDirectory = exports.getPatternsOutsideCurrentDirectory = exports.getPatternsInsideCurrentDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = undefined;
17907
- var path2 = __require("path");
17987
+ var path3 = __require("path");
17908
17988
  var globParent = require_glob_parent();
17909
17989
  var micromatch = require_micromatch();
17910
17990
  var GLOBSTAR = "**";
@@ -17999,7 +18079,7 @@ var require_pattern = __commonJS((exports) => {
17999
18079
  }
18000
18080
  exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
18001
18081
  function isAffectDepthOfReadingPattern(pattern) {
18002
- const basename = path2.basename(pattern);
18082
+ const basename = path3.basename(pattern);
18003
18083
  return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
18004
18084
  }
18005
18085
  exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
@@ -18057,7 +18137,7 @@ var require_pattern = __commonJS((exports) => {
18057
18137
  }
18058
18138
  exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
18059
18139
  function isAbsolute(pattern) {
18060
- return path2.isAbsolute(pattern);
18140
+ return path3.isAbsolute(pattern);
18061
18141
  }
18062
18142
  exports.isAbsolute = isAbsolute;
18063
18143
  });
@@ -18220,10 +18300,10 @@ var require_utils3 = __commonJS((exports) => {
18220
18300
  exports.array = array;
18221
18301
  var errno = require_errno();
18222
18302
  exports.errno = errno;
18223
- var fs4 = require_fs();
18224
- exports.fs = fs4;
18225
- var path2 = require_path();
18226
- exports.path = path2;
18303
+ var fs5 = require_fs();
18304
+ exports.fs = fs5;
18305
+ var path3 = require_path();
18306
+ exports.path = path3;
18227
18307
  var pattern = require_pattern();
18228
18308
  exports.pattern = pattern;
18229
18309
  var stream2 = require_stream();
@@ -18319,8 +18399,8 @@ var require_tasks = __commonJS((exports) => {
18319
18399
  var require_async = __commonJS((exports) => {
18320
18400
  Object.defineProperty(exports, "__esModule", { value: true });
18321
18401
  exports.read = undefined;
18322
- function read(path2, settings, callback) {
18323
- settings.fs.lstat(path2, (lstatError, lstat) => {
18402
+ function read(path3, settings, callback) {
18403
+ settings.fs.lstat(path3, (lstatError, lstat) => {
18324
18404
  if (lstatError !== null) {
18325
18405
  callFailureCallback(callback, lstatError);
18326
18406
  return;
@@ -18329,7 +18409,7 @@ var require_async = __commonJS((exports) => {
18329
18409
  callSuccessCallback(callback, lstat);
18330
18410
  return;
18331
18411
  }
18332
- settings.fs.stat(path2, (statError, stat2) => {
18412
+ settings.fs.stat(path3, (statError, stat2) => {
18333
18413
  if (statError !== null) {
18334
18414
  if (settings.throwErrorOnBrokenSymbolicLink) {
18335
18415
  callFailureCallback(callback, statError);
@@ -18358,13 +18438,13 @@ var require_async = __commonJS((exports) => {
18358
18438
  var require_sync = __commonJS((exports) => {
18359
18439
  Object.defineProperty(exports, "__esModule", { value: true });
18360
18440
  exports.read = undefined;
18361
- function read(path2, settings) {
18362
- const lstat = settings.fs.lstatSync(path2);
18441
+ function read(path3, settings) {
18442
+ const lstat = settings.fs.lstatSync(path3);
18363
18443
  if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
18364
18444
  return lstat;
18365
18445
  }
18366
18446
  try {
18367
- const stat2 = settings.fs.statSync(path2);
18447
+ const stat2 = settings.fs.statSync(path3);
18368
18448
  if (settings.markSymbolicLink) {
18369
18449
  stat2.isSymbolicLink = () => true;
18370
18450
  }
@@ -18383,12 +18463,12 @@ var require_sync = __commonJS((exports) => {
18383
18463
  var require_fs2 = __commonJS((exports) => {
18384
18464
  Object.defineProperty(exports, "__esModule", { value: true });
18385
18465
  exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = undefined;
18386
- var fs4 = __require("fs");
18466
+ var fs5 = __require("fs");
18387
18467
  exports.FILE_SYSTEM_ADAPTER = {
18388
- lstat: fs4.lstat,
18389
- stat: fs4.stat,
18390
- lstatSync: fs4.lstatSync,
18391
- statSync: fs4.statSync
18468
+ lstat: fs5.lstat,
18469
+ stat: fs5.stat,
18470
+ lstatSync: fs5.lstatSync,
18471
+ statSync: fs5.statSync
18392
18472
  };
18393
18473
  function createFileSystemAdapter(fsMethods) {
18394
18474
  if (fsMethods === undefined) {
@@ -18402,13 +18482,13 @@ var require_fs2 = __commonJS((exports) => {
18402
18482
  // ../../node_modules/@nodelib/fs.stat/out/settings.js
18403
18483
  var require_settings = __commonJS((exports) => {
18404
18484
  Object.defineProperty(exports, "__esModule", { value: true });
18405
- var fs4 = require_fs2();
18485
+ var fs5 = require_fs2();
18406
18486
 
18407
18487
  class Settings {
18408
18488
  constructor(_options = {}) {
18409
18489
  this._options = _options;
18410
18490
  this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
18411
- this.fs = fs4.createFileSystemAdapter(this._options.fs);
18491
+ this.fs = fs5.createFileSystemAdapter(this._options.fs);
18412
18492
  this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
18413
18493
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
18414
18494
  }
@@ -18427,17 +18507,17 @@ var require_out = __commonJS((exports) => {
18427
18507
  var sync = require_sync();
18428
18508
  var settings_1 = require_settings();
18429
18509
  exports.Settings = settings_1.default;
18430
- function stat2(path2, optionsOrSettingsOrCallback, callback) {
18510
+ function stat2(path3, optionsOrSettingsOrCallback, callback) {
18431
18511
  if (typeof optionsOrSettingsOrCallback === "function") {
18432
- async.read(path2, getSettings(), optionsOrSettingsOrCallback);
18512
+ async.read(path3, getSettings(), optionsOrSettingsOrCallback);
18433
18513
  return;
18434
18514
  }
18435
- async.read(path2, getSettings(optionsOrSettingsOrCallback), callback);
18515
+ async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
18436
18516
  }
18437
18517
  exports.stat = stat2;
18438
- function statSync2(path2, optionsOrSettings) {
18518
+ function statSync2(path3, optionsOrSettings) {
18439
18519
  const settings = getSettings(optionsOrSettings);
18440
- return sync.read(path2, settings);
18520
+ return sync.read(path3, settings);
18441
18521
  }
18442
18522
  exports.statSync = statSync2;
18443
18523
  function getSettings(settingsOrOptions = {}) {
@@ -18553,8 +18633,8 @@ var require_fs3 = __commonJS((exports) => {
18553
18633
  var require_utils4 = __commonJS((exports) => {
18554
18634
  Object.defineProperty(exports, "__esModule", { value: true });
18555
18635
  exports.fs = undefined;
18556
- var fs4 = require_fs3();
18557
- exports.fs = fs4;
18636
+ var fs5 = require_fs3();
18637
+ exports.fs = fs5;
18558
18638
  });
18559
18639
 
18560
18640
  // ../../node_modules/@nodelib/fs.scandir/out/providers/common.js
@@ -18640,16 +18720,16 @@ var require_async2 = __commonJS((exports) => {
18640
18720
  return;
18641
18721
  }
18642
18722
  const tasks = names.map((name) => {
18643
- const path2 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
18723
+ const path3 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
18644
18724
  return (done) => {
18645
- fsStat.stat(path2, settings.fsStatSettings, (error2, stats) => {
18725
+ fsStat.stat(path3, settings.fsStatSettings, (error2, stats) => {
18646
18726
  if (error2 !== null) {
18647
18727
  done(error2);
18648
18728
  return;
18649
18729
  }
18650
18730
  const entry = {
18651
18731
  name,
18652
- path: path2,
18732
+ path: path3,
18653
18733
  dirent: utils.fs.createDirentFromStats(name, stats)
18654
18734
  };
18655
18735
  if (settings.stats) {
@@ -18737,14 +18817,14 @@ var require_sync2 = __commonJS((exports) => {
18737
18817
  var require_fs4 = __commonJS((exports) => {
18738
18818
  Object.defineProperty(exports, "__esModule", { value: true });
18739
18819
  exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = undefined;
18740
- var fs4 = __require("fs");
18820
+ var fs5 = __require("fs");
18741
18821
  exports.FILE_SYSTEM_ADAPTER = {
18742
- lstat: fs4.lstat,
18743
- stat: fs4.stat,
18744
- lstatSync: fs4.lstatSync,
18745
- statSync: fs4.statSync,
18746
- readdir: fs4.readdir,
18747
- readdirSync: fs4.readdirSync
18822
+ lstat: fs5.lstat,
18823
+ stat: fs5.stat,
18824
+ lstatSync: fs5.lstatSync,
18825
+ statSync: fs5.statSync,
18826
+ readdir: fs5.readdir,
18827
+ readdirSync: fs5.readdirSync
18748
18828
  };
18749
18829
  function createFileSystemAdapter(fsMethods) {
18750
18830
  if (fsMethods === undefined) {
@@ -18758,16 +18838,16 @@ var require_fs4 = __commonJS((exports) => {
18758
18838
  // ../../node_modules/@nodelib/fs.scandir/out/settings.js
18759
18839
  var require_settings2 = __commonJS((exports) => {
18760
18840
  Object.defineProperty(exports, "__esModule", { value: true });
18761
- var path2 = __require("path");
18841
+ var path3 = __require("path");
18762
18842
  var fsStat = require_out();
18763
- var fs4 = require_fs4();
18843
+ var fs5 = require_fs4();
18764
18844
 
18765
18845
  class Settings {
18766
18846
  constructor(_options = {}) {
18767
18847
  this._options = _options;
18768
18848
  this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
18769
- this.fs = fs4.createFileSystemAdapter(this._options.fs);
18770
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path2.sep);
18849
+ this.fs = fs5.createFileSystemAdapter(this._options.fs);
18850
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path3.sep);
18771
18851
  this.stats = this._getValue(this._options.stats, false);
18772
18852
  this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
18773
18853
  this.fsStatSettings = new fsStat.Settings({
@@ -18791,17 +18871,17 @@ var require_out2 = __commonJS((exports) => {
18791
18871
  var sync = require_sync2();
18792
18872
  var settings_1 = require_settings2();
18793
18873
  exports.Settings = settings_1.default;
18794
- function scandir(path2, optionsOrSettingsOrCallback, callback) {
18874
+ function scandir(path3, optionsOrSettingsOrCallback, callback) {
18795
18875
  if (typeof optionsOrSettingsOrCallback === "function") {
18796
- async.read(path2, getSettings(), optionsOrSettingsOrCallback);
18876
+ async.read(path3, getSettings(), optionsOrSettingsOrCallback);
18797
18877
  return;
18798
18878
  }
18799
- async.read(path2, getSettings(optionsOrSettingsOrCallback), callback);
18879
+ async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
18800
18880
  }
18801
18881
  exports.scandir = scandir;
18802
- function scandirSync(path2, optionsOrSettings) {
18882
+ function scandirSync(path3, optionsOrSettings) {
18803
18883
  const settings = getSettings(optionsOrSettings);
18804
- return sync.read(path2, settings);
18884
+ return sync.read(path3, settings);
18805
18885
  }
18806
18886
  exports.scandirSync = scandirSync;
18807
18887
  function getSettings(settingsOrOptions = {}) {
@@ -19402,7 +19482,7 @@ var require_sync4 = __commonJS((exports) => {
19402
19482
  // ../../node_modules/@nodelib/fs.walk/out/settings.js
19403
19483
  var require_settings3 = __commonJS((exports) => {
19404
19484
  Object.defineProperty(exports, "__esModule", { value: true });
19405
- var path2 = __require("path");
19485
+ var path3 = __require("path");
19406
19486
  var fsScandir = require_out2();
19407
19487
 
19408
19488
  class Settings {
@@ -19413,7 +19493,7 @@ var require_settings3 = __commonJS((exports) => {
19413
19493
  this.deepFilter = this._getValue(this._options.deepFilter, null);
19414
19494
  this.entryFilter = this._getValue(this._options.entryFilter, null);
19415
19495
  this.errorFilter = this._getValue(this._options.errorFilter, null);
19416
- this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path2.sep);
19496
+ this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path3.sep);
19417
19497
  this.fsScandirSettings = new fsScandir.Settings({
19418
19498
  followSymbolicLinks: this._options.followSymbolicLinks,
19419
19499
  fs: this._options.fs,
@@ -19469,7 +19549,7 @@ var require_out3 = __commonJS((exports) => {
19469
19549
  // ../../node_modules/fast-glob/out/readers/reader.js
19470
19550
  var require_reader2 = __commonJS((exports) => {
19471
19551
  Object.defineProperty(exports, "__esModule", { value: true });
19472
- var path2 = __require("path");
19552
+ var path3 = __require("path");
19473
19553
  var fsStat = require_out();
19474
19554
  var utils = require_utils3();
19475
19555
 
@@ -19483,7 +19563,7 @@ var require_reader2 = __commonJS((exports) => {
19483
19563
  });
19484
19564
  }
19485
19565
  _getFullEntryPath(filepath) {
19486
- return path2.resolve(this._settings.cwd, filepath);
19566
+ return path3.resolve(this._settings.cwd, filepath);
19487
19567
  }
19488
19568
  _makeEntry(stats, pattern) {
19489
19569
  const entry = {
@@ -19880,7 +19960,7 @@ var require_entry2 = __commonJS((exports) => {
19880
19960
  // ../../node_modules/fast-glob/out/providers/provider.js
19881
19961
  var require_provider = __commonJS((exports) => {
19882
19962
  Object.defineProperty(exports, "__esModule", { value: true });
19883
- var path2 = __require("path");
19963
+ var path3 = __require("path");
19884
19964
  var deep_1 = require_deep();
19885
19965
  var entry_1 = require_entry();
19886
19966
  var error_1 = require_error2();
@@ -19895,7 +19975,7 @@ var require_provider = __commonJS((exports) => {
19895
19975
  this.entryTransformer = new entry_2.default(this._settings);
19896
19976
  }
19897
19977
  _getRootDirectory(task) {
19898
- return path2.resolve(this._settings.cwd, task.base);
19978
+ return path3.resolve(this._settings.cwd, task.base);
19899
19979
  }
19900
19980
  _getReaderOptions(task) {
19901
19981
  const basePath = task.base === "." ? "" : task.base;
@@ -20064,16 +20144,16 @@ var require_sync6 = __commonJS((exports) => {
20064
20144
  var require_settings4 = __commonJS((exports) => {
20065
20145
  Object.defineProperty(exports, "__esModule", { value: true });
20066
20146
  exports.DEFAULT_FILE_SYSTEM_ADAPTER = undefined;
20067
- var fs4 = __require("fs");
20147
+ var fs5 = __require("fs");
20068
20148
  var os4 = __require("os");
20069
20149
  var CPU_COUNT = Math.max(os4.cpus().length, 1);
20070
20150
  exports.DEFAULT_FILE_SYSTEM_ADAPTER = {
20071
- lstat: fs4.lstat,
20072
- lstatSync: fs4.lstatSync,
20073
- stat: fs4.stat,
20074
- statSync: fs4.statSync,
20075
- readdir: fs4.readdir,
20076
- readdirSync: fs4.readdirSync
20151
+ lstat: fs5.lstat,
20152
+ lstatSync: fs5.lstatSync,
20153
+ stat: fs5.stat,
20154
+ statSync: fs5.statSync,
20155
+ readdir: fs5.readdir,
20156
+ readdirSync: fs5.readdirSync
20077
20157
  };
20078
20158
 
20079
20159
  class Settings {
@@ -20776,16 +20856,16 @@ var init_contract = __esm(() => {
20776
20856
 
20777
20857
  // src/utils/config.ts
20778
20858
  import { randomBytes } from "node:crypto";
20779
- import { promises as fs4 } from "node:fs";
20859
+ import { promises as fs5 } from "node:fs";
20780
20860
  import { createRequire as createRequire2 } from "node:module";
20781
20861
  import { tmpdir } from "node:os";
20782
- import path2 from "node:path";
20862
+ import path3 from "node:path";
20783
20863
  import { pathToFileURL } from "node:url";
20784
20864
  async function findConfigFile(cwd) {
20785
20865
  for (const fileName of CONFIG_FILE_NAMES) {
20786
- const filePath = path2.join(cwd, fileName);
20866
+ const filePath = path3.join(cwd, fileName);
20787
20867
  try {
20788
- await fs4.access(filePath);
20868
+ await fs5.access(filePath);
20789
20869
  return filePath;
20790
20870
  } catch {}
20791
20871
  }
@@ -20793,21 +20873,21 @@ async function findConfigFile(cwd) {
20793
20873
  }
20794
20874
  async function loadConfig2(configPath) {
20795
20875
  const cwd = process.cwd();
20796
- const resolvedPath = configPath ? path2.resolve(cwd, configPath) : await findConfigFile(cwd);
20876
+ const resolvedPath = configPath ? path3.resolve(cwd, configPath) : await findConfigFile(cwd);
20797
20877
  if (!resolvedPath) {
20798
20878
  throw new Error("No config file found. Create a secondlayer.config.ts file or specify a path with --config");
20799
20879
  }
20800
20880
  let config;
20801
20881
  if (resolvedPath.endsWith(".ts")) {
20802
- const code = await fs4.readFile(resolvedPath, "utf-8");
20882
+ const code = await fs5.readFile(resolvedPath, "utf-8");
20803
20883
  let replacementPath;
20804
20884
  try {
20805
20885
  const require2 = createRequire2(import.meta.url);
20806
20886
  const packagePath = require2.resolve("@secondlayer/cli");
20807
20887
  replacementPath = pathToFileURL(packagePath).href;
20808
20888
  } catch {
20809
- const currentModuleDir = path2.dirname(new URL(import.meta.url).pathname);
20810
- const indexPath = path2.resolve(currentModuleDir, "../index");
20889
+ const currentModuleDir = path3.dirname(new URL(import.meta.url).pathname);
20890
+ const indexPath = path3.resolve(currentModuleDir, "../index");
20811
20891
  replacementPath = pathToFileURL(indexPath).href;
20812
20892
  }
20813
20893
  const transformedCode = code.replace(/from\s+["']@secondlayer\/cli["']/g, `from '${replacementPath}'`);
@@ -20817,14 +20897,14 @@ async function loadConfig2(configPath) {
20817
20897
  target: "node18",
20818
20898
  loader: "ts"
20819
20899
  });
20820
- const tempPath = path2.join(tmpdir(), `secondlayer-config-${randomBytes(4).toString("hex")}.mjs`);
20821
- await fs4.writeFile(tempPath, result.code);
20900
+ const tempPath = path3.join(tmpdir(), `secondlayer-config-${randomBytes(4).toString("hex")}.mjs`);
20901
+ await fs5.writeFile(tempPath, result.code);
20822
20902
  try {
20823
20903
  const fileUrl = pathToFileURL(tempPath).href;
20824
20904
  const module = await import(fileUrl);
20825
20905
  config = module.default;
20826
20906
  } finally {
20827
- await fs4.unlink(tempPath).catch(() => {});
20907
+ await fs5.unlink(tempPath).catch(() => {});
20828
20908
  }
20829
20909
  } else {
20830
20910
  const fileUrl = pathToFileURL(resolvedPath).href;
@@ -21794,11 +21874,11 @@ var init_commands = __esm(() => {
21794
21874
  });
21795
21875
 
21796
21876
  // ../../node_modules/@antfu/ni/dist/shared/ni.B5qNAuoI.mjs
21797
- import path3, { join as join11, dirname as dirname12, resolve as resolve9 } from "node:path";
21877
+ import path4, { join as join11, dirname as dirname12, resolve as resolve9 } from "node:path";
21798
21878
  import process$1 from "node:process";
21799
21879
  import require$$0 from "readline";
21800
21880
  import require$$2 from "events";
21801
- import fs5, { promises, existsSync as existsSync6 } from "node:fs";
21881
+ import fs6, { promises, existsSync as existsSync6 } from "node:fs";
21802
21882
  import require$$0$1 from "os";
21803
21883
  import require$$1 from "tty";
21804
21884
  import os4 from "node:os";
@@ -22030,32 +22110,32 @@ function requireKleur() {
22030
22110
  }
22031
22111
  const $ = {
22032
22112
  enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY),
22033
- reset: init2(0, 0),
22034
- bold: init2(1, 22),
22035
- dim: init2(2, 22),
22036
- italic: init2(3, 23),
22037
- underline: init2(4, 24),
22038
- inverse: init2(7, 27),
22039
- hidden: init2(8, 28),
22040
- strikethrough: init2(9, 29),
22041
- black: init2(30, 39),
22042
- red: init2(31, 39),
22043
- green: init2(32, 39),
22044
- yellow: init2(33, 39),
22045
- blue: init2(34, 39),
22046
- magenta: init2(35, 39),
22047
- cyan: init2(36, 39),
22048
- white: init2(37, 39),
22049
- gray: init2(90, 39),
22050
- grey: init2(90, 39),
22051
- bgBlack: init2(40, 49),
22052
- bgRed: init2(41, 49),
22053
- bgGreen: init2(42, 49),
22054
- bgYellow: init2(43, 49),
22055
- bgBlue: init2(44, 49),
22056
- bgMagenta: init2(45, 49),
22057
- bgCyan: init2(46, 49),
22058
- bgWhite: init2(47, 49)
22113
+ reset: init3(0, 0),
22114
+ bold: init3(1, 22),
22115
+ dim: init3(2, 22),
22116
+ italic: init3(3, 23),
22117
+ underline: init3(4, 24),
22118
+ inverse: init3(7, 27),
22119
+ hidden: init3(8, 28),
22120
+ strikethrough: init3(9, 29),
22121
+ black: init3(30, 39),
22122
+ red: init3(31, 39),
22123
+ green: init3(32, 39),
22124
+ yellow: init3(33, 39),
22125
+ blue: init3(34, 39),
22126
+ magenta: init3(35, 39),
22127
+ cyan: init3(36, 39),
22128
+ white: init3(37, 39),
22129
+ gray: init3(90, 39),
22130
+ grey: init3(90, 39),
22131
+ bgBlack: init3(40, 49),
22132
+ bgRed: init3(41, 49),
22133
+ bgGreen: init3(42, 49),
22134
+ bgYellow: init3(43, 49),
22135
+ bgBlue: init3(44, 49),
22136
+ bgMagenta: init3(45, 49),
22137
+ bgCyan: init3(46, 49),
22138
+ bgWhite: init3(47, 49)
22059
22139
  };
22060
22140
  function run(arr, str) {
22061
22141
  let i2 = 0, tmp, beg = "", end = "";
@@ -22099,7 +22179,7 @@ function requireKleur() {
22099
22179
  ctx.bgWhite = $.bgWhite.bind(ctx);
22100
22180
  return ctx;
22101
22181
  }
22102
- function init2(open, close) {
22182
+ function init3(open, close) {
22103
22183
  let blk = {
22104
22184
  open: `\x1B[${open}m`,
22105
22185
  close: `\x1B[${close}m`,
@@ -23754,11 +23834,11 @@ Instructions:
23754
23834
  if (this.done) {
23755
23835
  return this.value.filter((e2) => e2.selected).map((v2) => v2.title).join(", ");
23756
23836
  }
23757
- const output = [color.gray(this.hint), this.renderInstructions()];
23837
+ const output2 = [color.gray(this.hint), this.renderInstructions()];
23758
23838
  if (this.value[this.cursor].disabled) {
23759
- output.push(color.yellow(this.warn));
23839
+ output2.push(color.yellow(this.warn));
23760
23840
  }
23761
- return output.join(" ");
23841
+ return output2.join(" ");
23762
23842
  }
23763
23843
  render() {
23764
23844
  if (this.closed)
@@ -24146,11 +24226,11 @@ Filtered results for: ${this.inputValue ? this.inputValue : color.gray("Enter so
24146
24226
  if (this.done) {
24147
24227
  return this.value.filter((e2) => e2.selected).map((v2) => v2.title).join(", ");
24148
24228
  }
24149
- const output = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()];
24229
+ const output2 = [color.gray(this.hint), this.renderInstructions(), this.renderCurrentInput()];
24150
24230
  if (this.filteredOptions.length && this.filteredOptions[this.cursor].disabled) {
24151
- output.push(color.yellow(this.warn));
24231
+ output2.push(color.yellow(this.warn));
24152
24232
  }
24153
- return output.join(" ");
24233
+ return output2.join(" ");
24154
24234
  }
24155
24235
  render() {
24156
24236
  if (this.closed)
@@ -24647,10 +24727,10 @@ function requirePosix() {
24647
24727
  posix.sync = posix.isexe = undefined;
24648
24728
  const fs_1 = require$$0$2;
24649
24729
  const promises_1 = require$$1$1;
24650
- const isexe = async (path4, options2 = {}) => {
24730
+ const isexe = async (path5, options2 = {}) => {
24651
24731
  const { ignoreErrors = false } = options2;
24652
24732
  try {
24653
- return checkStat(await (0, promises_1.stat)(path4), options2);
24733
+ return checkStat(await (0, promises_1.stat)(path5), options2);
24654
24734
  } catch (e2) {
24655
24735
  const er = e2;
24656
24736
  if (ignoreErrors || er.code === "EACCES")
@@ -24659,10 +24739,10 @@ function requirePosix() {
24659
24739
  }
24660
24740
  };
24661
24741
  posix.isexe = isexe;
24662
- const sync = (path4, options2 = {}) => {
24742
+ const sync = (path5, options2 = {}) => {
24663
24743
  const { ignoreErrors = false } = options2;
24664
24744
  try {
24665
- return checkStat((0, fs_1.statSync)(path4), options2);
24745
+ return checkStat((0, fs_1.statSync)(path5), options2);
24666
24746
  } catch (e2) {
24667
24747
  const er = e2;
24668
24748
  if (ignoreErrors || er.code === "EACCES")
@@ -24699,10 +24779,10 @@ function requireWin32() {
24699
24779
  win32.sync = win32.isexe = undefined;
24700
24780
  const fs_1 = require$$0$2;
24701
24781
  const promises_1 = require$$1$1;
24702
- const isexe = async (path4, options2 = {}) => {
24782
+ const isexe = async (path5, options2 = {}) => {
24703
24783
  const { ignoreErrors = false } = options2;
24704
24784
  try {
24705
- return checkStat(await (0, promises_1.stat)(path4), path4, options2);
24785
+ return checkStat(await (0, promises_1.stat)(path5), path5, options2);
24706
24786
  } catch (e2) {
24707
24787
  const er = e2;
24708
24788
  if (ignoreErrors || er.code === "EACCES")
@@ -24711,10 +24791,10 @@ function requireWin32() {
24711
24791
  }
24712
24792
  };
24713
24793
  win32.isexe = isexe;
24714
- const sync = (path4, options2 = {}) => {
24794
+ const sync = (path5, options2 = {}) => {
24715
24795
  const { ignoreErrors = false } = options2;
24716
24796
  try {
24717
- return checkStat((0, fs_1.statSync)(path4), path4, options2);
24797
+ return checkStat((0, fs_1.statSync)(path5), path5, options2);
24718
24798
  } catch (e2) {
24719
24799
  const er = e2;
24720
24800
  if (ignoreErrors || er.code === "EACCES")
@@ -24723,7 +24803,7 @@ function requireWin32() {
24723
24803
  }
24724
24804
  };
24725
24805
  win32.sync = sync;
24726
- const checkPathExt = (path4, options2) => {
24806
+ const checkPathExt = (path5, options2) => {
24727
24807
  const { pathExt = process.env.PATHEXT || "" } = options2;
24728
24808
  const peSplit = pathExt.split(";");
24729
24809
  if (peSplit.indexOf("") !== -1) {
@@ -24731,14 +24811,14 @@ function requireWin32() {
24731
24811
  }
24732
24812
  for (let i2 = 0;i2 < peSplit.length; i2++) {
24733
24813
  const p2 = peSplit[i2].toLowerCase();
24734
- const ext = path4.substring(path4.length - p2.length).toLowerCase();
24814
+ const ext = path5.substring(path5.length - p2.length).toLowerCase();
24735
24815
  if (p2 && ext === p2) {
24736
24816
  return true;
24737
24817
  }
24738
24818
  }
24739
24819
  return false;
24740
24820
  };
24741
- const checkStat = (stat2, path4, options2) => stat2.isFile() && checkPathExt(path4, options2);
24821
+ const checkStat = (stat2, path5, options2) => stat2.isFile() && checkPathExt(path5, options2);
24742
24822
  return win32;
24743
24823
  }
24744
24824
  function requireOptions() {
@@ -24988,7 +25068,7 @@ var init_ni_B5qNAuoI = __esm(() => {
24988
25068
  CLI_TEMP_DIR = join11(os4.tmpdir(), "antfu-ni");
24989
25069
  customRcPath = process$1.env.NI_CONFIG_FILE;
24990
25070
  home = process$1.platform === "win32" ? process$1.env.USERPROFILE : process$1.env.HOME;
24991
- defaultRcPath = path3.join(home || "~/", ".nirc");
25071
+ defaultRcPath = path4.join(home || "~/", ".nirc");
24992
25072
  });
24993
25073
 
24994
25074
  // ../../node_modules/@antfu/ni/dist/index.mjs
@@ -25858,8 +25938,8 @@ var init_command = __esm(() => {
25858
25938
  var require_windows = __commonJS((exports, module) => {
25859
25939
  module.exports = isexe;
25860
25940
  isexe.sync = sync;
25861
- var fs6 = __require("fs");
25862
- function checkPathExt(path4, options3) {
25941
+ var fs7 = __require("fs");
25942
+ function checkPathExt(path5, options3) {
25863
25943
  var pathext = options3.pathExt !== undefined ? options3.pathExt : process.env.PATHEXT;
25864
25944
  if (!pathext) {
25865
25945
  return true;
@@ -25870,25 +25950,25 @@ var require_windows = __commonJS((exports, module) => {
25870
25950
  }
25871
25951
  for (var i2 = 0;i2 < pathext.length; i2++) {
25872
25952
  var p2 = pathext[i2].toLowerCase();
25873
- if (p2 && path4.substr(-p2.length).toLowerCase() === p2) {
25953
+ if (p2 && path5.substr(-p2.length).toLowerCase() === p2) {
25874
25954
  return true;
25875
25955
  }
25876
25956
  }
25877
25957
  return false;
25878
25958
  }
25879
- function checkStat(stat2, path4, options3) {
25959
+ function checkStat(stat2, path5, options3) {
25880
25960
  if (!stat2.isSymbolicLink() && !stat2.isFile()) {
25881
25961
  return false;
25882
25962
  }
25883
- return checkPathExt(path4, options3);
25963
+ return checkPathExt(path5, options3);
25884
25964
  }
25885
- function isexe(path4, options3, cb) {
25886
- fs6.stat(path4, function(er, stat2) {
25887
- cb(er, er ? false : checkStat(stat2, path4, options3));
25965
+ function isexe(path5, options3, cb) {
25966
+ fs7.stat(path5, function(er, stat2) {
25967
+ cb(er, er ? false : checkStat(stat2, path5, options3));
25888
25968
  });
25889
25969
  }
25890
- function sync(path4, options3) {
25891
- return checkStat(fs6.statSync(path4), path4, options3);
25970
+ function sync(path5, options3) {
25971
+ return checkStat(fs7.statSync(path5), path5, options3);
25892
25972
  }
25893
25973
  });
25894
25974
 
@@ -25896,14 +25976,14 @@ var require_windows = __commonJS((exports, module) => {
25896
25976
  var require_mode = __commonJS((exports, module) => {
25897
25977
  module.exports = isexe;
25898
25978
  isexe.sync = sync;
25899
- var fs6 = __require("fs");
25900
- function isexe(path4, options3, cb) {
25901
- fs6.stat(path4, function(er, stat2) {
25979
+ var fs7 = __require("fs");
25980
+ function isexe(path5, options3, cb) {
25981
+ fs7.stat(path5, function(er, stat2) {
25902
25982
  cb(er, er ? false : checkStat(stat2, options3));
25903
25983
  });
25904
25984
  }
25905
- function sync(path4, options3) {
25906
- return checkStat(fs6.statSync(path4), options3);
25985
+ function sync(path5, options3) {
25986
+ return checkStat(fs7.statSync(path5), options3);
25907
25987
  }
25908
25988
  function checkStat(stat2, options3) {
25909
25989
  return stat2.isFile() && checkMode(stat2, options3);
@@ -25925,7 +26005,7 @@ var require_mode = __commonJS((exports, module) => {
25925
26005
 
25926
26006
  // ../../node_modules/isexe/index.js
25927
26007
  var require_isexe = __commonJS((exports, module) => {
25928
- var fs6 = __require("fs");
26008
+ var fs7 = __require("fs");
25929
26009
  var core2;
25930
26010
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
25931
26011
  core2 = require_windows();
@@ -25934,7 +26014,7 @@ var require_isexe = __commonJS((exports, module) => {
25934
26014
  }
25935
26015
  module.exports = isexe;
25936
26016
  isexe.sync = sync;
25937
- function isexe(path4, options3, cb) {
26017
+ function isexe(path5, options3, cb) {
25938
26018
  if (typeof options3 === "function") {
25939
26019
  cb = options3;
25940
26020
  options3 = {};
@@ -25944,7 +26024,7 @@ var require_isexe = __commonJS((exports, module) => {
25944
26024
  throw new TypeError("callback not provided");
25945
26025
  }
25946
26026
  return new Promise(function(resolve10, reject) {
25947
- isexe(path4, options3 || {}, function(er, is2) {
26027
+ isexe(path5, options3 || {}, function(er, is2) {
25948
26028
  if (er) {
25949
26029
  reject(er);
25950
26030
  } else {
@@ -25953,7 +26033,7 @@ var require_isexe = __commonJS((exports, module) => {
25953
26033
  });
25954
26034
  });
25955
26035
  }
25956
- core2(path4, options3 || {}, function(er, is2) {
26036
+ core2(path5, options3 || {}, function(er, is2) {
25957
26037
  if (er) {
25958
26038
  if (er.code === "EACCES" || options3 && options3.ignoreErrors) {
25959
26039
  er = null;
@@ -25963,9 +26043,9 @@ var require_isexe = __commonJS((exports, module) => {
25963
26043
  cb(er, is2);
25964
26044
  });
25965
26045
  }
25966
- function sync(path4, options3) {
26046
+ function sync(path5, options3) {
25967
26047
  try {
25968
- return core2.sync(path4, options3 || {});
26048
+ return core2.sync(path5, options3 || {});
25969
26049
  } catch (er) {
25970
26050
  if (options3 && options3.ignoreErrors || er.code === "EACCES") {
25971
26051
  return false;
@@ -25979,7 +26059,7 @@ var require_isexe = __commonJS((exports, module) => {
25979
26059
  // ../../node_modules/which/which.js
25980
26060
  var require_which = __commonJS((exports, module) => {
25981
26061
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
25982
- var path4 = __require("path");
26062
+ var path5 = __require("path");
25983
26063
  var COLON = isWindows ? ";" : ":";
25984
26064
  var isexe = require_isexe();
25985
26065
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -26015,7 +26095,7 @@ var require_which = __commonJS((exports, module) => {
26015
26095
  return opt.all && found.length ? resolve10(found) : reject(getNotFoundError(cmd));
26016
26096
  const ppRaw = pathEnv[i2];
26017
26097
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
26018
- const pCmd = path4.join(pathPart, cmd);
26098
+ const pCmd = path5.join(pathPart, cmd);
26019
26099
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
26020
26100
  resolve10(subStep(p2, i2, 0));
26021
26101
  });
@@ -26042,7 +26122,7 @@ var require_which = __commonJS((exports, module) => {
26042
26122
  for (let i2 = 0;i2 < pathEnv.length; i2++) {
26043
26123
  const ppRaw = pathEnv[i2];
26044
26124
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
26045
- const pCmd = path4.join(pathPart, cmd);
26125
+ const pCmd = path5.join(pathPart, cmd);
26046
26126
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
26047
26127
  for (let j2 = 0;j2 < pathExt.length; j2++) {
26048
26128
  const cur = p2 + pathExt[j2];
@@ -26083,7 +26163,7 @@ var require_path_key = __commonJS((exports, module) => {
26083
26163
 
26084
26164
  // ../../node_modules/cross-spawn/lib/util/resolveCommand.js
26085
26165
  var require_resolveCommand = __commonJS((exports, module) => {
26086
- var path4 = __require("path");
26166
+ var path5 = __require("path");
26087
26167
  var which2 = require_which();
26088
26168
  var getPathKey = require_path_key();
26089
26169
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -26100,7 +26180,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
26100
26180
  try {
26101
26181
  resolved = which2.sync(parsed.command, {
26102
26182
  path: env2[getPathKey({ env: env2 })],
26103
- pathExt: withoutPathExt ? path4.delimiter : undefined
26183
+ pathExt: withoutPathExt ? path5.delimiter : undefined
26104
26184
  });
26105
26185
  } catch (e2) {} finally {
26106
26186
  if (shouldSwitchCwd) {
@@ -26108,7 +26188,7 @@ var require_resolveCommand = __commonJS((exports, module) => {
26108
26188
  }
26109
26189
  }
26110
26190
  if (resolved) {
26111
- resolved = path4.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
26191
+ resolved = path5.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
26112
26192
  }
26113
26193
  return resolved;
26114
26194
  }
@@ -26153,8 +26233,8 @@ var require_shebang_command = __commonJS((exports, module) => {
26153
26233
  if (!match) {
26154
26234
  return null;
26155
26235
  }
26156
- const [path4, argument] = match[0].replace(/#! ?/, "").split(" ");
26157
- const binary = path4.split("/").pop();
26236
+ const [path5, argument] = match[0].replace(/#! ?/, "").split(" ");
26237
+ const binary = path5.split("/").pop();
26158
26238
  if (binary === "env") {
26159
26239
  return argument;
26160
26240
  }
@@ -26164,16 +26244,16 @@ var require_shebang_command = __commonJS((exports, module) => {
26164
26244
 
26165
26245
  // ../../node_modules/cross-spawn/lib/util/readShebang.js
26166
26246
  var require_readShebang = __commonJS((exports, module) => {
26167
- var fs6 = __require("fs");
26247
+ var fs7 = __require("fs");
26168
26248
  var shebangCommand = require_shebang_command();
26169
26249
  function readShebang(command) {
26170
26250
  const size2 = 150;
26171
26251
  const buffer2 = Buffer.alloc(size2);
26172
26252
  let fd;
26173
26253
  try {
26174
- fd = fs6.openSync(command, "r");
26175
- fs6.readSync(fd, buffer2, 0, size2, 0);
26176
- fs6.closeSync(fd);
26254
+ fd = fs7.openSync(command, "r");
26255
+ fs7.readSync(fd, buffer2, 0, size2, 0);
26256
+ fs7.closeSync(fd);
26177
26257
  } catch (e2) {}
26178
26258
  return shebangCommand(buffer2.toString());
26179
26259
  }
@@ -26182,7 +26262,7 @@ var require_readShebang = __commonJS((exports, module) => {
26182
26262
 
26183
26263
  // ../../node_modules/cross-spawn/lib/parse.js
26184
26264
  var require_parse3 = __commonJS((exports, module) => {
26185
- var path4 = __require("path");
26265
+ var path5 = __require("path");
26186
26266
  var resolveCommand2 = require_resolveCommand();
26187
26267
  var escape2 = require_escape();
26188
26268
  var readShebang = require_readShebang();
@@ -26207,7 +26287,7 @@ var require_parse3 = __commonJS((exports, module) => {
26207
26287
  const needsShell = !isExecutableRegExp.test(commandFile);
26208
26288
  if (parsed.options.forceShell || needsShell) {
26209
26289
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
26210
- parsed.command = path4.normalize(parsed.command);
26290
+ parsed.command = path5.normalize(parsed.command);
26211
26291
  parsed.command = escape2.command(parsed.command);
26212
26292
  parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
26213
26293
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -26324,7 +26404,7 @@ function pathKey(options3 = {}) {
26324
26404
  // ../../node_modules/unicorn-magic/node.js
26325
26405
  import { promisify as promisify4 } from "node:util";
26326
26406
  import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
26327
- import path4 from "node:path";
26407
+ import path5 from "node:path";
26328
26408
  import { fileURLToPath as fileURLToPath4 } from "node:url";
26329
26409
  function toPath(urlOrPath) {
26330
26410
  return urlOrPath instanceof URL ? fileURLToPath4(urlOrPath) : urlOrPath;
@@ -26332,12 +26412,12 @@ function toPath(urlOrPath) {
26332
26412
  function traversePathUp(startPath) {
26333
26413
  return {
26334
26414
  *[Symbol.iterator]() {
26335
- let currentPath = path4.resolve(toPath(startPath));
26415
+ let currentPath = path5.resolve(toPath(startPath));
26336
26416
  let previousPath;
26337
26417
  while (previousPath !== currentPath) {
26338
26418
  yield currentPath;
26339
26419
  previousPath = currentPath;
26340
- currentPath = path4.resolve(currentPath, "..");
26420
+ currentPath = path5.resolve(currentPath, "..");
26341
26421
  }
26342
26422
  }
26343
26423
  };
@@ -26350,7 +26430,7 @@ var init_node = __esm(() => {
26350
26430
 
26351
26431
  // ../../node_modules/npm-run-path/index.js
26352
26432
  import process7 from "node:process";
26353
- import path5 from "node:path";
26433
+ import path6 from "node:path";
26354
26434
  var npmRunPath = ({
26355
26435
  cwd = process7.cwd(),
26356
26436
  path: pathOption = process7.env[pathKey()],
@@ -26358,25 +26438,25 @@ var npmRunPath = ({
26358
26438
  execPath = process7.execPath,
26359
26439
  addExecPath = true
26360
26440
  } = {}) => {
26361
- const cwdPath = path5.resolve(toPath(cwd));
26441
+ const cwdPath = path6.resolve(toPath(cwd));
26362
26442
  const result = [];
26363
- const pathParts = pathOption.split(path5.delimiter);
26443
+ const pathParts = pathOption.split(path6.delimiter);
26364
26444
  if (preferLocal) {
26365
26445
  applyPreferLocal(result, pathParts, cwdPath);
26366
26446
  }
26367
26447
  if (addExecPath) {
26368
26448
  applyExecPath(result, pathParts, execPath, cwdPath);
26369
26449
  }
26370
- return pathOption === "" || pathOption === path5.delimiter ? `${result.join(path5.delimiter)}${pathOption}` : [...result, pathOption].join(path5.delimiter);
26450
+ return pathOption === "" || pathOption === path6.delimiter ? `${result.join(path6.delimiter)}${pathOption}` : [...result, pathOption].join(path6.delimiter);
26371
26451
  }, applyPreferLocal = (result, pathParts, cwdPath) => {
26372
26452
  for (const directory of traversePathUp(cwdPath)) {
26373
- const pathPart = path5.join(directory, "node_modules/.bin");
26453
+ const pathPart = path6.join(directory, "node_modules/.bin");
26374
26454
  if (!pathParts.includes(pathPart)) {
26375
26455
  result.push(pathPart);
26376
26456
  }
26377
26457
  }
26378
26458
  }, applyExecPath = (result, pathParts, execPath, cwdPath) => {
26379
- const pathPart = path5.resolve(cwdPath, toPath(execPath), "..");
26459
+ const pathPart = path6.resolve(cwdPath, toPath(execPath), "..");
26380
26460
  if (!pathParts.includes(pathPart)) {
26381
26461
  result.push(pathPart);
26382
26462
  }
@@ -27486,7 +27566,7 @@ var init_timeout = __esm(() => {
27486
27566
 
27487
27567
  // ../../node_modules/execa/lib/methods/node.js
27488
27568
  import { execPath, execArgv } from "node:process";
27489
- import path6 from "node:path";
27569
+ import path7 from "node:path";
27490
27570
  var mapNode = ({ options: options3 }) => {
27491
27571
  if (options3.node === false) {
27492
27572
  throw new TypeError('The "node" option cannot be false with `execaNode()`.');
@@ -27504,7 +27584,7 @@ var mapNode = ({ options: options3 }) => {
27504
27584
  throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.');
27505
27585
  }
27506
27586
  const normalizedNodePath = safeNormalizeFileUrl(nodePath, 'The "nodePath" option');
27507
- const resolvedNodePath = path6.resolve(cwd, normalizedNodePath);
27587
+ const resolvedNodePath = path7.resolve(cwd, normalizedNodePath);
27508
27588
  const newOptions = {
27509
27589
  ...options3,
27510
27590
  nodePath: resolvedNodePath,
@@ -27514,7 +27594,7 @@ var mapNode = ({ options: options3 }) => {
27514
27594
  if (!shouldHandleNode) {
27515
27595
  return [file, commandArguments, newOptions];
27516
27596
  }
27517
- if (path6.basename(file, ".exe") === "node") {
27597
+ if (path7.basename(file, ".exe") === "node") {
27518
27598
  throw new TypeError('When the "node" option is true, the first argument does not need to be "node".');
27519
27599
  }
27520
27600
  return [
@@ -27605,11 +27685,11 @@ var init_encoding_option = __esm(() => {
27605
27685
 
27606
27686
  // ../../node_modules/execa/lib/arguments/cwd.js
27607
27687
  import { statSync as statSync2 } from "node:fs";
27608
- import path7 from "node:path";
27688
+ import path8 from "node:path";
27609
27689
  import process8 from "node:process";
27610
27690
  var normalizeCwd = (cwd = getDefaultCwd()) => {
27611
27691
  const cwdString = safeNormalizeFileUrl(cwd, 'The "cwd" option');
27612
- return path7.resolve(cwdString);
27692
+ return path8.resolve(cwdString);
27613
27693
  }, getDefaultCwd = () => {
27614
27694
  try {
27615
27695
  return process8.cwd();
@@ -27641,7 +27721,7 @@ var init_cwd = __esm(() => {
27641
27721
  });
27642
27722
 
27643
27723
  // ../../node_modules/execa/lib/arguments/options.js
27644
- import path8 from "node:path";
27724
+ import path9 from "node:path";
27645
27725
  import process9 from "node:process";
27646
27726
  var import_cross_spawn, normalizeOptions = (filePath, rawArguments, rawOptions) => {
27647
27727
  rawOptions.cwd = normalizeCwd(rawOptions.cwd);
@@ -27659,7 +27739,7 @@ var import_cross_spawn, normalizeOptions = (filePath, rawArguments, rawOptions)
27659
27739
  options3.killSignal = normalizeKillSignal(options3.killSignal);
27660
27740
  options3.forceKillAfterDelay = normalizeForceKillAfterDelay(options3.forceKillAfterDelay);
27661
27741
  options3.lines = options3.lines.map((lines2, fdNumber) => lines2 && !BINARY_ENCODINGS.has(options3.encoding) && options3.buffer[fdNumber]);
27662
- if (process9.platform === "win32" && path8.basename(file, ".exe") === "cmd") {
27742
+ if (process9.platform === "win32" && path9.basename(file, ".exe") === "cmd") {
27663
27743
  commandArguments.unshift("/q");
27664
27744
  }
27665
27745
  return { file, commandArguments, options: options3 };
@@ -27907,7 +27987,7 @@ var handleMaxBuffer = ({ error: error2, stream: stream2, readableObjectMode, lin
27907
27987
  return { streamName: "IPC output", threshold, unit: "messages" };
27908
27988
  }
27909
27989
  return { streamName: getStreamName(fdNumber), threshold, unit };
27910
- }, isMaxBufferSync = (resultError, output, maxBuffer) => resultError?.code === "ENOBUFS" && output !== null && output.some((result) => result !== null && result.length > getMaxBufferSync(maxBuffer)), truncateMaxBufferSync = (result, isMaxBuffer, maxBuffer) => {
27990
+ }, isMaxBufferSync = (resultError, output2, maxBuffer) => resultError?.code === "ENOBUFS" && output2 !== null && output2.some((result) => result !== null && result.length > getMaxBufferSync(maxBuffer)), truncateMaxBufferSync = (result, isMaxBuffer, maxBuffer) => {
27911
27991
  if (!isMaxBuffer) {
27912
27992
  return result;
27913
27993
  }
@@ -29443,13 +29523,13 @@ var init_output2 = __esm(() => {
29443
29523
 
29444
29524
  // ../../node_modules/execa/lib/io/output-sync.js
29445
29525
  import { writeFileSync as writeFileSync5, appendFileSync } from "node:fs";
29446
- var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: options3, isMaxBuffer, verboseInfo }) => {
29447
- if (output === null) {
29526
+ var transformOutputSync = ({ fileDescriptors, syncResult: { output: output2 }, options: options3, isMaxBuffer, verboseInfo }) => {
29527
+ if (output2 === null) {
29448
29528
  return { output: Array.from({ length: 3 }) };
29449
29529
  }
29450
29530
  const state = {};
29451
29531
  const outputFiles = new Set([]);
29452
- const transformedOutput = output.map((result, fdNumber) => transformOutputResultSync({
29532
+ const transformedOutput = output2.map((result, fdNumber) => transformOutputResultSync({
29453
29533
  result,
29454
29534
  fileDescriptors,
29455
29535
  fdNumber,
@@ -29529,13 +29609,13 @@ var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options: o
29529
29609
  state.error ??= error2;
29530
29610
  }
29531
29611
  }, writeToFiles = (serializedResult, stdioItems, outputFiles) => {
29532
- for (const { path: path9, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) {
29533
- const pathString = typeof path9 === "string" ? path9 : path9.toString();
29612
+ for (const { path: path10, append } of stdioItems.filter(({ type }) => FILE_TYPES.has(type))) {
29613
+ const pathString = typeof path10 === "string" ? path10 : path10.toString();
29534
29614
  if (append || outputFiles.has(pathString)) {
29535
- appendFileSync(path9, serializedResult);
29615
+ appendFileSync(path10, serializedResult);
29536
29616
  } else {
29537
29617
  outputFiles.add(pathString);
29538
- writeFileSync5(path9, serializedResult);
29618
+ writeFileSync5(path10, serializedResult);
29539
29619
  }
29540
29620
  }
29541
29621
  };
@@ -29608,10 +29688,10 @@ var init_exit_async = __esm(() => {
29608
29688
  });
29609
29689
 
29610
29690
  // ../../node_modules/execa/lib/resolve/exit-sync.js
29611
- var getExitResultSync = ({ error: error2, status: exitCode, signal, output }, { maxBuffer }) => {
29691
+ var getExitResultSync = ({ error: error2, status: exitCode, signal, output: output2 }, { maxBuffer }) => {
29612
29692
  const resultError = getResultError(error2, exitCode, signal);
29613
29693
  const timedOut2 = resultError?.code === "ETIMEDOUT";
29614
- const isMaxBuffer = isMaxBufferSync(resultError, output, maxBuffer);
29694
+ const isMaxBuffer = isMaxBufferSync(resultError, output2, maxBuffer);
29615
29695
  return {
29616
29696
  resultError,
29617
29697
  exitCode,
@@ -29691,15 +29771,15 @@ var execaCoreSync = (rawFile, rawArguments, rawOptions) => {
29691
29771
  return syncResult;
29692
29772
  }
29693
29773
  const { resultError, exitCode, signal, timedOut: timedOut2, isMaxBuffer } = getExitResultSync(syncResult, options3);
29694
- const { output, error: error2 = resultError } = transformOutputSync({
29774
+ const { output: output2, error: error2 = resultError } = transformOutputSync({
29695
29775
  fileDescriptors,
29696
29776
  syncResult,
29697
29777
  options: options3,
29698
29778
  isMaxBuffer,
29699
29779
  verboseInfo
29700
29780
  });
29701
- const stdio = output.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options3, fdNumber));
29702
- const all2 = stripNewline(getAllSync(output, options3), options3, "all");
29781
+ const stdio = output2.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options3, fdNumber));
29782
+ const all2 = stripNewline(getAllSync(output2, options3), options3, "all");
29703
29783
  return getSyncResult({
29704
29784
  error: error2,
29705
29785
  exitCode,
@@ -30924,7 +31004,7 @@ var getStreamOutput = async ({ stream: stream2, onStreamEnd, fdNumber, encoding,
30924
31004
  stripFinalNewline: stripFinalNewlineValue,
30925
31005
  allMixed
30926
31006
  });
30927
- const [output] = await Promise.all([
31007
+ const [output2] = await Promise.all([
30928
31008
  getStreamContents({
30929
31009
  stream: stream2,
30930
31010
  iterable,
@@ -30935,7 +31015,7 @@ var getStreamOutput = async ({ stream: stream2, onStreamEnd, fdNumber, encoding,
30935
31015
  }),
30936
31016
  logPromise
30937
31017
  ]);
30938
- return output;
31018
+ return output2;
30939
31019
  }, logOutputAsync = async ({ stream: stream2, onStreamEnd, fdNumber, encoding, allMixed, verboseInfo, streamInfo: { fileDescriptors } }) => {
30940
31020
  if (!shouldLogOutput({
30941
31021
  stdioItems: fileDescriptors[fdNumber]?.stdioItems,
@@ -31061,7 +31141,7 @@ var waitForStdioStreams = ({ subprocess, encoding, buffer: buffer2, maxBuffer, l
31061
31141
  await onStreamEnd;
31062
31142
  return;
31063
31143
  }
31064
- const [output] = await Promise.all([
31144
+ const [output2] = await Promise.all([
31065
31145
  getStreamOutput({
31066
31146
  stream: stream2,
31067
31147
  onStreamEnd,
@@ -31077,7 +31157,7 @@ var waitForStdioStreams = ({ subprocess, encoding, buffer: buffer2, maxBuffer, l
31077
31157
  }),
31078
31158
  onStreamEnd
31079
31159
  ]);
31080
- return output;
31160
+ return output2;
31081
31161
  };
31082
31162
  var init_stdio = __esm(() => {
31083
31163
  init_contents();
@@ -31938,8 +32018,8 @@ var init_execa = __esm(() => {
31938
32018
  });
31939
32019
 
31940
32020
  // src/utils/dependencies.ts
31941
- import { promises as fs6 } from "node:fs";
31942
- import path9 from "node:path";
32021
+ import { promises as fs7 } from "node:fs";
32022
+ import path10 from "node:path";
31943
32023
  async function getPackageManager(targetDir) {
31944
32024
  const packageManager = await detect2({ programmatic: true, cwd: targetDir });
31945
32025
  if (packageManager === "yarn@berry")
@@ -31954,16 +32034,16 @@ async function getPackageManager(targetDir) {
31954
32034
  }
31955
32035
  async function hasPackageJson(targetDir) {
31956
32036
  try {
31957
- const packageJsonPath = path9.join(targetDir, "package.json");
31958
- await fs6.access(packageJsonPath);
32037
+ const packageJsonPath = path10.join(targetDir, "package.json");
32038
+ await fs7.access(packageJsonPath);
31959
32039
  return true;
31960
32040
  } catch {
31961
32041
  return false;
31962
32042
  }
31963
32043
  }
31964
32044
  async function readPackageJson(targetDir) {
31965
- const packageJsonPath = path9.join(targetDir, "package.json");
31966
- const content = await fs6.readFile(packageJsonPath, "utf-8");
32045
+ const packageJsonPath = path10.join(targetDir, "package.json");
32046
+ const content = await fs7.readFile(packageJsonPath, "utf-8");
31967
32047
  return JSON.parse(content);
31968
32048
  }
31969
32049
  async function getMissingDependenciesFor(targetDir, requiredDeps) {
@@ -32016,7 +32096,7 @@ __export(exports_generate, {
32016
32096
  resolveContract: () => resolveContract,
32017
32097
  generate: () => generate
32018
32098
  });
32019
- import path10 from "node:path";
32099
+ import path11 from "node:path";
32020
32100
  import { getErrorMessage as getErrorMessage2 } from "@secondlayer/shared";
32021
32101
  import { toCamelCase as toCamelCase8 } from "@secondlayer/stacks/clarity";
32022
32102
  function isContractAddress(input5) {
@@ -32041,7 +32121,7 @@ async function parseInputs(inputs) {
32041
32121
  continue;
32042
32122
  }
32043
32123
  if (input5.endsWith(".clar")) {
32044
- const absolutePath = path10.resolve(process.cwd(), input5);
32124
+ const absolutePath = path11.resolve(process.cwd(), input5);
32045
32125
  files.push(absolutePath);
32046
32126
  }
32047
32127
  }
@@ -32051,7 +32131,7 @@ async function parseInputs(inputs) {
32051
32131
  };
32052
32132
  }
32053
32133
  function deriveContractName(filePath) {
32054
- const basename = path10.basename(filePath, ".clar");
32134
+ const basename = path11.basename(filePath, ".clar");
32055
32135
  return basename.replace(/[-_](.)/g, (_2, char) => char.toUpperCase()).replace(/^(.)/, (_2, char) => char.toLowerCase()).replace(/^\d/, "_$&");
32056
32136
  }
32057
32137
  async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddress) {
@@ -32178,9 +32258,9 @@ ${getErrorMessage2(error2)}`));
32178
32258
  }
32179
32259
  async function resolveContract(source, network, apiKey, apiUrl) {
32180
32260
  if (source.source) {
32181
- const filePath = path10.resolve(process.cwd(), source.source);
32261
+ const filePath = path11.resolve(process.cwd(), source.source);
32182
32262
  const abi = await parseClarityFile(filePath);
32183
- const name = source.name || path10.basename(source.source, ".clar").replace(/-/g, "_").replace(/^\d/, "_$&");
32263
+ const name = source.name || path11.basename(source.source, ".clar").replace(/-/g, "_").replace(/^\d/, "_$&");
32184
32264
  const address = typeof source.address === "string" ? source.address : source.address?.[network] || DEFAULT_DEVNET_ADDRESS;
32185
32265
  const { address: contractAddress, contractName } = address.includes(".") ? parseContractId(address) : { address, contractName: name };
32186
32266
  return {
@@ -32256,56 +32336,6 @@ var init_generate = __esm(() => {
32256
32336
  import_fast_glob = __toESM(require_out4(), 1);
32257
32337
  });
32258
32338
 
32259
- // src/commands/init.ts
32260
- var exports_init = {};
32261
- __export(exports_init, {
32262
- init: () => init2
32263
- });
32264
- import { promises as fs7 } from "node:fs";
32265
- import path11 from "node:path";
32266
- async function init2() {
32267
- const configPath = path11.join(process.cwd(), "secondlayer.config.ts");
32268
- try {
32269
- await fs7.access(configPath);
32270
- console.log(source_default3.yellow("⚠ secondlayer.config.ts already exists"));
32271
- return;
32272
- } catch {}
32273
- const hasClarinetProject = await fileExists2("./Clarinet.toml");
32274
- let config;
32275
- if (hasClarinetProject) {
32276
- config = `import { defineConfig } from '@secondlayer/cli';
32277
- import { clarinet } from '@secondlayer/cli/plugins';
32278
-
32279
- export default defineConfig({
32280
- out: './src/generated/contracts.ts',
32281
- plugins: [
32282
- clarinet() // Found Clarinet.toml in current directory
32283
- ]
32284
- });`;
32285
- } else {
32286
- config = `import { defineConfig } from '@secondlayer/cli';
32287
-
32288
- export default defineConfig({
32289
- out: './src/generated/contracts.ts',
32290
- plugins: [],
32291
- });`;
32292
- }
32293
- await fs7.writeFile(configPath, config);
32294
- console.log(source_default3.green("✓ Created `secondlayer.config.ts`"));
32295
- console.log("\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!");
32296
- }
32297
- async function fileExists2(filePath) {
32298
- try {
32299
- await fs7.access(filePath);
32300
- return true;
32301
- } catch {
32302
- return false;
32303
- }
32304
- }
32305
- var init_init = __esm(() => {
32306
- init_source4();
32307
- });
32308
-
32309
32339
  // ../../node_modules/commander/esm.mjs
32310
32340
  var import__ = __toESM(require_commander(), 1);
32311
32341
  var {
@@ -32324,7 +32354,7 @@ var {
32324
32354
  // package.json
32325
32355
  var package_default = {
32326
32356
  name: "@secondlayer/cli",
32327
- version: "5.10.1",
32357
+ version: "7.0.0",
32328
32358
  repository: {
32329
32359
  type: "git",
32330
32360
  url: "git+https://github.com/ryanwaits/secondlayer.git",
@@ -32402,7 +32432,7 @@ var package_default = {
32402
32432
  import { ApiError, SecondLayer } from "@secondlayer/sdk";
32403
32433
 
32404
32434
  // src/lib/http.ts
32405
- init_session();
32435
+ init_resolve_auth();
32406
32436
 
32407
32437
  class CliHttpError extends Error {
32408
32438
  status;
@@ -32416,7 +32446,6 @@ class CliHttpError extends Error {
32416
32446
  this.body = body;
32417
32447
  }
32418
32448
  }
32419
- var PLATFORM_API_URL = process.env.SL_PLATFORM_API_URL ?? "https://api.secondlayer.tools";
32420
32449
  var REQUEST_TIMEOUT_MS = 30000;
32421
32450
  async function request(url, opts) {
32422
32451
  const headers = {
@@ -32447,33 +32476,49 @@ async function request(url, opts) {
32447
32476
  return await res.json();
32448
32477
  }
32449
32478
  async function httpPlatform(path2, opts = {}) {
32450
- const session = await readSession();
32451
- if (!session) {
32479
+ let auth;
32480
+ try {
32481
+ auth = await resolveAuth();
32482
+ } catch {
32452
32483
  throw new CliHttpError(401, "SESSION_EXPIRED", { error: "Not logged in" }, "Not logged in — run `sl login`");
32453
32484
  }
32454
- return request(`${PLATFORM_API_URL}${path2}`, {
32485
+ return request(`${auth.apiUrl}${path2}`, {
32455
32486
  ...opts,
32456
- bearer: session.token
32487
+ bearer: auth.ephemeralKey
32457
32488
  });
32458
32489
  }
32459
32490
  async function httpPlatformAnon(path2, opts = {}) {
32460
- return request(`${PLATFORM_API_URL}${path2}`, opts);
32491
+ return request(`${resolveApiUrl()}${path2}`, opts);
32461
32492
  }
32462
32493
 
32463
32494
  // src/lib/api-client.ts
32495
+ init_output();
32464
32496
  init_resolve_auth();
32497
+ function nextStepHint(status) {
32498
+ if (status === undefined)
32499
+ return;
32500
+ if (status === 403)
32501
+ return "You may not have access — check your active project with `sl whoami`.";
32502
+ if (status === 404)
32503
+ return "Check the name/slug — run the matching `list` command to see what exists.";
32504
+ if (status === 400 || status === 422)
32505
+ return "Check the command arguments and flags — see `--help` for the expected format.";
32506
+ if (status === 429)
32507
+ return "Rate limited — wait a moment and retry.";
32508
+ if (status >= 500)
32509
+ return "Server error — retry shortly, or check `sl status`.";
32510
+ return;
32511
+ }
32465
32512
  function handleApiError(err, action) {
32466
- if (err instanceof CliHttpError) {
32467
- if (err.code === "SESSION_EXPIRED") {
32468
- console.error("Session expired. Run: sl login");
32469
- process.exit(1);
32470
- }
32471
- }
32472
- if (err instanceof ApiError && err.status === 401) {
32473
- console.error("Authentication required. Run: sl login");
32513
+ const status = err instanceof ApiError || err instanceof CliHttpError ? err.status : undefined;
32514
+ if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED" || status === 401) {
32515
+ printError("Authentication required.", {
32516
+ hint: "Run `sl login` to re-authenticate."
32517
+ });
32474
32518
  process.exit(1);
32475
32519
  }
32476
- console.error(`Error: Failed to ${action}: ${err}`);
32520
+ const detail = err instanceof Error ? err.message : String(err);
32521
+ printError(`Failed to ${action}: ${detail}`, { hint: nextStepHint(status) });
32477
32522
  process.exit(1);
32478
32523
  }
32479
32524
  function withErrorHandling(fn, options) {
@@ -32541,105 +32586,116 @@ async function updateAccountProfile(data) {
32541
32586
 
32542
32587
  // src/commands/account.ts
32543
32588
  init_output();
32544
- function registerAccountCommand(program2) {
32545
- const account = program2.command("account").description("Manage your account profile");
32546
- account.command("profile").description("View or update your public profile").option("--name <name>", "Set display name").option("--bio <bio>", "Set bio").option("--slug <slug>", "Set public URL slug").option("--json", "Output as JSON").action(withErrorHandling(async (options) => {
32547
- const hasUpdates = options.name || options.bio || options.slug;
32548
- if (hasUpdates) {
32549
- const data = {};
32550
- if (options.name)
32551
- data.display_name = options.name;
32552
- if (options.bio)
32553
- data.bio = options.bio;
32554
- if (options.slug)
32555
- data.slug = options.slug;
32556
- const updated = await updateAccountProfile(data);
32557
- if (options.json) {
32558
- console.log(JSON.stringify(updated, null, 2));
32559
- return;
32560
- }
32561
- success("Profile updated");
32562
- console.log(formatKeyValue([
32563
- ["Display Name", updated.displayName ?? dim("—")],
32564
- ["Bio", updated.bio ?? dim("—")],
32565
- ["Slug", updated.slug ?? dim("—")]
32566
- ]));
32567
- return;
32568
- }
32569
- const profile = await getAccountProfile();
32570
- if (options.json) {
32571
- console.log(JSON.stringify(profile, null, 2));
32572
- return;
32589
+
32590
+ // src/commands/billing.ts
32591
+ init_output();
32592
+ async function runBillingStatus(json) {
32593
+ let res;
32594
+ try {
32595
+ res = await httpPlatform("/api/billing/status");
32596
+ } catch (err) {
32597
+ if (err instanceof CliHttpError) {
32598
+ error(err.message);
32599
+ process.exit(1);
32573
32600
  }
32601
+ throw err;
32602
+ }
32603
+ output({ json, data: res, human: () => renderBillingStatus(res) });
32604
+ }
32605
+ function addBillingCommand(parent) {
32606
+ parent.command("billing").description("Show your plan, Stripe subscription, trial, and discounts").option("--json", "Output as JSON").action((options) => runBillingStatus(options.json));
32607
+ }
32608
+ function renderBillingStatus(res) {
32609
+ if (!res.subscription) {
32574
32610
  console.log(formatKeyValue([
32611
+ ["Plan", "Free during open beta"],
32612
+ ["Cost", dim("$0 — no limits, no charges")],
32613
+ ["Paid plans", dim("coming after beta")]
32614
+ ]));
32615
+ return;
32616
+ }
32617
+ const rows = [];
32618
+ rows.push(["Plan", res.plan]);
32619
+ rows.push([
32620
+ "Customer",
32621
+ res.stripeCustomerId ?? dim("(none — no subscription yet)")
32622
+ ]);
32623
+ const sub = res.subscription;
32624
+ rows.push(["Subscription", `${sub.id} (${sub.status})`]);
32625
+ if (sub.tier)
32626
+ rows.push(["Tier", sub.tier]);
32627
+ if (sub.amountCents !== null && sub.interval) {
32628
+ const dollars = (sub.amountCents / 100).toFixed(2);
32629
+ rows.push(["Price", `$${dollars} / ${sub.interval}`]);
32630
+ }
32631
+ if (sub.trialEnd) {
32632
+ const days = Math.max(0, Math.round((new Date(sub.trialEnd).getTime() - Date.now()) / 86400000));
32633
+ rows.push([
32634
+ "Trial ends",
32635
+ `${formatDate(sub.trialEnd)} (${days}d remaining)`
32636
+ ]);
32637
+ }
32638
+ if (sub.currentPeriodEnd) {
32639
+ rows.push(["Renews", formatDate(sub.currentPeriodEnd)]);
32640
+ }
32641
+ if (sub.cancelAtPeriodEnd) {
32642
+ rows.push(["Cancels at period end", "yes"]);
32643
+ }
32644
+ if (sub.discount) {
32645
+ const off = sub.discount.percentOff !== null ? `${sub.discount.percentOff}% off` : sub.discount.amountOff !== null ? `$${(sub.discount.amountOff / 100).toFixed(2)} off` : "discount";
32646
+ const label = sub.discount.code ? `${sub.discount.code} (${sub.discount.name ?? "coupon"})` : sub.discount.name ?? "applied";
32647
+ rows.push(["Discount", `${label} — ${off}, ${sub.discount.duration}`]);
32648
+ }
32649
+ console.log(formatKeyValue(rows));
32650
+ }
32651
+ function formatDate(iso) {
32652
+ return new Date(iso).toISOString().slice(0, 10);
32653
+ }
32654
+
32655
+ // src/commands/account.ts
32656
+ async function showProfile(json) {
32657
+ const profile = await getAccountProfile();
32658
+ output({
32659
+ json,
32660
+ data: profile,
32661
+ human: () => console.log(formatKeyValue([
32575
32662
  ["Email", profile.email],
32576
32663
  ["Plan", profile.plan],
32577
32664
  ["Display Name", profile.displayName ?? dim("—")],
32578
32665
  ["Bio", profile.bio ?? dim("—")],
32579
32666
  ["Slug", profile.slug ?? dim("—")]
32580
- ]));
32581
- }, { action: "manage profile" }));
32667
+ ]))
32668
+ });
32582
32669
  }
32583
- // src/commands/billing.ts
32584
- init_output();
32585
- function registerBillingCommand(program2) {
32586
- const billing = program2.command("billing").description("Inspect billing state");
32587
- billing.command("status").description("Show your current plan, Stripe subscription, trial, and discounts").action(async () => {
32588
- let res;
32589
- try {
32590
- res = await httpPlatform("/api/billing/status");
32591
- } catch (err) {
32592
- if (err instanceof CliHttpError) {
32593
- error(err.message);
32594
- process.exit(1);
32595
- }
32596
- throw err;
32597
- }
32598
- if (!res.subscription) {
32670
+ async function applyProfileUpdate(options) {
32671
+ const data = {};
32672
+ if (options.name)
32673
+ data.display_name = options.name;
32674
+ if (options.bio)
32675
+ data.bio = options.bio;
32676
+ if (options.slug)
32677
+ data.slug = options.slug;
32678
+ const updated = await updateAccountProfile(data);
32679
+ output({
32680
+ json: options.json,
32681
+ data: updated,
32682
+ human: () => {
32683
+ success("Profile updated");
32599
32684
  console.log(formatKeyValue([
32600
- ["Plan", "Free during open beta"],
32601
- ["Cost", dim("$0 — no limits, no charges")],
32602
- ["Paid plans", dim("coming after beta")]
32685
+ ["Display Name", updated.displayName ?? dim("—")],
32686
+ ["Bio", updated.bio ?? dim("—")],
32687
+ ["Slug", updated.slug ?? dim("—")]
32603
32688
  ]));
32604
- return;
32605
- }
32606
- const rows = [];
32607
- rows.push(["Plan", res.plan]);
32608
- rows.push([
32609
- "Customer",
32610
- res.stripeCustomerId ?? dim("(none — no subscription yet)")
32611
- ]);
32612
- const sub = res.subscription;
32613
- rows.push(["Subscription", `${sub.id} (${sub.status})`]);
32614
- if (sub.tier)
32615
- rows.push(["Tier", sub.tier]);
32616
- if (sub.amountCents !== null && sub.interval) {
32617
- const dollars = (sub.amountCents / 100).toFixed(2);
32618
- rows.push(["Price", `$${dollars} / ${sub.interval}`]);
32619
- }
32620
- if (sub.trialEnd) {
32621
- const days = Math.max(0, Math.round((new Date(sub.trialEnd).getTime() - Date.now()) / 86400000));
32622
- rows.push([
32623
- "Trial ends",
32624
- `${formatDate(sub.trialEnd)} (${days}d remaining)`
32625
- ]);
32626
32689
  }
32627
- if (sub.currentPeriodEnd) {
32628
- rows.push(["Renews", formatDate(sub.currentPeriodEnd)]);
32629
- }
32630
- if (sub.cancelAtPeriodEnd) {
32631
- rows.push(["Cancels at period end", "yes"]);
32632
- }
32633
- if (sub.discount) {
32634
- const off = sub.discount.percentOff !== null ? `${sub.discount.percentOff}% off` : sub.discount.amountOff !== null ? `$${(sub.discount.amountOff / 100).toFixed(2)} off` : "discount";
32635
- const label = sub.discount.code ? `${sub.discount.code} (${sub.discount.name ?? "coupon"})` : sub.discount.name ?? "applied";
32636
- rows.push(["Discount", `${label} — ${off}, ${sub.discount.duration}`]);
32637
- }
32638
- console.log(formatKeyValue(rows));
32639
32690
  });
32640
32691
  }
32641
- function formatDate(iso) {
32642
- return new Date(iso).toISOString().slice(0, 10);
32692
+ function registerAccountCommand(program2) {
32693
+ const account = program2.command("account").description("Manage your account profile");
32694
+ addBillingCommand(account);
32695
+ account.command("get").description("Show your account profile").option("--json", "Output as JSON").action(withErrorHandling(async (options) => showProfile(options.json), { action: "show profile" }));
32696
+ account.command("update").description("Update your public profile").option("--name <name>", "Set display name").option("--bio <bio>", "Set bio").option("--slug <slug>", "Set public URL slug").option("--json", "Output as JSON").action(withErrorHandling(async (options) => applyProfileUpdate(options), {
32697
+ action: "update profile"
32698
+ }));
32643
32699
  }
32644
32700
  // src/commands/config.ts
32645
32701
  init_config();
@@ -32885,10 +32941,14 @@ async function detectStacksNodes() {
32885
32941
  init_output();
32886
32942
  function registerConfigCommand(program2) {
32887
32943
  const config = program2.command("config").description("Manage CLI configuration");
32888
- config.command("show").description("Show current configuration").action(async () => {
32944
+ config.command("get").description("Show current configuration").option("--json", "Output as JSON").action(async (options) => {
32889
32945
  try {
32890
32946
  const cfg = await loadConfig();
32891
- console.log(dim(`Config file: ${getConfigPath()}`));
32947
+ if (options.json) {
32948
+ writeData(JSON.stringify(cfg, null, 2));
32949
+ return;
32950
+ }
32951
+ note(`Config file: ${getConfigPath()}`);
32892
32952
  console.log("");
32893
32953
  await printConfigTree(cfg);
32894
32954
  } catch (err) {
@@ -32896,7 +32956,11 @@ function registerConfigCommand(program2) {
32896
32956
  process.exit(1);
32897
32957
  }
32898
32958
  });
32899
- config.command("set <key> <value>").description("Set a configuration value (supports dot notation: ports.api)").option("--no-validate", "Skip connection validation for database/redis URLs").action(async (key, value, options) => {
32959
+ config.command("set <key> <value>").description("Set a configuration value (supports dot notation: ports.api)").option("--no-validate", "Skip connection validation for database/redis URLs").addHelpText("after", `
32960
+ Examples:
32961
+ $ sl config set network local
32962
+ $ sl config set ports.api 3800
32963
+ $ sl config set database.url postgres://localhost:5432/secondlayer_dev`).action(async (key, value, options) => {
32900
32964
  try {
32901
32965
  await setConfigValue(key, value);
32902
32966
  success(`Set ${key} = ${value}`);
@@ -32926,7 +32990,7 @@ function registerConfigCommand(program2) {
32926
32990
  process.exit(1);
32927
32991
  }
32928
32992
  });
32929
- config.command("clear").description("Clear all configuration (delete config file)").option("-y, --yes", "Skip confirmation").action(async (opts) => {
32993
+ config.command("delete").description("Delete all configuration (remove the config file)").option("-y, --yes", "Skip confirmation").action(async (opts) => {
32930
32994
  try {
32931
32995
  if (!opts.yes && !await confirmDestructive("Delete the config file?")) {
32932
32996
  return;
@@ -33031,20 +33095,97 @@ async function validateDatabaseConnection(url) {
33031
33095
  console.log(dim("The URL was saved but connection failed. Check your database settings."));
33032
33096
  }
33033
33097
  }
33034
- // src/commands/create.ts
33035
- import {
33036
- copyFileSync,
33037
- existsSync,
33038
- mkdirSync,
33039
- readFileSync,
33040
- readdirSync,
33041
- statSync,
33042
- writeFileSync
33043
- } from "node:fs";
33044
- import { dirname as dirname2, join as join4, relative, resolve } from "node:path";
33045
- import { fileURLToPath } from "node:url";
33046
- import { input, select as select2 } from "@inquirer/prompts";
33047
- import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
33098
+ // src/commands/status.ts
33099
+ init_config();
33100
+ init_output();
33101
+ function registerStatusCommand(program2) {
33102
+ program2.command("status").description("Show system status").option("--json", "Output as JSON").action(async (options) => {
33103
+ const config = await loadConfig();
33104
+ try {
33105
+ const status = await httpPlatform("/status");
33106
+ output({
33107
+ json: options.json,
33108
+ data: status,
33109
+ human: () => printStatus(status)
33110
+ });
33111
+ } catch (err) {
33112
+ if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
33113
+ console.error("Not logged in. Run: sl login");
33114
+ process.exit(1);
33115
+ }
33116
+ console.log("");
33117
+ console.log(blue("System Status"));
33118
+ console.log(` ${red("NOT RUNNING")}`);
33119
+ console.log("");
33120
+ if (config.network === "local") {
33121
+ console.log(dim(" API service is not running."));
33122
+ console.log(dim(" Start with: sl local start"));
33123
+ } else {
33124
+ console.log(dim(" Can't reach the platform API."));
33125
+ console.log(dim(" Check your connection or try again."));
33126
+ }
33127
+ console.log("");
33128
+ process.exit(1);
33129
+ }
33130
+ });
33131
+ }
33132
+ function printStatus(status) {
33133
+ console.log("");
33134
+ const statusColor = status.status === "healthy" ? green : red;
33135
+ console.log(blue("System Status"));
33136
+ console.log(` ${statusColor(status.status.toUpperCase())}${status.network ? dim(` (${status.network})`) : ""}`);
33137
+ console.log("");
33138
+ console.log(blue("Database"));
33139
+ const dbColor = status.database.status === "ok" ? green : red;
33140
+ console.log(` Status: ${dbColor(status.database.status)}`);
33141
+ console.log("");
33142
+ console.log(blue("Index Progress"));
33143
+ if (status.indexProgress.length === 0) {
33144
+ console.log(dim(" No data indexed yet"));
33145
+ } else {
33146
+ for (const p of status.indexProgress) {
33147
+ const behind = p.highestSeenBlock - p.lastIndexedBlock;
33148
+ const behindStr = behind > 0 ? yellow(` (${behind} behind)`) : green(" (synced)");
33149
+ console.log(` ${p.network}: block ${p.lastIndexedBlock}${behindStr}`);
33150
+ if (status.chainTip && status.chainTip > 0) {
33151
+ const pct = Math.min(p.lastIndexedBlock / status.chainTip * 100, 100);
33152
+ const barWidth = 30;
33153
+ const filled = Math.round(pct / 100 * barWidth);
33154
+ const empty = barWidth - filled;
33155
+ const bar = `${"█".repeat(filled)}${"░".repeat(empty)}`;
33156
+ const pctStr = `${pct.toFixed(1)}%`;
33157
+ const color = pct >= 99.9 ? green : pct >= 50 ? yellow : red;
33158
+ console.log(` ${dim("chain:")} ${color(bar)} ${color(pctStr)} ${dim(`(tip: ${status.chainTip.toLocaleString()})`)}`);
33159
+ }
33160
+ const contiguous = p.lastContiguousBlock ?? 0;
33161
+ if (status.integrity === "complete") {
33162
+ console.log(` ${dim("contiguous:")} ${contiguous} ${green("(complete)")}`);
33163
+ } else {
33164
+ const gapCount = status.gaps?.length ?? 0;
33165
+ const missing = status.totalMissingBlocks ?? 0;
33166
+ console.log(` ${dim("contiguous:")} ${contiguous} ${yellow(`(${gapCount} gaps, ${missing} missing blocks)`)}`);
33167
+ if (status.gaps) {
33168
+ for (const gap of status.gaps.slice(0, 5)) {
33169
+ const range = gap.gapStart === gap.gapEnd ? `${gap.gapStart}` : `${gap.gapStart}-${gap.gapEnd}`;
33170
+ console.log(` ${dim("gap:")} ${range} ${dim(`(${gap.size} block${gap.size > 1 ? "s" : ""})`)}`);
33171
+ }
33172
+ }
33173
+ }
33174
+ }
33175
+ }
33176
+ console.log("");
33177
+ if (status.activeSubgraphs !== undefined) {
33178
+ console.log(blue("Activity"));
33179
+ console.log(formatKeyValue([
33180
+ [" Active Subgraphs", status.activeSubgraphs.toString()]
33181
+ ]));
33182
+ console.log("");
33183
+ }
33184
+ console.log(dim(`Last updated: ${status.timestamp}`));
33185
+ }
33186
+ // src/commands/subscriptions.ts
33187
+ import { confirm } from "@inquirer/prompts";
33188
+ import { sign } from "@secondlayer/shared/crypto/standard-webhooks";
33048
33189
 
33049
33190
  // src/lib/filter-params.ts
33050
33191
  var FILTER_OPERATORS = ["eq", "neq", "gt", "gte", "lt", "lte"];
@@ -33112,9 +33253,8 @@ function parseSubscriptionFilter(args) {
33112
33253
  return Object.keys(filters).length > 0 ? filters : undefined;
33113
33254
  }
33114
33255
 
33115
- // src/commands/create.ts
33256
+ // src/commands/subscriptions.ts
33116
33257
  init_output();
33117
- init_resolve_auth();
33118
33258
 
33119
33259
  // src/lib/subscription-validation.ts
33120
33260
  import {
@@ -33134,6 +33274,23 @@ async function validateSubscriptionTargetFromApi(client, input) {
33134
33274
  }
33135
33275
  }
33136
33276
 
33277
+ // src/commands/create.ts
33278
+ import {
33279
+ copyFileSync,
33280
+ existsSync,
33281
+ mkdirSync,
33282
+ readFileSync,
33283
+ readdirSync,
33284
+ statSync,
33285
+ writeFileSync
33286
+ } from "node:fs";
33287
+ import { dirname as dirname2, join as join4, relative, resolve } from "node:path";
33288
+ import { fileURLToPath } from "node:url";
33289
+ import { input, select as select2 } from "@inquirer/prompts";
33290
+ import { SecondLayer as SecondLayer2 } from "@secondlayer/sdk";
33291
+ init_output();
33292
+ init_resolve_auth();
33293
+
33137
33294
  // src/utils/urls.ts
33138
33295
  function deriveBaseUrl(apiUrl) {
33139
33296
  const override = process.env.SL_DASHBOARD_URL?.trim();
@@ -33364,104 +33521,22 @@ async function getSubscriptionClient(opts) {
33364
33521
  apiKey: resolvedConfig.apiKey
33365
33522
  });
33366
33523
  }
33367
- function registerCreateCommand(program2) {
33368
- const create = program2.command("create").description("Scaffold new resources (subscription receivers, etc.)");
33369
- create.command("subscription <name>").description("Scaffold a subscription receiver for a runtime").option("-r, --runtime <runtime>", "inngest | trigger | cloudflare | node").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").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--service-key <key>", "SL_SERVICE_KEY override").option("--base-url <url>", "SL_API_URL override").option("--skip-api", "Copy template only, don't call the API").option("--no-scaffold", "Skip the local runtime template directory (webhook-only setups)").action(async (name, options) => {
33524
+ function addSubscriptionScaffold(parent, commandSpec, opts) {
33525
+ parent.command(commandSpec).description(opts.description).option("-r, --runtime <runtime>", "inngest | trigger | cloudflare | node").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").option("--filter <kv...>", "Filter as key=value (supports .eq/.neq/.gt/.gte/.lt/.lte suffixes)").option("--service-key <key>", "SL_SERVICE_KEY override").option("--base-url <url>", "SL_API_URL override").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", `
33526
+ Examples:
33527
+ $ ${opts.examplePrefix} my-sub -s my-graph -t transfers -u https://example.com/webhook
33528
+ $ ${opts.examplePrefix} my-sub -s my-graph -t balances -r inngest --filter amount.gte=1000`).action(async (name, options) => {
33370
33529
  await createSubscription(name, options);
33371
33530
  });
33372
33531
  }
33373
- // src/commands/status.ts
33374
- init_config();
33375
- init_output();
33376
- function registerStatusCommand(program2) {
33377
- program2.command("status").description("Show system status").option("--json", "Output as JSON").action(async (options) => {
33378
- const config = await loadConfig();
33379
- try {
33380
- const status = await httpPlatform("/status");
33381
- if (options.json) {
33382
- console.log(JSON.stringify(status, null, 2));
33383
- return;
33384
- }
33385
- printStatus(status);
33386
- } catch (err) {
33387
- if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
33388
- console.error("Not logged in. Run: sl login");
33389
- process.exit(1);
33390
- }
33391
- console.log("");
33392
- console.log(blue("System Status"));
33393
- console.log(` ${red("NOT RUNNING")}`);
33394
- console.log("");
33395
- if (config.network === "local") {
33396
- console.log(dim(" API service is not running."));
33397
- console.log(dim(" Start with: sl local start"));
33398
- } else {
33399
- console.log(dim(" Can't reach the platform API."));
33400
- console.log(dim(" Check your connection or try again."));
33401
- }
33402
- console.log("");
33403
- process.exit(1);
33404
- }
33532
+ function addSubscriptionsCreateCommand(subscriptions) {
33533
+ addSubscriptionScaffold(subscriptions, "create <name>", {
33534
+ description: "Create a subscription receiver for a runtime",
33535
+ examplePrefix: "sl subscriptions create"
33405
33536
  });
33406
33537
  }
33407
- function printStatus(status) {
33408
- console.log("");
33409
- const statusColor = status.status === "healthy" ? green : red;
33410
- console.log(blue("System Status"));
33411
- console.log(` ${statusColor(status.status.toUpperCase())}${status.network ? dim(` (${status.network})`) : ""}`);
33412
- console.log("");
33413
- console.log(blue("Database"));
33414
- const dbColor = status.database.status === "ok" ? green : red;
33415
- console.log(` Status: ${dbColor(status.database.status)}`);
33416
- console.log("");
33417
- console.log(blue("Index Progress"));
33418
- if (status.indexProgress.length === 0) {
33419
- console.log(dim(" No data indexed yet"));
33420
- } else {
33421
- for (const p of status.indexProgress) {
33422
- const behind = p.highestSeenBlock - p.lastIndexedBlock;
33423
- const behindStr = behind > 0 ? yellow(` (${behind} behind)`) : green(" (synced)");
33424
- console.log(` ${p.network}: block ${p.lastIndexedBlock}${behindStr}`);
33425
- if (status.chainTip && status.chainTip > 0) {
33426
- const pct = Math.min(p.lastIndexedBlock / status.chainTip * 100, 100);
33427
- const barWidth = 30;
33428
- const filled = Math.round(pct / 100 * barWidth);
33429
- const empty = barWidth - filled;
33430
- const bar = `${"█".repeat(filled)}${"░".repeat(empty)}`;
33431
- const pctStr = `${pct.toFixed(1)}%`;
33432
- const color = pct >= 99.9 ? green : pct >= 50 ? yellow : red;
33433
- console.log(` ${dim("chain:")} ${color(bar)} ${color(pctStr)} ${dim(`(tip: ${status.chainTip.toLocaleString()})`)}`);
33434
- }
33435
- const contiguous = p.lastContiguousBlock ?? 0;
33436
- if (status.integrity === "complete") {
33437
- console.log(` ${dim("contiguous:")} ${contiguous} ${green("(complete)")}`);
33438
- } else {
33439
- const gapCount = status.gaps?.length ?? 0;
33440
- const missing = status.totalMissingBlocks ?? 0;
33441
- console.log(` ${dim("contiguous:")} ${contiguous} ${yellow(`(${gapCount} gaps, ${missing} missing blocks)`)}`);
33442
- if (status.gaps) {
33443
- for (const gap of status.gaps.slice(0, 5)) {
33444
- const range = gap.gapStart === gap.gapEnd ? `${gap.gapStart}` : `${gap.gapStart}-${gap.gapEnd}`;
33445
- console.log(` ${dim("gap:")} ${range} ${dim(`(${gap.size} block${gap.size > 1 ? "s" : ""})`)}`);
33446
- }
33447
- }
33448
- }
33449
- }
33450
- }
33451
- console.log("");
33452
- if (status.activeSubgraphs !== undefined) {
33453
- console.log(blue("Activity"));
33454
- console.log(formatKeyValue([
33455
- [" Active Subgraphs", status.activeSubgraphs.toString()]
33456
- ]));
33457
- console.log("");
33458
- }
33459
- console.log(dim(`Last updated: ${status.timestamp}`));
33460
- }
33538
+
33461
33539
  // src/commands/subscriptions.ts
33462
- import { confirm } from "@inquirer/prompts";
33463
- import { sign } from "@secondlayer/shared/crypto/standard-webhooks";
33464
- init_output();
33465
33540
  function commonOptions(cmd) {
33466
33541
  return cmd.option("--service-key <key>", "SL_SERVICE_KEY override").option("--base-url <url>", "SL_API_URL override");
33467
33542
  }
@@ -33818,6 +33893,7 @@ async function confirmOrExit(message, yes) {
33818
33893
  }
33819
33894
  function registerSubscriptionsCommand(program2) {
33820
33895
  const subscriptions = commonOptions(program2.command("subscriptions").alias("subs").description("Manage subgraph table subscriptions"));
33896
+ addSubscriptionsCreateCommand(subscriptions);
33821
33897
  commonOptions(subscriptions.command("list").alias("ls").description("List subscriptions").option("--json", "Output as JSON")).action(async (options) => {
33822
33898
  try {
33823
33899
  const client = await getSubscriptionClient(options);
@@ -33856,7 +33932,11 @@ ${data.length} subscription(s) total`));
33856
33932
  handleApiError(err, "get subscription");
33857
33933
  }
33858
33934
  });
33859
- commonOptions(subscriptions.command("update <idOrName>").description("Update subscription config").option("--name <name>", "Rename subscription").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config").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-subscription delivery concurrency").option("--json", "Output as JSON")).action(async (idOrName, options) => {
33935
+ commonOptions(subscriptions.command("update <idOrName>").description("Update subscription config").option("--name <name>", "Rename subscription").option("--url <url>", "Webhook URL").option("--auth-token <token>", "Set bearer token auth config").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-subscription delivery concurrency").option("--json", "Output as JSON").addHelpText("after", `
33936
+ Examples:
33937
+ $ sl subscriptions update my-sub --url https://example.com/hook
33938
+ $ sl subscriptions update my-sub --filter amount.gte=1000 --max-retries 5
33939
+ $ sl subscriptions update my-sub --clear-filter`)).action(async (idOrName, options) => {
33860
33940
  try {
33861
33941
  const client = await getSubscriptionClient(options);
33862
33942
  const patch = buildUpdatePatch(options);
@@ -33892,7 +33972,7 @@ ${data.length} subscription(s) total`));
33892
33972
  }
33893
33973
  });
33894
33974
  }
33895
- commonOptions(subscriptions.command("delete <idOrName>").description("Delete a subscription").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")).action(async (idOrName, options) => {
33975
+ commonOptions(subscriptions.command("delete <idOrName>").alias("rm").description("Delete a subscription").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")).action(async (idOrName, options) => {
33896
33976
  try {
33897
33977
  const client = await getSubscriptionClient(options);
33898
33978
  let resolved = null;
@@ -33983,7 +34063,9 @@ ${data.length} subscription(s) total`));
33983
34063
  handleApiError(err, "requeue dead-letter row");
33984
34064
  }
33985
34065
  });
33986
- commonOptions(subscriptions.command("replay <idOrName>").description("Replay a block range").requiredOption("--from-block <n>", "Start block height").requiredOption("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON")).action(async (idOrName, options) => {
34066
+ commonOptions(subscriptions.command("replay <idOrName>").description("Replay a block range").requiredOption("--from-block <n>", "Start block height").requiredOption("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON").addHelpText("after", `
34067
+ Examples:
34068
+ $ sl subscriptions replay my-sub --from-block 150000 --to-block 160000 -y`)).action(async (idOrName, options) => {
33987
34069
  try {
33988
34070
  const fromBlock = requireIntegerOption(options.fromBlock, "--from-block");
33989
34071
  const toBlock = requireIntegerOption(options.toBlock, "--to-block");
@@ -34080,363 +34162,10 @@ POST result:`));
34080
34162
  }
34081
34163
  });
34082
34164
  }
34083
- // src/commands/db.ts
34084
- init_config();
34085
- init_dev_state();
34086
- init_output();
34087
- import { confirm as confirm2 } from "@inquirer/prompts";
34088
- import { getDb, sql } from "@secondlayer/shared/db";
34089
- import {
34090
- countMissingBlocks,
34091
- findGaps
34092
- } from "@secondlayer/shared/db/queries/integrity";
34093
- import { StacksNodeClient } from "@secondlayer/shared/node";
34094
- var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
34095
- function registerDbCommand(program2) {
34096
- const dbCmd = program2.command("db").description("Inspect indexer database tables").hook("preAction", async () => {
34097
- await requireLocalNetwork();
34098
- }).action(async () => {
34099
- await showOverview(10);
34100
- });
34101
- dbCmd.command("blocks").description("Show recent blocks").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
34102
- const opts = this.opts();
34103
- await showBlocks(Number.parseInt(opts.limit), opts.json);
34104
- });
34105
- dbCmd.command("txs").description("Show recent transactions").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
34106
- const opts = this.opts();
34107
- await showTransactions(Number.parseInt(opts.limit), opts.json);
34108
- });
34109
- dbCmd.command("events").description("Show recent events").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
34110
- const opts = this.opts();
34111
- await showEvents(Number.parseInt(opts.limit), opts.json);
34112
- });
34113
- dbCmd.command("gaps").description("Show gaps in indexed block data").option("--limit <n>", "Number of gaps to show", "50").option("--json", "Output as JSON").action(async function() {
34114
- const opts = this.opts();
34115
- await showGaps(Number.parseInt(opts.limit), opts.json);
34116
- });
34117
- dbCmd.command("reset").description("Truncate all indexed data (blocks, txs, events)").option("-y, --yes", "Skip confirmation prompt").action(async function() {
34118
- const opts = this.opts();
34119
- await resetDatabase(opts.yes);
34120
- });
34121
- dbCmd.command("resync").description("Reset database and restart indexer for fresh sync").option("-y, --yes", "Skip confirmation prompt").option("--backfill", "After reset, fetch all blocks from node").action(async function() {
34122
- const opts = this.opts();
34123
- await resyncDatabase(opts.yes, opts.backfill);
34124
- });
34125
- }
34126
- function ensureDb() {
34127
- if (!process.env.DATABASE_URL) {
34128
- process.env.DATABASE_URL = DEV_DATABASE_URL;
34129
- }
34130
- return getDb();
34131
- }
34132
- async function showOverview(_limit) {
34133
- try {
34134
- const db = ensureDb();
34135
- const blockCountResult = await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst();
34136
- const txCountResult = await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst();
34137
- const eventCountResult = await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst();
34138
- const blockCount = blockCountResult?.count ?? 0;
34139
- const txCount = txCountResult?.count ?? 0;
34140
- const eventCount = eventCountResult?.count ?? 0;
34141
- const latest = await db.selectFrom("blocks").select(["height", "hash", "timestamp"]).orderBy("height", "desc").limit(1).executeTakeFirst();
34142
- console.log("");
34143
- console.log(blue("Database Overview"));
34144
- console.log("");
34145
- console.log(` Blocks: ${green(blockCount.toString())}`);
34146
- console.log(` Transactions: ${green(txCount.toString())}`);
34147
- console.log(` Events: ${green(eventCount.toString())}`);
34148
- console.log("");
34149
- if (latest) {
34150
- const time = new Date(latest.timestamp * 1000).toISOString();
34151
- console.log(blue("Latest Block"));
34152
- console.log(` Height: ${latest.height}`);
34153
- console.log(` Hash: ${dim(latest.hash.slice(0, 20))}...`);
34154
- console.log(` Time: ${time}`);
34155
- console.log("");
34156
- }
34157
- console.log(dim(`Use 'sl db blocks|txs|events' to see records`));
34158
- console.log("");
34159
- process.exit(0);
34160
- } catch (err) {
34161
- error(`Failed to query database: ${err}`);
34162
- console.log(dim(`
34163
- Make sure PostgreSQL is running.`));
34164
- console.log(dim("Run 'sl local start' to start all services."));
34165
- process.exit(1);
34166
- }
34167
- }
34168
- async function showBlocks(limit, json) {
34169
- try {
34170
- const db = ensureDb();
34171
- const rows = await db.selectFrom("blocks").select(["height", "hash", "timestamp", "canonical"]).orderBy("height", "desc").limit(limit).execute();
34172
- if (json) {
34173
- console.log(JSON.stringify(rows, null, 2));
34174
- process.exit(0);
34175
- }
34176
- console.log("");
34177
- console.log(blue(`Recent Blocks (${rows.length})`));
34178
- console.log("");
34179
- console.log(dim(" HEIGHT".padEnd(10)) + dim("HASH".padEnd(24)) + dim("TIME"));
34180
- for (const row of rows) {
34181
- const time = new Date(row.timestamp * 1000).toLocaleTimeString();
34182
- const canonicalMark = row.canonical ? "" : yellow(" (reorg)");
34183
- console.log(` ${row.height.toString().padEnd(10)}${`${row.hash.slice(0, 20)}... `.padEnd(24)}${time}${canonicalMark}`);
34184
- }
34185
- console.log("");
34186
- process.exit(0);
34187
- } catch (err) {
34188
- error(`Failed to query blocks: ${err}`);
34189
- process.exit(1);
34190
- }
34191
- }
34192
- async function showTransactions(limit, json) {
34193
- try {
34194
- const db = ensureDb();
34195
- const rows = await db.selectFrom("transactions").select([
34196
- "tx_id",
34197
- "block_height",
34198
- "type",
34199
- "sender",
34200
- "status",
34201
- "contract_id",
34202
- "function_name"
34203
- ]).orderBy("block_height", "desc").limit(limit).execute();
34204
- if (json) {
34205
- console.log(JSON.stringify(rows, null, 2));
34206
- process.exit(0);
34207
- }
34208
- console.log("");
34209
- console.log(blue(`Recent Transactions (${rows.length})`));
34210
- console.log("");
34211
- console.log(dim(" BLOCK".padEnd(8)) + dim("TYPE".padEnd(18)) + dim("SENDER".padEnd(20)) + dim("CONTRACT/FUNCTION"));
34212
- for (const row of rows) {
34213
- const statusColor = row.status === "success" ? green : yellow;
34214
- const contractInfo = row.contract_id ? `${row.contract_id.split(".")[1] || row.contract_id}${row.function_name ? `::${row.function_name}` : ""}` : "-";
34215
- console.log(` ${statusColor(row.block_height.toString().padEnd(8))}${row.type.padEnd(18)}${`${row.sender.slice(0, 18)}... `.padEnd(20)}${contractInfo}`);
34216
- }
34217
- console.log("");
34218
- process.exit(0);
34219
- } catch (err) {
34220
- error(`Failed to query transactions: ${err}`);
34221
- process.exit(1);
34222
- }
34223
- }
34224
- async function showEvents(limit, json) {
34225
- try {
34226
- const db = ensureDb();
34227
- const rows = await db.selectFrom("events").select(["block_height", "tx_id", "event_index", "type", "data"]).orderBy("block_height", "desc").limit(limit).execute();
34228
- if (json) {
34229
- console.log(JSON.stringify(rows, null, 2));
34230
- process.exit(0);
34231
- }
34232
- console.log("");
34233
- console.log(blue(`Recent Events (${rows.length})`));
34234
- console.log("");
34235
- if (rows.length === 0) {
34236
- console.log(dim(" No events found"));
34237
- console.log("");
34238
- process.exit(0);
34239
- }
34240
- console.log(dim(" BLOCK".padEnd(8)) + dim("INDEX".padEnd(8)) + dim("TYPE".padEnd(24)) + dim("TX"));
34241
- for (const row of rows) {
34242
- console.log(` ${row.block_height.toString().padEnd(8)}` + `${row.event_index.toString().padEnd(8)}` + `${row.type.padEnd(24)}` + `${row.tx_id.slice(0, 16)}...`);
34243
- }
34244
- console.log("");
34245
- process.exit(0);
34246
- } catch (err) {
34247
- error(`Failed to query events: ${err}`);
34248
- process.exit(1);
34249
- }
34250
- }
34251
- async function showGaps(limit, json) {
34252
- try {
34253
- const db = ensureDb();
34254
- const gaps = await findGaps(db, limit);
34255
- const missing = await countMissingBlocks(db);
34256
- if (json) {
34257
- console.log(JSON.stringify({ gaps, totalMissingBlocks: missing }, null, 2));
34258
- process.exit(0);
34259
- }
34260
- console.log("");
34261
- if (gaps.length === 0) {
34262
- console.log(green("No gaps detected — block data is contiguous"));
34263
- console.log("");
34264
- process.exit(0);
34265
- }
34266
- console.log(blue(`Block Gaps (${gaps.length})`));
34267
- console.log("");
34268
- console.log(dim(" GAP_START".padEnd(14)) + dim("GAP_END".padEnd(14)) + dim("SIZE"));
34269
- for (const gap of gaps) {
34270
- console.log(` ${gap.gapStart.toString().padEnd(14)}` + `${gap.gapEnd.toString().padEnd(14)}` + `${gap.size}`);
34271
- }
34272
- console.log("");
34273
- console.log(`${yellow(gaps.length.toString())} gaps, ${red(missing.toString())} missing blocks`);
34274
- console.log("");
34275
- process.exit(0);
34276
- } catch (err) {
34277
- error(`Failed to query gaps: ${err}`);
34278
- process.exit(1);
34279
- }
34280
- }
34281
- async function resetDatabase(skipConfirm) {
34282
- try {
34283
- const db = ensureDb();
34284
- const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
34285
- const txCount = (await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
34286
- const eventCount = (await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
34287
- console.log("");
34288
- console.log(yellow("This will delete all indexed blockchain data:"));
34289
- console.log("");
34290
- console.log(` ${red(blockCount.toString())} blocks`);
34291
- console.log(` ${red(txCount.toString())} transactions`);
34292
- console.log(` ${red(eventCount.toString())} events`);
34293
- console.log(` ${dim("+ index_progress")}`);
34294
- console.log("");
34295
- console.log(dim("Note: Subgraph configurations will be preserved."));
34296
- console.log("");
34297
- if (!skipConfirm) {
34298
- const confirmed = await confirm2({
34299
- message: "Are you sure you want to reset the database?",
34300
- default: false
34301
- });
34302
- if (!confirmed) {
34303
- info("Cancelled");
34304
- process.exit(0);
34305
- }
34306
- }
34307
- info("Truncating tables...");
34308
- await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
34309
- console.log("");
34310
- success("Database reset complete");
34311
- console.log("");
34312
- console.log(dim("Run 'sl local restart' to restart the indexer for fresh sync."));
34313
- console.log("");
34314
- process.exit(0);
34315
- } catch (err) {
34316
- error(`Failed to reset database: ${err}`);
34317
- process.exit(1);
34318
- }
34319
- }
34320
- async function resyncDatabase(skipConfirm, backfill) {
34321
- try {
34322
- const db = ensureDb();
34323
- const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
34324
- console.log("");
34325
- console.log(yellow("This will:"));
34326
- console.log(` 1. Delete all indexed data (${red(blockCount.toString())} blocks)`);
34327
- console.log(" 2. Restart the indexer for fresh sync");
34328
- if (backfill) {
34329
- console.log(" 3. Fetch all blocks from node (backfill)");
34330
- }
34331
- console.log("");
34332
- console.log(dim("Note: Subgraph configurations will be preserved."));
34333
- console.log("");
34334
- if (!skipConfirm) {
34335
- const confirmed = await confirm2({
34336
- message: "Are you sure you want to resync?",
34337
- default: false
34338
- });
34339
- if (!confirmed) {
34340
- info("Cancelled");
34341
- process.exit(0);
34342
- }
34343
- }
34344
- info("Truncating tables...");
34345
- await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
34346
- console.log(green(" ✓ Database reset"));
34347
- const state = await loadDevState();
34348
- if (state?.services?.indexer && isProcessRunning(state.services.indexer.pid)) {
34349
- info("Restarting indexer...");
34350
- try {
34351
- process.kill(state.services.indexer.pid, "SIGTERM");
34352
- await Bun.sleep(1000);
34353
- } catch {}
34354
- if (isProcessRunning(state.services.indexer.pid)) {
34355
- try {
34356
- process.kill(state.services.indexer.pid, "SIGKILL");
34357
- } catch {}
34358
- }
34359
- console.log(green(" ✓ Indexer stopped"));
34360
- console.log("");
34361
- info("Run 'sl local restart' to start fresh sync");
34362
- } else {
34363
- console.log("");
34364
- success("Database reset complete");
34365
- console.log("");
34366
- if (!backfill) {
34367
- console.log(dim("Indexer not running. Start with 'sl local start' to begin sync."));
34368
- }
34369
- }
34370
- if (backfill) {
34371
- console.log("");
34372
- info("Starting backfill from node...");
34373
- const nodeClient = new StacksNodeClient;
34374
- const healthy = await nodeClient.isHealthy();
34375
- if (!healthy) {
34376
- warn(`Cannot reach Stacks node at ${nodeClient.getRpcUrl()}`);
34377
- console.log(dim("Run 'sl sync --from 1 --to <tip>' manually once the node is available."));
34378
- console.log("");
34379
- process.exit(0);
34380
- }
34381
- const nodeInfo = await nodeClient.getInfo();
34382
- const tip = nodeInfo.stacks_tip_height;
34383
- info(`Node tip: block ${tip}. Fetching blocks 1 to ${tip}...`);
34384
- console.log(dim(`This may take a while. Run 'sl sync --from 1 --to ${tip}' if interrupted.`));
34385
- console.log("");
34386
- const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
34387
- const config = await loadConfig2();
34388
- const indexerUrl = process.env.INDEXER_URL || `http://localhost:${config.ports.indexer}`;
34389
- const concurrency = 5;
34390
- let fetched = 0;
34391
- let errors = 0;
34392
- for (let i = 1;i <= tip; i += concurrency) {
34393
- const batch = [];
34394
- for (let j = i;j < i + concurrency && j <= tip; j++) {
34395
- batch.push(j);
34396
- }
34397
- const results = await Promise.allSettled(batch.map(async (height) => {
34398
- const block = await nodeClient.getBlock(height);
34399
- if (!block)
34400
- throw new Error(`Block ${height} not found`);
34401
- const res = await fetch(`${indexerUrl}/new_block`, {
34402
- method: "POST",
34403
- headers: {
34404
- "Content-Type": "application/json",
34405
- "X-Source": "backfill"
34406
- },
34407
- body: JSON.stringify(block)
34408
- });
34409
- if (!res.ok)
34410
- throw new Error(`Indexer rejected block ${height}: ${res.status}`);
34411
- }));
34412
- for (const r of results) {
34413
- if (r.status === "fulfilled")
34414
- fetched++;
34415
- else
34416
- errors++;
34417
- }
34418
- const pct = Math.round((fetched + errors) / tip * 100);
34419
- process.stdout.write(`\r ${green(`${fetched}`)} fetched, ${errors > 0 ? red(`${errors} errors`) : "0 errors"} (${pct}%)`);
34420
- }
34421
- console.log("");
34422
- console.log("");
34423
- if (errors === 0) {
34424
- success(`Backfill complete: ${fetched} blocks indexed`);
34425
- } else {
34426
- warn(`Backfill complete: ${fetched} indexed, ${errors} errors`);
34427
- }
34428
- }
34429
- console.log("");
34430
- process.exit(0);
34431
- } catch (err) {
34432
- error(`Failed to resync: ${err}`);
34433
- process.exit(1);
34434
- }
34435
- }
34436
34165
  // src/commands/devnet.ts
34437
34166
  import { spawnSync } from "node:child_process";
34438
34167
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
34439
- import { dirname as dirname4, join as join7 } from "node:path";
34168
+ import { dirname as dirname4, join as join6 } from "node:path";
34440
34169
 
34441
34170
  // src/lib/devnet-compose.ts
34442
34171
  var DEFAULT_IMAGE_OWNER = "ryanwaits";
@@ -34579,14 +34308,14 @@ volumes:
34579
34308
 
34580
34309
  // src/lib/devnet-config.ts
34581
34310
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
34582
- import { dirname as dirname3, join as join6, parse as parsePath } from "node:path";
34311
+ import { dirname as dirname3, join as join5, parse as parsePath } from "node:path";
34583
34312
  import { parse as parseToml } from "smol-toml";
34584
34313
  var DEFAULT_INDEXER_OBSERVER = "host.docker.internal:3700";
34585
34314
  function findClarinetProject(startDir) {
34586
34315
  let dir = startDir;
34587
34316
  const { root } = parsePath(dir);
34588
34317
  while (true) {
34589
- if (existsSync2(join6(dir, "Clarinet.toml")))
34318
+ if (existsSync2(join5(dir, "Clarinet.toml")))
34590
34319
  return dir;
34591
34320
  if (dir === root)
34592
34321
  return null;
@@ -34633,7 +34362,7 @@ stacks_node_events_observers = [${entry}]
34633
34362
 
34634
34363
  // src/commands/devnet.ts
34635
34364
  init_output();
34636
- var COMPOSE_REL = join7(".secondlayer", "docker-compose.yml");
34365
+ var COMPOSE_REL = join6(".secondlayer", "docker-compose.yml");
34637
34366
  function ensureDocker() {
34638
34367
  const probe = spawnSync("docker", ["info"], { stdio: "ignore" });
34639
34368
  if (probe.error || probe.status !== 0) {
@@ -34668,16 +34397,16 @@ function registerDevnetCommand(program2) {
34668
34397
  devnet.command("down").description("Stop the local Secondlayer stack started by `sl devnet connect`").option("--project <dir>", "Clarinet project directory").option("--purge", "Also remove volumes (wipes the local index)").action(async (options) => {
34669
34398
  await down(options);
34670
34399
  });
34671
- devnet.command("status").description("Snapshot of the local stack: ingest, subgraphs, and recent activity").option("-w, --watch", "Refresh every 2s until Ctrl-C").option("-n, --limit <n>", "Recent activity rows to show", "12").action(async (options) => {
34400
+ 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) => {
34672
34401
  await status(options);
34673
34402
  });
34674
- 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, --tail <n>", "Lines to show from the end of each log", "200").action(async (service, options) => {
34403
+ 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) => {
34675
34404
  await logs(service, options);
34676
34405
  });
34677
34406
  }
34678
34407
  function resolveProject(explicit) {
34679
34408
  if (explicit) {
34680
- if (!existsSync3(join7(explicit, "Clarinet.toml"))) {
34409
+ if (!existsSync3(join6(explicit, "Clarinet.toml"))) {
34681
34410
  error(`No Clarinet.toml in ${explicit}`);
34682
34411
  process.exit(1);
34683
34412
  }
@@ -34693,7 +34422,7 @@ function resolveProject(explicit) {
34693
34422
  }
34694
34423
  async function connect(options) {
34695
34424
  const project = resolveProject(options.project);
34696
- const devnetToml = join7(project, "settings", "Devnet.toml");
34425
+ const devnetToml = join6(project, "settings", "Devnet.toml");
34697
34426
  mkdirSync2(dirname4(devnetToml), { recursive: true });
34698
34427
  const result = ensureEventObserver(devnetToml, DEFAULT_INDEXER_OBSERVER);
34699
34428
  console.log(`${green("✓")} found Clarinet.toml`);
@@ -34703,7 +34432,7 @@ async function connect(options) {
34703
34432
  console.log(`${green("✓")} ${result.status === "created" ? "created" : "patched"} settings/Devnet.toml`);
34704
34433
  console.log(dim(` + stacks_node_events_observers = ["${DEFAULT_INDEXER_OBSERVER}"]`));
34705
34434
  }
34706
- const composePath = join7(project, COMPOSE_REL);
34435
+ const composePath = join6(project, COMPOSE_REL);
34707
34436
  mkdirSync2(dirname4(composePath), { recursive: true });
34708
34437
  writeFileSync3(composePath, buildDevnetCompose({ owner: options.owner, imageTag: options.imageTag }));
34709
34438
  console.log(`${green("✓")} wrote ${COMPOSE_REL}`);
@@ -34727,13 +34456,13 @@ ${bold("Secondlayer stack up")}`);
34727
34456
  console.log(`
34728
34457
  ${bold("Next:")}`);
34729
34458
  console.log(` ${yellow("clarinet devnet start")} ${dim("# auto-deploys + streams to the indexer")}`);
34730
- console.log(` ${yellow("SL_API_URL=http://localhost:3800 SL_SERVICE_KEY=dummy sl subgraphs deploy ./subgraph.ts")}`);
34459
+ console.log(` ${yellow("SL_API_URL=http://localhost:3800 SL_API_KEY=dummy sl subgraphs deploy ./subgraph.ts")}`);
34731
34460
  console.log(dim(`
34732
34461
  Stop with: sl devnet down`));
34733
34462
  }
34734
34463
  async function down(options) {
34735
34464
  const project = resolveProject(options.project);
34736
- const composePath = join7(project, COMPOSE_REL);
34465
+ const composePath = join6(project, COMPOSE_REL);
34737
34466
  if (!existsSync3(composePath)) {
34738
34467
  error(`No ${COMPOSE_REL} in ${project} — nothing to stop. Run \`sl devnet connect\` first.`);
34739
34468
  process.exit(1);
@@ -34748,7 +34477,7 @@ async function down(options) {
34748
34477
  }
34749
34478
  async function logs(service, options) {
34750
34479
  const project = resolveProject(options.project);
34751
- const composePath = join7(project, COMPOSE_REL);
34480
+ const composePath = join6(project, COMPOSE_REL);
34752
34481
  if (!existsSync3(composePath)) {
34753
34482
  error(`No ${COMPOSE_REL} in ${project} — run \`sl devnet connect\` first.`);
34754
34483
  process.exit(1);
@@ -34758,7 +34487,7 @@ async function logs(service, options) {
34758
34487
  process.exit(1);
34759
34488
  }
34760
34489
  ensureDocker();
34761
- const args = ["logs", "--tail", options.tail];
34490
+ const args = ["logs", "--tail", options.lines ?? "200"];
34762
34491
  if (options.follow)
34763
34492
  args.push("-f");
34764
34493
  if (service)
@@ -34875,9 +34604,9 @@ import {
34875
34604
  watch,
34876
34605
  writeFileSync as writeFileSync4
34877
34606
  } from "node:fs";
34878
- import { dirname as dirname5, join as join8, resolve as resolve2 } from "node:path";
34607
+ import { dirname as dirname5, join as join7, resolve as resolve2 } from "node:path";
34879
34608
  import { fileURLToPath as fileURLToPath2 } from "node:url";
34880
- import { confirm as confirm4 } from "@inquirer/prompts";
34609
+ import { confirm as confirm3 } from "@inquirer/prompts";
34881
34610
 
34882
34611
  // src/generators/subgraph-scaffold.ts
34883
34612
  init_format();
@@ -35140,9 +34869,40 @@ init_fs();
35140
34869
  init_output();
35141
34870
 
35142
34871
  // src/commands/login.ts
35143
- import { confirm as confirm3, input as input2 } from "@inquirer/prompts";
34872
+ import { confirm as confirm2, input as input2 } from "@inquirer/prompts";
35144
34873
  init_output();
35145
34874
  init_session();
34875
+ function sessionExpiry() {
34876
+ return new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString();
34877
+ }
34878
+ async function readStdin() {
34879
+ const chunks = [];
34880
+ for await (const chunk of process.stdin)
34881
+ chunks.push(chunk);
34882
+ return Buffer.concat(chunks).toString("utf8").trim();
34883
+ }
34884
+ async function runTokenLogin() {
34885
+ const token = await readStdin();
34886
+ if (!token) {
34887
+ error('No token on stdin. Usage: echo "$KEY" | sl login --with-token');
34888
+ process.exit(1);
34889
+ }
34890
+ process.env.SL_API_KEY = token;
34891
+ let account;
34892
+ try {
34893
+ account = await httpPlatform("/api/accounts/me");
34894
+ } catch (err) {
34895
+ error(err instanceof CliHttpError ? `Token rejected: ${err.message}` : err instanceof Error ? err.message : String(err));
34896
+ process.exit(1);
34897
+ }
34898
+ await writeSession({
34899
+ token,
34900
+ email: account.email,
34901
+ accountId: account.id,
34902
+ expiresAt: sessionExpiry()
34903
+ });
34904
+ success(`Logged in as ${account.email}`);
34905
+ }
35146
34906
  async function runLoginFlow(options = {}) {
35147
34907
  if (!options.force) {
35148
34908
  const existing = await readSession();
@@ -35153,7 +34913,7 @@ async function runLoginFlow(options = {}) {
35153
34913
  return;
35154
34914
  }
35155
34915
  try {
35156
- const proceed = await confirm3({
34916
+ const proceed = await confirm2({
35157
34917
  message: "Log in as a different user?",
35158
34918
  default: false
35159
34919
  });
@@ -35197,12 +34957,11 @@ async function runLoginFlow(options = {}) {
35197
34957
  method: "POST",
35198
34958
  body: { email, code }
35199
34959
  });
35200
- const expiresAt = new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString();
35201
34960
  await writeSession({
35202
34961
  token: verified.sessionToken,
35203
34962
  email: verified.account.email,
35204
34963
  accountId: verified.account.id,
35205
- expiresAt
34964
+ expiresAt: sessionExpiry()
35206
34965
  });
35207
34966
  success(`Logged in as ${verified.account.email}`);
35208
34967
  info(dim("Run 'sl whoami' to see your account status."));
@@ -35216,7 +34975,10 @@ async function runLoginFlow(options = {}) {
35216
34975
  }
35217
34976
  }
35218
34977
  function registerLoginCommand(program2) {
35219
- program2.command("login").description("Log in to Secondlayer (magic-link email)").option("-f, --force", "Skip the already-logged-in check and re-run the flow").action((opts) => runLoginFlow({ force: opts.force }));
34978
+ program2.command("login").description("Log in to Secondlayer (magic-link email)").option("--force", "Skip the already-logged-in check and re-run the flow").option("--with-token", "Read an API key from stdin (non-interactive)").addHelpText("after", `
34979
+ Examples:
34980
+ $ sl login
34981
+ $ echo "$SL_API_KEY" | sl login --with-token`).action((opts) => opts.withToken ? runTokenLogin() : runLoginFlow({ force: opts.force }));
35220
34982
  }
35221
34983
 
35222
34984
  // src/lib/require-auth.ts
@@ -35622,7 +35384,7 @@ async function loadSubgraphWithDepCheck(absPath) {
35622
35384
  if (!missingSdk)
35623
35385
  throw err;
35624
35386
  warn("Missing dependency: @secondlayer/subgraphs");
35625
- const install = await confirm4({
35387
+ const install = await confirm3({
35626
35388
  message: "Install with `bun add @secondlayer/subgraphs`?",
35627
35389
  default: true
35628
35390
  });
@@ -35678,19 +35440,48 @@ function formatSubgraphSpecOutput(spec, format) {
35678
35440
  return `${JSON.stringify(spec, null, 2)}
35679
35441
  `;
35680
35442
  }
35681
- async function writeOrPrintSubgraphSpec(spec, format, output) {
35443
+ async function writeOrPrintSubgraphSpec(spec, format, output2) {
35682
35444
  const text = formatSubgraphSpecOutput(spec, format);
35683
- if (!output) {
35445
+ if (!output2) {
35684
35446
  process.stdout.write(text);
35685
35447
  return;
35686
35448
  }
35687
- const outPath = resolve2(output);
35449
+ const outPath = resolve2(output2);
35688
35450
  const dir = resolve2(outPath, "..");
35689
35451
  if (!existsSync4(dir))
35690
35452
  mkdirSync3(dir, { recursive: true });
35691
35453
  await writeTextFile(outPath, text);
35692
35454
  success(`Created ${outPath}`);
35693
35455
  }
35456
+ async function specFromLocalFile(absPath, format, specOptions) {
35457
+ const { readFile: readFile3 } = await import("node:fs/promises");
35458
+ const { bundleSubgraphCode } = await import("@secondlayer/bundler");
35459
+ const { generateSubgraphSQL } = await import("@secondlayer/subgraphs");
35460
+ const {
35461
+ generateSubgraphAgentSchema,
35462
+ generateSubgraphMarkdown,
35463
+ generateSubgraphOpenApi
35464
+ } = await import("@secondlayer/shared/subgraphs/spec");
35465
+ const source = await readFile3(absPath, "utf8");
35466
+ const bundled = await bundleSubgraphCode(source);
35467
+ const { hash } = generateSubgraphSQL({
35468
+ name: bundled.name,
35469
+ version: bundled.version,
35470
+ description: bundled.description,
35471
+ sources: bundled.sources,
35472
+ schema: bundled.schema,
35473
+ handlers: {}
35474
+ });
35475
+ const detail = createLocalSubgraphDetail({
35476
+ name: bundled.name,
35477
+ version: bundled.version,
35478
+ description: bundled.description,
35479
+ sources: bundled.sources,
35480
+ schema: bundled.schema,
35481
+ schemaHash: hash
35482
+ });
35483
+ return format === "openapi" ? generateSubgraphOpenApi(detail, specOptions) : format === "agent" ? generateSubgraphAgentSchema(detail, specOptions) : generateSubgraphMarkdown(detail, specOptions);
35484
+ }
35694
35485
  function createLocalSubgraphDetail(input3) {
35695
35486
  const tables = {};
35696
35487
  for (const [tableName, rawTable] of Object.entries(input3.schema)) {
@@ -35765,7 +35556,7 @@ function readCliSubgraphsDependency() {
35765
35556
  return "^1.3.2";
35766
35557
  }
35767
35558
  function ensureScaffoldPackageJson(dir) {
35768
- const packagePath = join8(dir, "package.json");
35559
+ const packagePath = join7(dir, "package.json");
35769
35560
  const subgraphsDep = readCliSubgraphsDependency();
35770
35561
  if (!existsSync4(packagePath)) {
35771
35562
  writeFileSync4(packagePath, `${JSON.stringify({
@@ -35883,7 +35674,10 @@ function formatSubgraphSync(sync) {
35883
35674
  }
35884
35675
  function registerSubgraphsCommand(program2) {
35885
35676
  const subgraphs = program2.command("subgraphs").description("Manage materialized subgraphs");
35886
- subgraphs.command("new <name>").description("Scaffold a new subgraph definition file").option("--template <slug>", `Foundation Dataset starter (one of: ${SUBGRAPH_TEMPLATE_SLUGS.join(", ")})`).action(async (name, opts) => {
35677
+ subgraphs.command("create <name>").description("Create a new subgraph definition file").option("--template <slug>", `Foundation Dataset starter (one of: ${SUBGRAPH_TEMPLATE_SLUGS.join(", ")})`).addHelpText("after", `
35678
+ Examples:
35679
+ $ sl subgraphs new my-graph
35680
+ $ sl subgraphs new token-balances --template sip-010-balances`).action(async (name, opts) => {
35887
35681
  const slug = opts.template ?? "basic";
35888
35682
  if (!SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
35889
35683
  error(`Unknown template "${opts.template}". Available templates:
@@ -35925,9 +35719,9 @@ ${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESC
35925
35719
  const def = mod.default ?? mod;
35926
35720
  const { validateSubgraphDefinition } = await import("@secondlayer/subgraphs/validate");
35927
35721
  const { deploySchema } = await import("@secondlayer/subgraphs");
35928
- const { getDb: getDb2 } = await import("@secondlayer/shared/db");
35722
+ const { getDb } = await import("@secondlayer/shared/db");
35929
35723
  validateSubgraphDefinition(def);
35930
- const db = getDb2();
35724
+ const db = getDb();
35931
35725
  const result = await deploySchema(db, def, absPath, {
35932
35726
  forceReindex: false
35933
35727
  });
@@ -35969,14 +35763,14 @@ Stopped watching.`);
35969
35763
  });
35970
35764
  await new Promise(() => {});
35971
35765
  });
35972
- subgraphs.command("deploy <file>").description("Deploy a subgraph definition file").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--dry-run", "Validate and preview deploy without writing changes").option("--preview", "Alias for --dry-run").option("--force", "Skip confirmation prompt for reindex operations").option("--database-url <url>", "BYO data plane: write the subgraph's schema/rows to your own Postgres. With --dry-run, prints the DDL + grant script and verifies the connection.").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").action(async (file, options2) => {
35766
+ subgraphs.command("deploy <file>").description("Deploy a subgraph definition file").option("--start-block <n>", "Override the subgraph definition startBlock for this deploy").option("--dry-run", "Validate and preview deploy without writing changes").option("-y, --yes", "Skip the reindex confirmation prompt").option("--database-url <url>", "BYO data plane: write the subgraph's schema/rows to your own Postgres. With --dry-run, prints the DDL + grant script and verifies the connection.").option("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").action(async (file, options2) => {
35973
35767
  try {
35974
35768
  const absPath = resolve2(file);
35975
35769
  const config = await loadConfig();
35976
35770
  if (config.network !== "local") {
35977
35771
  await requireAuth();
35978
35772
  }
35979
- const dryRun = options2.dryRun || options2.preview;
35773
+ const dryRun = options2.dryRun;
35980
35774
  const startBlock = parseStartBlockOption(options2.startBlock);
35981
35775
  if (startBlock !== undefined) {
35982
35776
  warn(`--start-block ${startBlock} overrides the definition's startBlock for this deploy.`);
@@ -36059,7 +35853,7 @@ Stopped watching.`);
36059
35853
  info(` + columns: ${t}.${cols.join(", ")}`);
36060
35854
  }
36061
35855
  }
36062
- const confirmed = options2.force || await confirm4({
35856
+ const confirmed = options2.yes || await confirm3({
36063
35857
  message: "⚠ This will drop all data and reindex from scratch. Continue?"
36064
35858
  });
36065
35859
  if (!confirmed) {
@@ -36093,8 +35887,8 @@ Stopped watching.`);
36093
35887
  return;
36094
35888
  }
36095
35889
  const { deploySchema } = await import("@secondlayer/subgraphs");
36096
- const { getDb: getDb2, closeDb } = await import("@secondlayer/shared/db");
36097
- const db = getDb2();
35890
+ const { getDb, closeDb } = await import("@secondlayer/shared/db");
35891
+ const db = getDb();
36098
35892
  const result = await deploySchema(db, effectiveDef, absPath, {
36099
35893
  version: undefined,
36100
35894
  forceReindex: startBlock !== undefined
@@ -36145,7 +35939,7 @@ ${data.length} subgraph(s) total`));
36145
35939
  handleApiError(err, "list subgraphs");
36146
35940
  }
36147
35941
  });
36148
- subgraphs.command("status <name>").description("Show detailed subgraph status").option("-w, --watch", "Refresh every 2s until synced or Ctrl-C").action(async (name, options2) => {
35942
+ subgraphs.command("status <name>").alias("get").description("Show detailed subgraph status").option("-w, --watch", "Refresh every 2s until synced or Ctrl-C").action(async (name, options2) => {
36149
35943
  const renderOnce = async () => {
36150
35944
  const subgraph = await getSubgraphApi(name);
36151
35945
  const rowCounts = Object.entries(subgraph.tables).map(([t, info2]) => `${t}: ${info2.rowCount}`).join(", ") || "N/A";
@@ -36210,64 +36004,24 @@ Synced — exiting watch.`));
36210
36004
  handleApiError(err, "get subgraph status");
36211
36005
  }
36212
36006
  });
36213
- subgraphs.command("spec <name>").description("Output API documentation for a deployed subgraph").option("--format <format>", "Output format: openapi, agent, markdown", "openapi").option("-o, --output <path>", "Write output to a file").option("--server <url>", "Override the server URL in generated docs").action(async (name, options2) => {
36007
+ subgraphs.command("spec <nameOrFile>").description("Output API documentation for a deployed subgraph or a local subgraph file").option("--format <format>", "Output format: openapi, agent, markdown", "openapi").option("-o, --output <path>", "Write output to a file").option("--server <url>", "Override the server URL in generated docs").action(async (nameOrFile, options2) => {
36214
36008
  try {
36215
36009
  const format = parseSubgraphSpecFormat(options2.format);
36216
36010
  const specOptions = options2.server ? { serverUrl: options2.server } : undefined;
36217
- const spec = format === "openapi" ? await getSubgraphOpenApi(name, specOptions) : format === "agent" ? await getSubgraphAgentSchema(name, specOptions) : await getSubgraphMarkdown(name, specOptions);
36218
- await writeOrPrintSubgraphSpec(spec, format, options2.output);
36219
- } catch (err) {
36220
- if (err instanceof Error && err.message.startsWith("--format")) {
36221
- error(err.message);
36222
- process.exit(1);
36223
- }
36224
- handleApiError(err, "generate subgraph spec");
36225
- }
36226
- });
36227
- subgraphs.command("inspect <file>").description("Output API documentation for a local subgraph file").option("--format <format>", "Output format: openapi, agent, markdown", "agent").option("-o, --output <path>", "Write output to a file").option("--server <url>", "Override the server URL in generated docs").action(async (file, options2) => {
36228
- try {
36229
- const format = parseSubgraphSpecFormat(options2.format);
36230
- const absPath = resolve2(file);
36231
- if (!existsSync4(absPath)) {
36011
+ const absPath = resolve2(nameOrFile);
36012
+ if (nameOrFile.endsWith(".ts") && !existsSync4(absPath)) {
36232
36013
  error(`File not found: ${absPath}`);
36233
36014
  process.exit(1);
36234
36015
  }
36235
- const { readFile: readFile3 } = await import("node:fs/promises");
36236
- const { bundleSubgraphCode } = await import("@secondlayer/bundler");
36237
- const { generateSubgraphSQL } = await import("@secondlayer/subgraphs");
36238
- const {
36239
- generateSubgraphAgentSchema,
36240
- generateSubgraphMarkdown,
36241
- generateSubgraphOpenApi
36242
- } = await import("@secondlayer/shared/subgraphs/spec");
36243
- const source = await readFile3(absPath, "utf8");
36244
- const bundled = await bundleSubgraphCode(source);
36245
- const { hash } = generateSubgraphSQL({
36246
- name: bundled.name,
36247
- version: bundled.version,
36248
- description: bundled.description,
36249
- sources: bundled.sources,
36250
- schema: bundled.schema,
36251
- handlers: {}
36252
- });
36253
- const detail = createLocalSubgraphDetail({
36254
- name: bundled.name,
36255
- version: bundled.version,
36256
- description: bundled.description,
36257
- sources: bundled.sources,
36258
- schema: bundled.schema,
36259
- schemaHash: hash
36260
- });
36261
- const specOptions = options2.server ? { serverUrl: options2.server } : undefined;
36262
- const spec = format === "openapi" ? generateSubgraphOpenApi(detail, specOptions) : format === "agent" ? generateSubgraphAgentSchema(detail, specOptions) : generateSubgraphMarkdown(detail, specOptions);
36016
+ const isLocalFile = nameOrFile.endsWith(".ts");
36017
+ const spec = isLocalFile ? await specFromLocalFile(absPath, format, specOptions) : format === "openapi" ? await getSubgraphOpenApi(nameOrFile, specOptions) : format === "agent" ? await getSubgraphAgentSchema(nameOrFile, specOptions) : await getSubgraphMarkdown(nameOrFile, specOptions);
36263
36018
  await writeOrPrintSubgraphSpec(spec, format, options2.output);
36264
36019
  } catch (err) {
36265
36020
  if (err instanceof Error && err.message.startsWith("--format")) {
36266
36021
  error(err.message);
36267
36022
  process.exit(1);
36268
36023
  }
36269
- error(`Failed to inspect subgraph: ${err}`);
36270
- process.exit(1);
36024
+ handleApiError(err, "generate subgraph spec");
36271
36025
  }
36272
36026
  });
36273
36027
  subgraphs.command("codegen <file>").description("Generate an ORM schema (Prisma or Drizzle) for a subgraph's tables — point it at your BYO database").option("--target <orm>", "ORM target: prisma | drizzle", "prisma").option("--schema <name>", "Postgres schema name (defaults to subgraph_<name>)").option("--env <var>", "datasource url env var", "DATABASE_URL").option("--models-only", "Emit only Prisma models (compose via prismaSchemaFolder)").option("-o, --output <path>", "Write to a file (defaults to stdout)").action(async (file, options2) => {
@@ -36312,20 +36066,25 @@ Synced — exiting watch.`));
36312
36066
  process.exit(1);
36313
36067
  }
36314
36068
  });
36315
- subgraphs.command("reindex <name>").description("Reindex a subgraph from historical blocks (drops + reprocesses)").option("--from <block>", "Start block height").option("--to <block>", "End block height").option("-y, --yes", "Skip confirmation").action(async (name, options2) => {
36069
+ subgraphs.command("reindex <name>").description("Reindex a subgraph from historical blocks (drops + reprocesses)").option("--from-block <n>", "Start block height").option("--to-block <n>", "End block height").option("-y, --yes", "Skip confirmation").addHelpText("after", `
36070
+ Examples:
36071
+ $ sl subgraphs reindex my-graph -y
36072
+ $ sl subgraphs reindex my-graph --from-block 150000 --to-block 160000 -y`).action(async (name, options2) => {
36316
36073
  try {
36317
- const fromBlock = options2.from ? Number.parseInt(options2.from, 10) : undefined;
36318
- const toBlock = options2.to ? Number.parseInt(options2.to, 10) : undefined;
36074
+ const fromRaw = options2.fromBlock;
36075
+ const toRaw = options2.toBlock;
36076
+ const fromBlock = fromRaw ? Number.parseInt(fromRaw, 10) : undefined;
36077
+ const toBlock = toRaw ? Number.parseInt(toRaw, 10) : undefined;
36319
36078
  if (!options2.yes) {
36320
36079
  if (!process.stdin.isTTY) {
36321
36080
  error("Interactive prompt unavailable (stdin is not a TTY). Re-run with -y to skip confirmation.");
36322
36081
  process.exit(1);
36323
36082
  }
36324
- const { confirm: confirm5 } = await import("@inquirer/prompts");
36083
+ const { confirm: confirm4 } = await import("@inquirer/prompts");
36325
36084
  const range = fromBlock !== undefined && toBlock !== undefined ? ` for blocks [${fromBlock}, ${toBlock}]` : fromBlock !== undefined ? ` from block ${fromBlock}` : toBlock !== undefined ? ` up to block ${toBlock}` : "";
36326
36085
  let ok = false;
36327
36086
  try {
36328
- ok = await confirm5({
36087
+ ok = await confirm4({
36329
36088
  message: `Reindex subgraph "${name}"${range}? Existing rows in this range will be dropped and reprocessed.`,
36330
36089
  default: false
36331
36090
  });
@@ -36353,23 +36112,34 @@ Synced — exiting watch.`));
36353
36112
  handleApiError(err, "reindex subgraph");
36354
36113
  }
36355
36114
  });
36356
- subgraphs.command("backfill <name>").description("Backfill a block range without dropping existing data").requiredOption("--from <block>", "Start block height").requiredOption("--to <block>", "End block height").action(async (name, options2) => {
36115
+ subgraphs.command("backfill <name>").description("Backfill a block range without dropping existing data").option("--from-block <n>", "Start block height").option("--to-block <n>", "End block height").addHelpText("after", `
36116
+ Examples:
36117
+ $ sl subgraphs backfill my-graph --from-block 150000 --to-block 160000`).action(async (name, options2) => {
36357
36118
  try {
36358
- const fromBlock = Number.parseInt(options2.from, 10);
36359
- const toBlock = Number.parseInt(options2.to, 10);
36119
+ const fromRaw = options2.fromBlock;
36120
+ const toRaw = options2.toBlock;
36121
+ if (!fromRaw || !toRaw) {
36122
+ error("--from-block and --to-block are required");
36123
+ process.exit(1);
36124
+ }
36125
+ const fromBlock = Number.parseInt(fromRaw, 10);
36126
+ const toBlock = Number.parseInt(toRaw, 10);
36360
36127
  if (Number.isNaN(fromBlock) || Number.isNaN(toBlock)) {
36361
- error("--from and --to must be valid block numbers");
36128
+ error("--from-block and --to-block must be valid block numbers");
36362
36129
  process.exit(1);
36363
36130
  }
36364
36131
  info(`Backfilling subgraph "${name}" from block ${fromBlock} to ${toBlock}...`);
36365
- const result = await backfillSubgraphApi(name, { fromBlock, toBlock });
36132
+ const result = await backfillSubgraphApi(name, {
36133
+ fromBlock,
36134
+ toBlock
36135
+ });
36366
36136
  success(result.message);
36367
36137
  info(`From block ${result.fromBlock} to ${result.toBlock}`);
36368
36138
  } catch (err) {
36369
36139
  handleApiError(err, "backfill subgraph");
36370
36140
  }
36371
36141
  });
36372
- subgraphs.command("stop <name>").description("Stop a running reindex or backfill operation").action(async (name) => {
36142
+ subgraphs.command("cancel <name>").description("Cancel a running reindex or backfill operation").action(async (name) => {
36373
36143
  try {
36374
36144
  info(`Stopping operation for subgraph "${name}"...`);
36375
36145
  const result = await stopSubgraphApi(name);
@@ -36407,7 +36177,11 @@ ${result.meta.total} gap(s), ${result.meta.totalMissingBlocks} total missing blo
36407
36177
  handleApiError(err, "get subgraph gaps");
36408
36178
  }
36409
36179
  });
36410
- subgraphs.command("query <name> <table>").description("Query a subgraph table").option("--sort <column>", "Sort by column").option("--order <dir>", "Sort direction (asc|desc)", "asc").option("--limit <n>", "Max rows to return", "20").option("--offset <n>", "Skip first N rows").option("--fields <cols>", "Comma-separated columns to include").option("--filter <kv...>", "Filter as key=value (supports .gte/.lte/.gt/.lt/.neq suffixes)").option("--count", "Return row count only").option("--json", "Output as JSON").action(async (name, table, options2) => {
36180
+ subgraphs.command("query <name> <table>").description("Query a subgraph table").option("--sort <column>", "Sort by column").option("--order <dir>", "Sort direction (asc|desc)", "asc").option("--limit <n>", "Max rows to return", "20").option("--offset <n>", "Skip first N rows").option("--fields <cols>", "Comma-separated columns to include").option("--filter <kv...>", "Filter as key=value (supports .gte/.lte/.gt/.lt/.neq suffixes)").option("--count", "Return row count only").option("--json", "Output as JSON").addHelpText("after", `
36181
+ Examples:
36182
+ $ sl subgraphs query my-graph balances --filter holder=SP2J6ZY... --limit 50
36183
+ $ sl subgraphs query my-graph transfers --filter amount.gte=1000 --sort _block_height --order desc
36184
+ $ sl subgraphs query my-graph balances --count`).action(async (name, table, options2) => {
36411
36185
  try {
36412
36186
  let filters;
36413
36187
  try {
@@ -36461,17 +36235,17 @@ ${rows.length} row(s)`));
36461
36235
  handleApiError(err, "query subgraph");
36462
36236
  }
36463
36237
  });
36464
- subgraphs.command("delete <name>").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").option("--force", "Cancel active operations and force delete").action(async (name, options2) => {
36238
+ subgraphs.command("delete <name>").alias("rm").description("Delete a subgraph and its data").option("-y, --yes", "Skip confirmation").option("--force", "Cancel active operations and force delete").action(async (name, options2) => {
36465
36239
  try {
36466
36240
  if (!options2.yes && !options2.force) {
36467
36241
  if (!process.stdin.isTTY) {
36468
36242
  error("Interactive prompt unavailable (stdin is not a TTY). Re-run with -y to skip confirmation.");
36469
36243
  process.exit(1);
36470
36244
  }
36471
- const { confirm: confirm5 } = await import("@inquirer/prompts");
36245
+ const { confirm: confirm4 } = await import("@inquirer/prompts");
36472
36246
  let ok = false;
36473
36247
  try {
36474
- ok = await confirm5({
36248
+ ok = await confirm4({
36475
36249
  message: `Delete subgraph "${name}" and all its data? This cannot be undone.`
36476
36250
  });
36477
36251
  } catch (promptErr) {
@@ -36505,7 +36279,11 @@ ${rows.length} row(s)`));
36505
36279
  handleApiError(err, "delete subgraph");
36506
36280
  }
36507
36281
  });
36508
- subgraphs.command("scaffold [contractAddress]").description("Scaffold a defineSubgraph() file. Detects SIP-010/009 → ft/nft source; --functions for typed call tables; --trait for a trait-scoped source (no contract)").option("-o, --output <path>", "Output file path (required)").option("--api-key <key>", "Stacks node API key for direct RPC URLs").option("--functions <names>", "Comma-separated public functions to index as typed contract_call tables").option("--trait <std>", "Scaffold a trait-scoped source (sip-009|sip-010|sip-013) — no contract needed").option("--no-install", "Skip bun install after writing package.json").action(async (contractAddress, options2) => {
36282
+ subgraphs.command("scaffold [contractAddress]").description("Scaffold a defineSubgraph() file from a contract or trait").option("-o, --output <path>", "Output file path (required)").option("-k, --api-key <key>", "Stacks node API key for direct RPC URLs").option("--functions <names>", "Comma-separated public functions to index as typed contract_call tables").option("--trait <std>", "Scaffold a trait-scoped source (sip-009|sip-010|sip-013) — no contract needed").option("--no-install", "Skip bun install after writing package.json").addHelpText("after", `
36283
+ Examples:
36284
+ $ sl subgraphs scaffold SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft -o subgraphs/apes.ts
36285
+ $ sl subgraphs scaffold SP00...token --functions transfer,mint -o subgraphs/token.ts
36286
+ $ sl subgraphs scaffold --trait sip-010 -o subgraphs/all-ft.ts`).action(async (contractAddress, options2) => {
36509
36287
  try {
36510
36288
  if (!options2.output) {
36511
36289
  error("--output <path> is required");
@@ -36564,7 +36342,7 @@ ${rows.length} row(s)`));
36564
36342
  process.exit(1);
36565
36343
  }
36566
36344
  });
36567
- subgraphs.command("client <subgraphName>").alias("generate").description("Generate a typed query client for a deployed subgraph").option("-o, --output <path>", "Output file path (required)").action(async (subgraphName, options2) => {
36345
+ subgraphs.command("client <subgraphName>").description("Generate a typed query client for a deployed subgraph").option("-o, --output <path>", "Output file path (required)").action(async (subgraphName, options2) => {
36568
36346
  try {
36569
36347
  if (!options2.output) {
36570
36348
  error("--output <path> is required");
@@ -36585,187 +36363,9 @@ ${rows.length} row(s)`));
36585
36363
  }
36586
36364
  });
36587
36365
  }
36588
- // src/commands/stack.ts
36589
- init_config();
36590
- init_dev_state();
36591
- init_docker();
36592
- init_network();
36593
- init_node_manager();
36594
- init_output();
36595
- function registerStackCommand(program2) {
36596
- const stack = program2.command("stack").description("Manage the full stack");
36597
- stack.command("start").description("Start the full stack (node + dev services)").option("--no-node", "Skip starting the Stacks node").option("--no-dev", "Skip starting dev services").option("--network <network>", "Override network (mainnet|testnet)").hook("preAction", async () => {
36598
- await requireLocalNetwork();
36599
- }).action(async (options2) => {
36600
- await stackStart(options2);
36601
- });
36602
- stack.command("stop").description("Stop the full stack").option("--no-node", "Skip stopping the Stacks node").option("--no-dev", "Skip stopping dev services").option("--wait", "Wait for in-flight work to drain before stopping").hook("preAction", async () => {
36603
- await requireLocalNetwork();
36604
- }).action(async (options2) => {
36605
- await stackStop(options2);
36606
- });
36607
- stack.command("restart").description("Restart the full stack").option("--no-node", "Skip restarting the Stacks node").option("--no-dev", "Skip restarting dev services").hook("preAction", async () => {
36608
- await requireLocalNetwork();
36609
- }).action(async (options2) => {
36610
- await stackStop({ ...options2, wait: false });
36611
- await stackStart(options2);
36612
- });
36613
- }
36614
- async function stackStart(options2) {
36615
- const config = await loadConfig();
36616
- try {
36617
- await requireDocker();
36618
- } catch (err) {
36619
- if (err instanceof DockerNotAvailableError) {
36620
- error(err.message);
36621
- process.exit(1);
36622
- }
36623
- throw err;
36624
- }
36625
- const network = options2.network ?? config.node?.network ?? "mainnet";
36626
- const validation = await validateNetworkConsistency(config);
36627
- if (!validation.valid) {
36628
- error("Network mismatch detected:");
36629
- for (const issue of validation.issues) {
36630
- console.log(red(` - ${issue}`));
36631
- }
36632
- console.log("");
36633
- console.log(dim("Fix your config or stop mismatched containers first."));
36634
- process.exit(1);
36635
- }
36636
- console.log("");
36637
- console.log(blue("Starting Secondlayer Stack"));
36638
- console.log(dim(` Network: ${network}`));
36639
- console.log("");
36640
- if (options2.node) {
36641
- const nodePath = config.node?.installPath;
36642
- if (!nodePath) {
36643
- warn("No node configured, skipping. Run 'sl local node setup' to configure.");
36644
- } else if (await isNodeRunning()) {
36645
- info("Node already running");
36646
- } else {
36647
- info("Starting Stacks node...");
36648
- const started = await startNodeContainers(nodePath, network);
36649
- if (!started) {
36650
- error("Failed to start node containers");
36651
- process.exit(1);
36652
- }
36653
- success("Node containers started");
36654
- info("Waiting for node RPC...");
36655
- let rpcReady = false;
36656
- for (let i = 0;i < 60; i++) {
36657
- try {
36658
- const res = await fetch("http://localhost:20443/v2/info", {
36659
- signal: AbortSignal.timeout(2000)
36660
- });
36661
- if (res.ok) {
36662
- rpcReady = true;
36663
- break;
36664
- }
36665
- } catch {}
36666
- await Bun.sleep(1000);
36667
- }
36668
- if (rpcReady) {
36669
- success("Node RPC responsive");
36670
- const postValidation = await validateNetworkConsistency(config);
36671
- if (!postValidation.valid) {
36672
- warn("Post-start chain ID mismatch:");
36673
- for (const issue of postValidation.issues) {
36674
- console.log(yellow(` - ${issue}`));
36675
- }
36676
- }
36677
- } else {
36678
- warn("Node RPC not responsive after 60s (may still be starting)");
36679
- }
36680
- }
36681
- console.log("");
36682
- }
36683
- if (options2.dev) {
36684
- if (await isDevRunning()) {
36685
- info("Dev services already running");
36686
- } else {
36687
- const args = [
36688
- "bun",
36689
- "run",
36690
- `${import.meta.dir}/../../bin/secondlayer.ts`,
36691
- "dev",
36692
- "start"
36693
- ];
36694
- if (config.node?.installPath) {
36695
- args.push("--stacks-node");
36696
- }
36697
- info("Starting dev services...");
36698
- const proc = Bun.spawn(args, {
36699
- stdin: "inherit",
36700
- stdout: "inherit",
36701
- stderr: "inherit"
36702
- });
36703
- await proc.exited;
36704
- }
36705
- }
36706
- console.log("");
36707
- success("Stack started");
36708
- console.log(dim("Run 'sl status' to check health"));
36709
- console.log("");
36710
- }
36711
- async function stackStop(options2) {
36712
- console.log("");
36713
- info("Stopping Secondlayer Stack...");
36714
- if (options2.dev) {
36715
- if (await isDevRunning()) {
36716
- info("Stopping dev services...");
36717
- const proc = Bun.spawn([
36718
- "bun",
36719
- "run",
36720
- `${import.meta.dir}/../../bin/secondlayer.ts`,
36721
- "dev",
36722
- "stop"
36723
- ], { stdin: "inherit", stdout: "inherit", stderr: "inherit" });
36724
- await proc.exited;
36725
- } else {
36726
- info("Dev services not running");
36727
- }
36728
- }
36729
- if (options2.node) {
36730
- if (await isNodeRunning()) {
36731
- info("Stopping node containers...");
36732
- const stopped = await stopNodeContainers();
36733
- if (stopped.length > 0) {
36734
- success(`Stopped: ${stopped.join(", ")}`);
36735
- }
36736
- } else {
36737
- info("Node not running");
36738
- }
36739
- }
36740
- try {
36741
- const result = await Bun.$`docker ps -a --format json --filter "name=secondlayer-dev" --filter "name=stacks"`.quiet().nothrow();
36742
- if (result.exitCode === 0) {
36743
- const lines = result.stdout.toString().trim().split(`
36744
- `).filter(Boolean);
36745
- const orphans = [];
36746
- for (const line of lines) {
36747
- try {
36748
- const c = JSON.parse(line);
36749
- const name = c.Names || c.Name;
36750
- if (name && c.Status?.includes("Exited")) {
36751
- orphans.push(name);
36752
- }
36753
- } catch {}
36754
- }
36755
- if (orphans.length > 0) {
36756
- info(`Cleaning up ${orphans.length} orphaned container(s)...`);
36757
- for (const name of orphans) {
36758
- await Bun.$`docker rm ${name}`.quiet().nothrow();
36759
- }
36760
- }
36761
- }
36762
- } catch {}
36763
- console.log("");
36764
- success("Stack stopped");
36765
- console.log("");
36766
- }
36767
36366
  // src/commands/streams.ts
36768
36367
  init_output();
36368
+ init_resolve_auth();
36769
36369
  import { createStreamsClient } from "@secondlayer/sdk";
36770
36370
  var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
36771
36371
  var VALID_TYPES = [
@@ -36782,9 +36382,9 @@ var VALID_TYPES = [
36782
36382
  "print"
36783
36383
  ];
36784
36384
  function readApiKey() {
36785
- const key = process.env.SL_STREAMS_API_KEY;
36385
+ const key = resolveEnvKey();
36786
36386
  if (!key) {
36787
- error("SL_STREAMS_API_KEY env var not set. Issue a key at https://www.secondlayer.tools/platform/api-keys (product: Streams).");
36387
+ error("No API key set. Export SL_API_KEY (issue one at https://www.secondlayer.tools/platform/api-keys).");
36788
36388
  process.exit(1);
36789
36389
  }
36790
36390
  return key;
@@ -36825,40 +36425,45 @@ function parseHeight(value, name) {
36825
36425
  return n;
36826
36426
  }
36827
36427
  function registerStreamsCommand(program2) {
36828
- const streams = program2.command("streams").description("Read raw chain events from Streams (requires SL_STREAMS_API_KEY)");
36428
+ const streams = program2.command("streams").description("Read raw chain events from Streams (requires SL_API_KEY)");
36829
36429
  streams.command("tip").description("Print current canonical tip").action(async () => {
36830
36430
  try {
36831
36431
  const tip = await client().tip();
36832
- process.stdout.write(`${JSON.stringify(tip, null, 2)}
36833
- `);
36432
+ writeData(JSON.stringify(tip, null, 2));
36834
36433
  } catch (err) {
36835
36434
  error(err instanceof Error ? err.message : String(err));
36836
36435
  process.exit(1);
36837
36436
  }
36838
36437
  });
36839
- streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-height <n>", "filter to blocks >= n").option("--to-height <n>", "filter to blocks <= n").option("--limit <n>", "page size (1-1000, default 100)", "100").action(async (options2) => {
36438
+ streams.command("events").description("List events (cursor-paginated; one page per call)").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--from-block <n>", "filter to blocks >= n").option("--to-block <n>", "filter to blocks <= n").option("--limit <n>", "page size (1-1000, default 100)", "100").addHelpText("after", `
36439
+ Examples:
36440
+ $ sl streams events --types stx_transfer,print --limit 50
36441
+ $ sl streams events --contract-id SP00....token --from-block 150000 --to-block 160000
36442
+ $ sl streams events --cursor 150000:3`).action(async (options2) => {
36840
36443
  try {
36841
36444
  const envelope = await client().events.list({
36842
36445
  types: parseTypes(options2.types),
36843
36446
  contractId: options2.contractId,
36844
36447
  cursor: options2.cursor,
36845
- fromHeight: parseHeight(options2.fromHeight, "--from-height"),
36846
- toHeight: parseHeight(options2.toHeight, "--to-height"),
36448
+ fromHeight: parseHeight(options2.fromBlock, "--from-block"),
36449
+ toHeight: parseHeight(options2.toBlock, "--to-block"),
36847
36450
  limit: parseLimit(options2.limit)
36848
36451
  });
36849
- process.stdout.write(`${JSON.stringify(envelope, null, 2)}
36850
- `);
36452
+ writeData(JSON.stringify(envelope, null, 2));
36851
36453
  } catch (err) {
36852
36454
  error(err instanceof Error ? err.message : String(err));
36853
36455
  process.exit(1);
36854
36456
  }
36855
36457
  });
36856
- streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--batch-size <n>", "events per batch (1-1000, default 100)", "100").option("--max-pages <n>", "stop after N pages (default: run until SIGINT)").action(async (options2) => {
36458
+ streams.command("consume").description("Long-running pull from a cursor; emits one event per line (jsonl) until SIGINT or --max-pages").option("--types <types>", `comma-separated event types (${VALID_TYPES.join(", ")})`).option("--contract-id <id>", "filter to a single contract identifier").option("--cursor <cursor>", "start cursor (block_height:event_index)").option("--batch-size <n>", "events per batch (1-1000, default 100)", "100").option("--max-pages <n>", "stop after N pages (default: run until SIGINT)").addHelpText("after", `
36459
+ Examples:
36460
+ $ sl streams consume --types print --cursor 150000:0
36461
+ $ sl streams consume --types stx_transfer --batch-size 500 --max-pages 10`).action(async (options2) => {
36857
36462
  try {
36858
36463
  const types6 = parseTypes(options2.types);
36859
36464
  const batchSize = parseLimit(options2.batchSize) ?? 100;
36860
36465
  const maxPages = options2.maxPages ? Number.parseInt(options2.maxPages, 10) : undefined;
36861
- info(dim("# streaming events to stdout (jsonl); next_cursor printed to stderr"));
36466
+ note("# streaming events to stdout (jsonl); next_cursor printed to stderr");
36862
36467
  await client().events.consume({
36863
36468
  fromCursor: options2.cursor,
36864
36469
  types: types6,
@@ -36889,8 +36494,7 @@ function registerStreamsCommand(program2) {
36889
36494
  since: options2.since,
36890
36495
  limit: parseLimit(options2.limit)
36891
36496
  });
36892
- process.stdout.write(`${JSON.stringify(envelope, null, 2)}
36893
- `);
36497
+ writeData(JSON.stringify(envelope, null, 2));
36894
36498
  } catch (err) {
36895
36499
  error(err instanceof Error ? err.message : String(err));
36896
36500
  process.exit(1);
@@ -36902,8 +36506,7 @@ function registerStreamsCommand(program2) {
36902
36506
  if (height === undefined)
36903
36507
  throw new Error("<height> is required");
36904
36508
  const block = await client().canonical(height);
36905
- process.stdout.write(`${JSON.stringify(block, null, 2)}
36906
- `);
36509
+ writeData(JSON.stringify(block, null, 2));
36907
36510
  } catch (err) {
36908
36511
  error(err instanceof Error ? err.message : String(err));
36909
36512
  process.exit(1);
@@ -36933,14 +36536,17 @@ function registerDatasetsCommand(program2) {
36933
36536
  datasets.command("list").description("List the dataset catalog + freshness").action(async () => {
36934
36537
  try {
36935
36538
  const catalog = await client2().listDatasets();
36936
- process.stdout.write(`${JSON.stringify(catalog, null, 2)}
36937
- `);
36539
+ writeData(JSON.stringify(catalog, null, 2));
36938
36540
  } catch (err) {
36939
36541
  error(`Failed to list datasets: ${err}`);
36940
36542
  process.exit(1);
36941
36543
  }
36942
36544
  });
36943
- datasets.command("query <dataset>").description(`Query a cursor-paginated dataset (${Object.keys(CURSOR_SLUGS).join(", ")})`).option("--filter <key=value...>", "Filter as key=value (e.g. --filter stacker=SP… --filter address=SP…)").option("--limit <n>", "Rows per page").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--json", "Print the full envelope as JSON").action(async (dataset, options2) => {
36545
+ datasets.command("query <dataset>").description(`Query a cursor-paginated dataset (${Object.keys(CURSOR_SLUGS).join(", ")})`).option("--filter <key=value...>", "Filter as key=value (e.g. --filter stacker=SP… --filter address=SP…)").option("--limit <n>", "Rows per page").option("--cursor <cursor>", "Resume token from a previous next_cursor").option("--json", "Print the full envelope as JSON").addHelpText("after", `
36546
+ Examples:
36547
+ $ sl datasets query stx-transfers --filter sender=SP2J6ZY... --limit 100
36548
+ $ sl datasets query sbtc-events --filter amount.gte=1000
36549
+ $ sl datasets query bns-events --cursor 150000:3 --json`).action(async (dataset, options2) => {
36944
36550
  try {
36945
36551
  const params = parseFilters(options2.filter);
36946
36552
  if (options2.limit)
@@ -36948,16 +36554,15 @@ function registerDatasetsCommand(program2) {
36948
36554
  if (options2.cursor)
36949
36555
  params.cursor = options2.cursor;
36950
36556
  const env = await client2().query(dataset, params);
36951
- if (options2.json) {
36952
- process.stdout.write(`${JSON.stringify(env, null, 2)}
36953
- `);
36954
- } else {
36955
- process.stdout.write(`${JSON.stringify(env.rows, null, 2)}
36956
- `);
36957
- if (env.next_cursor) {
36958
- info(`next_cursor: ${env.next_cursor}`);
36557
+ output({
36558
+ json: options2.json,
36559
+ data: env,
36560
+ human: () => {
36561
+ writeData(JSON.stringify(env.rows, null, 2));
36562
+ if (env.next_cursor)
36563
+ note(`next_cursor: ${env.next_cursor}`);
36959
36564
  }
36960
- }
36565
+ });
36961
36566
  } catch (err) {
36962
36567
  error(`Failed to query dataset: ${err}`);
36963
36568
  process.exit(1);
@@ -37315,6 +36920,532 @@ async function runLocalDoctor(jsonOutput) {
37315
36920
  }
37316
36921
  // src/commands/local.ts
37317
36922
  init_config();
36923
+
36924
+ // src/commands/db.ts
36925
+ init_config();
36926
+ init_dev_state();
36927
+ init_output();
36928
+ import { confirm as confirm4 } from "@inquirer/prompts";
36929
+ import { getDb, sql } from "@secondlayer/shared/db";
36930
+ import {
36931
+ countMissingBlocks,
36932
+ findGaps
36933
+ } from "@secondlayer/shared/db/queries/integrity";
36934
+ import { StacksNodeClient } from "@secondlayer/shared/node";
36935
+ var DEV_DATABASE_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
36936
+ function addDbCommand(parent) {
36937
+ const dbCmd = parent.command("db").description("Inspect indexer database tables").addHelpText("after", `
36938
+ Subcommands:
36939
+ blocks Show recent blocks
36940
+ txs Show recent transactions
36941
+ events Show recent events
36942
+ gaps Show gaps in indexed block data
36943
+ truncate Truncate all indexed data
36944
+ resync Reset database and restart indexer
36945
+
36946
+ Run \`sl db\` with no subcommand to print an overview.`).hook("preAction", async () => {
36947
+ await requireLocalNetwork();
36948
+ }).action(async () => {
36949
+ await showOverview(10);
36950
+ });
36951
+ dbCmd.command("blocks").description("Show recent blocks").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
36952
+ const opts = this.opts();
36953
+ await showBlocks(Number.parseInt(opts.limit), opts.json);
36954
+ });
36955
+ dbCmd.command("txs").description("Show recent transactions").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
36956
+ const opts = this.opts();
36957
+ await showTransactions(Number.parseInt(opts.limit), opts.json);
36958
+ });
36959
+ dbCmd.command("events").description("Show recent events").option("--limit <n>", "Number of rows", "10").option("--json", "Output as JSON").action(async function() {
36960
+ const opts = this.opts();
36961
+ await showEvents(Number.parseInt(opts.limit), opts.json);
36962
+ });
36963
+ dbCmd.command("gaps").description("Show gaps in indexed block data").option("--limit <n>", "Number of gaps to show", "50").option("--json", "Output as JSON").action(async function() {
36964
+ const opts = this.opts();
36965
+ await showGaps(Number.parseInt(opts.limit), opts.json);
36966
+ });
36967
+ dbCmd.command("truncate").description("Truncate all indexed data (blocks, txs, events)").option("-y, --yes", "Skip confirmation prompt").action(async function() {
36968
+ const opts = this.opts();
36969
+ await resetDatabase(opts.yes);
36970
+ });
36971
+ dbCmd.command("resync").description("Reset database and restart indexer for fresh sync").option("-y, --yes", "Skip confirmation prompt").option("--backfill", "After reset, fetch all blocks from node").action(async function() {
36972
+ const opts = this.opts();
36973
+ await resyncDatabase(opts.yes, opts.backfill);
36974
+ });
36975
+ }
36976
+ function ensureDb() {
36977
+ if (!process.env.DATABASE_URL) {
36978
+ process.env.DATABASE_URL = DEV_DATABASE_URL;
36979
+ }
36980
+ return getDb();
36981
+ }
36982
+ async function showOverview(_limit) {
36983
+ try {
36984
+ const db = ensureDb();
36985
+ const blockCountResult = await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst();
36986
+ const txCountResult = await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst();
36987
+ const eventCountResult = await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst();
36988
+ const blockCount = blockCountResult?.count ?? 0;
36989
+ const txCount = txCountResult?.count ?? 0;
36990
+ const eventCount = eventCountResult?.count ?? 0;
36991
+ const latest = await db.selectFrom("blocks").select(["height", "hash", "timestamp"]).orderBy("height", "desc").limit(1).executeTakeFirst();
36992
+ console.log("");
36993
+ console.log(blue("Database Overview"));
36994
+ console.log("");
36995
+ console.log(` Blocks: ${green(blockCount.toString())}`);
36996
+ console.log(` Transactions: ${green(txCount.toString())}`);
36997
+ console.log(` Events: ${green(eventCount.toString())}`);
36998
+ console.log("");
36999
+ if (latest) {
37000
+ const time = new Date(latest.timestamp * 1000).toISOString();
37001
+ console.log(blue("Latest Block"));
37002
+ console.log(` Height: ${latest.height}`);
37003
+ console.log(` Hash: ${dim(latest.hash.slice(0, 20))}...`);
37004
+ console.log(` Time: ${time}`);
37005
+ console.log("");
37006
+ }
37007
+ console.log(dim(`Use 'sl db blocks|txs|events' to see records`));
37008
+ console.log("");
37009
+ process.exit(0);
37010
+ } catch (err) {
37011
+ error(`Failed to query database: ${err}`);
37012
+ console.log(dim(`
37013
+ Make sure PostgreSQL is running.`));
37014
+ console.log(dim("Run 'sl local start' to start all services."));
37015
+ process.exit(1);
37016
+ }
37017
+ }
37018
+ async function showBlocks(limit, json) {
37019
+ try {
37020
+ const db = ensureDb();
37021
+ const rows = await db.selectFrom("blocks").select(["height", "hash", "timestamp", "canonical"]).orderBy("height", "desc").limit(limit).execute();
37022
+ if (json) {
37023
+ console.log(JSON.stringify(rows, null, 2));
37024
+ process.exit(0);
37025
+ }
37026
+ console.log("");
37027
+ console.log(blue(`Recent Blocks (${rows.length})`));
37028
+ console.log("");
37029
+ console.log(dim(" HEIGHT".padEnd(10)) + dim("HASH".padEnd(24)) + dim("TIME"));
37030
+ for (const row of rows) {
37031
+ const time = new Date(row.timestamp * 1000).toLocaleTimeString();
37032
+ const canonicalMark = row.canonical ? "" : yellow(" (reorg)");
37033
+ console.log(` ${row.height.toString().padEnd(10)}${`${row.hash.slice(0, 20)}... `.padEnd(24)}${time}${canonicalMark}`);
37034
+ }
37035
+ console.log("");
37036
+ process.exit(0);
37037
+ } catch (err) {
37038
+ error(`Failed to query blocks: ${err}`);
37039
+ process.exit(1);
37040
+ }
37041
+ }
37042
+ async function showTransactions(limit, json) {
37043
+ try {
37044
+ const db = ensureDb();
37045
+ const rows = await db.selectFrom("transactions").select([
37046
+ "tx_id",
37047
+ "block_height",
37048
+ "type",
37049
+ "sender",
37050
+ "status",
37051
+ "contract_id",
37052
+ "function_name"
37053
+ ]).orderBy("block_height", "desc").limit(limit).execute();
37054
+ if (json) {
37055
+ console.log(JSON.stringify(rows, null, 2));
37056
+ process.exit(0);
37057
+ }
37058
+ console.log("");
37059
+ console.log(blue(`Recent Transactions (${rows.length})`));
37060
+ console.log("");
37061
+ console.log(dim(" BLOCK".padEnd(8)) + dim("TYPE".padEnd(18)) + dim("SENDER".padEnd(20)) + dim("CONTRACT/FUNCTION"));
37062
+ for (const row of rows) {
37063
+ const statusColor = row.status === "success" ? green : yellow;
37064
+ const contractInfo = row.contract_id ? `${row.contract_id.split(".")[1] || row.contract_id}${row.function_name ? `::${row.function_name}` : ""}` : "-";
37065
+ console.log(` ${statusColor(row.block_height.toString().padEnd(8))}${row.type.padEnd(18)}${`${row.sender.slice(0, 18)}... `.padEnd(20)}${contractInfo}`);
37066
+ }
37067
+ console.log("");
37068
+ process.exit(0);
37069
+ } catch (err) {
37070
+ error(`Failed to query transactions: ${err}`);
37071
+ process.exit(1);
37072
+ }
37073
+ }
37074
+ async function showEvents(limit, json) {
37075
+ try {
37076
+ const db = ensureDb();
37077
+ const rows = await db.selectFrom("events").select(["block_height", "tx_id", "event_index", "type", "data"]).orderBy("block_height", "desc").limit(limit).execute();
37078
+ if (json) {
37079
+ console.log(JSON.stringify(rows, null, 2));
37080
+ process.exit(0);
37081
+ }
37082
+ console.log("");
37083
+ console.log(blue(`Recent Events (${rows.length})`));
37084
+ console.log("");
37085
+ if (rows.length === 0) {
37086
+ console.log(dim(" No events found"));
37087
+ console.log("");
37088
+ process.exit(0);
37089
+ }
37090
+ console.log(dim(" BLOCK".padEnd(8)) + dim("INDEX".padEnd(8)) + dim("TYPE".padEnd(24)) + dim("TX"));
37091
+ for (const row of rows) {
37092
+ console.log(` ${row.block_height.toString().padEnd(8)}` + `${row.event_index.toString().padEnd(8)}` + `${row.type.padEnd(24)}` + `${row.tx_id.slice(0, 16)}...`);
37093
+ }
37094
+ console.log("");
37095
+ process.exit(0);
37096
+ } catch (err) {
37097
+ error(`Failed to query events: ${err}`);
37098
+ process.exit(1);
37099
+ }
37100
+ }
37101
+ async function showGaps(limit, json) {
37102
+ try {
37103
+ const db = ensureDb();
37104
+ const gaps = await findGaps(db, limit);
37105
+ const missing = await countMissingBlocks(db);
37106
+ if (json) {
37107
+ console.log(JSON.stringify({ gaps, totalMissingBlocks: missing }, null, 2));
37108
+ process.exit(0);
37109
+ }
37110
+ console.log("");
37111
+ if (gaps.length === 0) {
37112
+ console.log(green("No gaps detected — block data is contiguous"));
37113
+ console.log("");
37114
+ process.exit(0);
37115
+ }
37116
+ console.log(blue(`Block Gaps (${gaps.length})`));
37117
+ console.log("");
37118
+ console.log(dim(" GAP_START".padEnd(14)) + dim("GAP_END".padEnd(14)) + dim("SIZE"));
37119
+ for (const gap of gaps) {
37120
+ console.log(` ${gap.gapStart.toString().padEnd(14)}` + `${gap.gapEnd.toString().padEnd(14)}` + `${gap.size}`);
37121
+ }
37122
+ console.log("");
37123
+ console.log(`${yellow(gaps.length.toString())} gaps, ${red(missing.toString())} missing blocks`);
37124
+ console.log("");
37125
+ process.exit(0);
37126
+ } catch (err) {
37127
+ error(`Failed to query gaps: ${err}`);
37128
+ process.exit(1);
37129
+ }
37130
+ }
37131
+ async function resetDatabase(skipConfirm) {
37132
+ try {
37133
+ const db = ensureDb();
37134
+ const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
37135
+ const txCount = (await db.selectFrom("transactions").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
37136
+ const eventCount = (await db.selectFrom("events").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
37137
+ console.log("");
37138
+ console.log(yellow("This will delete all indexed blockchain data:"));
37139
+ console.log("");
37140
+ console.log(` ${red(blockCount.toString())} blocks`);
37141
+ console.log(` ${red(txCount.toString())} transactions`);
37142
+ console.log(` ${red(eventCount.toString())} events`);
37143
+ console.log(` ${dim("+ index_progress")}`);
37144
+ console.log("");
37145
+ console.log(dim("Note: Subgraph configurations will be preserved."));
37146
+ console.log("");
37147
+ if (!skipConfirm) {
37148
+ const confirmed = await confirm4({
37149
+ message: "Are you sure you want to reset the database?",
37150
+ default: false
37151
+ });
37152
+ if (!confirmed) {
37153
+ info("Cancelled");
37154
+ process.exit(0);
37155
+ }
37156
+ }
37157
+ info("Truncating tables...");
37158
+ await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
37159
+ console.log("");
37160
+ success("Database reset complete");
37161
+ console.log("");
37162
+ console.log(dim("Run 'sl local restart' to restart the indexer for fresh sync."));
37163
+ console.log("");
37164
+ process.exit(0);
37165
+ } catch (err) {
37166
+ error(`Failed to reset database: ${err}`);
37167
+ process.exit(1);
37168
+ }
37169
+ }
37170
+ async function resyncDatabase(skipConfirm, backfill) {
37171
+ try {
37172
+ const db = ensureDb();
37173
+ const blockCount = (await db.selectFrom("blocks").select(sql`count(*)`.as("count")).executeTakeFirst())?.count ?? 0;
37174
+ console.log("");
37175
+ console.log(yellow("This will:"));
37176
+ console.log(` 1. Delete all indexed data (${red(blockCount.toString())} blocks)`);
37177
+ console.log(" 2. Restart the indexer for fresh sync");
37178
+ if (backfill) {
37179
+ console.log(" 3. Fetch all blocks from node (backfill)");
37180
+ }
37181
+ console.log("");
37182
+ console.log(dim("Note: Subgraph configurations will be preserved."));
37183
+ console.log("");
37184
+ if (!skipConfirm) {
37185
+ const confirmed = await confirm4({
37186
+ message: "Are you sure you want to resync?",
37187
+ default: false
37188
+ });
37189
+ if (!confirmed) {
37190
+ info("Cancelled");
37191
+ process.exit(0);
37192
+ }
37193
+ }
37194
+ info("Truncating tables...");
37195
+ await sql`TRUNCATE TABLE events, transactions, blocks, index_progress RESTART IDENTITY CASCADE`.execute(db);
37196
+ console.log(green(" ✓ Database reset"));
37197
+ const state = await loadDevState();
37198
+ if (state?.services?.indexer && isProcessRunning(state.services.indexer.pid)) {
37199
+ info("Restarting indexer...");
37200
+ try {
37201
+ process.kill(state.services.indexer.pid, "SIGTERM");
37202
+ await Bun.sleep(1000);
37203
+ } catch {}
37204
+ if (isProcessRunning(state.services.indexer.pid)) {
37205
+ try {
37206
+ process.kill(state.services.indexer.pid, "SIGKILL");
37207
+ } catch {}
37208
+ }
37209
+ console.log(green(" ✓ Indexer stopped"));
37210
+ console.log("");
37211
+ info("Run 'sl local restart' to start fresh sync");
37212
+ } else {
37213
+ console.log("");
37214
+ success("Database reset complete");
37215
+ console.log("");
37216
+ if (!backfill) {
37217
+ console.log(dim("Indexer not running. Start with 'sl local start' to begin sync."));
37218
+ }
37219
+ }
37220
+ if (backfill) {
37221
+ console.log("");
37222
+ info("Starting backfill from node...");
37223
+ const nodeClient = new StacksNodeClient;
37224
+ const healthy = await nodeClient.isHealthy();
37225
+ if (!healthy) {
37226
+ warn(`Cannot reach Stacks node at ${nodeClient.getRpcUrl()}`);
37227
+ console.log(dim("Run 'sl sync --from 1 --to <tip>' manually once the node is available."));
37228
+ console.log("");
37229
+ process.exit(0);
37230
+ }
37231
+ const nodeInfo = await nodeClient.getInfo();
37232
+ const tip = nodeInfo.stacks_tip_height;
37233
+ info(`Node tip: block ${tip}. Fetching blocks 1 to ${tip}...`);
37234
+ console.log(dim(`This may take a while. Run 'sl sync --from 1 --to ${tip}' if interrupted.`));
37235
+ console.log("");
37236
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
37237
+ const config = await loadConfig2();
37238
+ const indexerUrl = process.env.INDEXER_URL || `http://localhost:${config.ports.indexer}`;
37239
+ const concurrency = 5;
37240
+ let fetched = 0;
37241
+ let errors2 = 0;
37242
+ for (let i = 1;i <= tip; i += concurrency) {
37243
+ const batch = [];
37244
+ for (let j = i;j < i + concurrency && j <= tip; j++) {
37245
+ batch.push(j);
37246
+ }
37247
+ const results = await Promise.allSettled(batch.map(async (height) => {
37248
+ const block = await nodeClient.getBlock(height);
37249
+ if (!block)
37250
+ throw new Error(`Block ${height} not found`);
37251
+ const res = await fetch(`${indexerUrl}/new_block`, {
37252
+ method: "POST",
37253
+ headers: {
37254
+ "Content-Type": "application/json",
37255
+ "X-Source": "backfill"
37256
+ },
37257
+ body: JSON.stringify(block)
37258
+ });
37259
+ if (!res.ok)
37260
+ throw new Error(`Indexer rejected block ${height}: ${res.status}`);
37261
+ }));
37262
+ for (const r of results) {
37263
+ if (r.status === "fulfilled")
37264
+ fetched++;
37265
+ else
37266
+ errors2++;
37267
+ }
37268
+ const pct = Math.round((fetched + errors2) / tip * 100);
37269
+ process.stdout.write(`\r ${green(`${fetched}`)} fetched, ${errors2 > 0 ? red(`${errors2} errors`) : "0 errors"} (${pct}%)`);
37270
+ }
37271
+ console.log("");
37272
+ console.log("");
37273
+ if (errors2 === 0) {
37274
+ success(`Backfill complete: ${fetched} blocks indexed`);
37275
+ } else {
37276
+ warn(`Backfill complete: ${fetched} indexed, ${errors2} errors`);
37277
+ }
37278
+ }
37279
+ console.log("");
37280
+ process.exit(0);
37281
+ } catch (err) {
37282
+ error(`Failed to resync: ${err}`);
37283
+ process.exit(1);
37284
+ }
37285
+ }
37286
+
37287
+ // src/commands/stack.ts
37288
+ init_config();
37289
+ init_dev_state();
37290
+ init_docker();
37291
+ init_network();
37292
+ init_node_manager();
37293
+ init_output();
37294
+ async function stackStart(options2) {
37295
+ const config = await loadConfig();
37296
+ try {
37297
+ await requireDocker();
37298
+ } catch (err) {
37299
+ if (err instanceof DockerNotAvailableError) {
37300
+ error(err.message);
37301
+ process.exit(1);
37302
+ }
37303
+ throw err;
37304
+ }
37305
+ const network = process.env.STACKS_NETWORK ?? config.node?.network ?? "mainnet";
37306
+ const validation = await validateNetworkConsistency(config);
37307
+ if (!validation.valid) {
37308
+ error("Network mismatch detected:");
37309
+ for (const issue of validation.issues) {
37310
+ console.log(red(` - ${issue}`));
37311
+ }
37312
+ console.log("");
37313
+ console.log(dim("Fix your config or stop mismatched containers first."));
37314
+ process.exit(1);
37315
+ }
37316
+ console.log("");
37317
+ console.log(blue("Starting Secondlayer Stack"));
37318
+ console.log(dim(` Network: ${network}`));
37319
+ console.log("");
37320
+ if (options2.node) {
37321
+ const nodePath = config.node?.installPath;
37322
+ if (!nodePath) {
37323
+ warn("No node configured, skipping. Run 'sl local node setup' to configure.");
37324
+ } else if (await isNodeRunning()) {
37325
+ info("Node already running");
37326
+ } else {
37327
+ info("Starting Stacks node...");
37328
+ const started = await startNodeContainers(nodePath, network);
37329
+ if (!started) {
37330
+ error("Failed to start node containers");
37331
+ process.exit(1);
37332
+ }
37333
+ success("Node containers started");
37334
+ info("Waiting for node RPC...");
37335
+ let rpcReady = false;
37336
+ for (let i = 0;i < 60; i++) {
37337
+ try {
37338
+ const res = await fetch("http://localhost:20443/v2/info", {
37339
+ signal: AbortSignal.timeout(2000)
37340
+ });
37341
+ if (res.ok) {
37342
+ rpcReady = true;
37343
+ break;
37344
+ }
37345
+ } catch {}
37346
+ await Bun.sleep(1000);
37347
+ }
37348
+ if (rpcReady) {
37349
+ success("Node RPC responsive");
37350
+ const postValidation = await validateNetworkConsistency(config);
37351
+ if (!postValidation.valid) {
37352
+ warn("Post-start chain ID mismatch:");
37353
+ for (const issue of postValidation.issues) {
37354
+ console.log(yellow(` - ${issue}`));
37355
+ }
37356
+ }
37357
+ } else {
37358
+ warn("Node RPC not responsive after 60s (may still be starting)");
37359
+ }
37360
+ }
37361
+ console.log("");
37362
+ }
37363
+ if (options2.dev) {
37364
+ if (await isDevRunning()) {
37365
+ info("Dev services already running");
37366
+ } else {
37367
+ const args = [
37368
+ "bun",
37369
+ "run",
37370
+ `${import.meta.dir}/../../bin/secondlayer.ts`,
37371
+ "dev",
37372
+ "start"
37373
+ ];
37374
+ if (config.node?.installPath) {
37375
+ args.push("--stacks-node");
37376
+ }
37377
+ info("Starting dev services...");
37378
+ const proc = Bun.spawn(args, {
37379
+ stdin: "inherit",
37380
+ stdout: "inherit",
37381
+ stderr: "inherit"
37382
+ });
37383
+ await proc.exited;
37384
+ }
37385
+ }
37386
+ console.log("");
37387
+ success("Stack started");
37388
+ console.log(dim("Run 'sl status' to check health"));
37389
+ console.log("");
37390
+ }
37391
+ async function stackStop(options2) {
37392
+ console.log("");
37393
+ info("Stopping Secondlayer Stack...");
37394
+ if (options2.dev) {
37395
+ if (await isDevRunning()) {
37396
+ info("Stopping dev services...");
37397
+ const proc = Bun.spawn([
37398
+ "bun",
37399
+ "run",
37400
+ `${import.meta.dir}/../../bin/secondlayer.ts`,
37401
+ "dev",
37402
+ "stop"
37403
+ ], { stdin: "inherit", stdout: "inherit", stderr: "inherit" });
37404
+ await proc.exited;
37405
+ } else {
37406
+ info("Dev services not running");
37407
+ }
37408
+ }
37409
+ if (options2.node) {
37410
+ if (await isNodeRunning()) {
37411
+ info("Stopping node containers...");
37412
+ const stopped = await stopNodeContainers();
37413
+ if (stopped.length > 0) {
37414
+ success(`Stopped: ${stopped.join(", ")}`);
37415
+ }
37416
+ } else {
37417
+ info("Node not running");
37418
+ }
37419
+ }
37420
+ try {
37421
+ const result = await Bun.$`docker ps -a --format json --filter "name=secondlayer-dev" --filter "name=stacks"`.quiet().nothrow();
37422
+ if (result.exitCode === 0) {
37423
+ const lines = result.stdout.toString().trim().split(`
37424
+ `).filter(Boolean);
37425
+ const orphans = [];
37426
+ for (const line of lines) {
37427
+ try {
37428
+ const c = JSON.parse(line);
37429
+ const name = c.Names || c.Name;
37430
+ if (name && c.Status?.includes("Exited")) {
37431
+ orphans.push(name);
37432
+ }
37433
+ } catch {}
37434
+ }
37435
+ if (orphans.length > 0) {
37436
+ info(`Cleaning up ${orphans.length} orphaned container(s)...`);
37437
+ for (const name of orphans) {
37438
+ await Bun.$`docker rm ${name}`.quiet().nothrow();
37439
+ }
37440
+ }
37441
+ }
37442
+ } catch {}
37443
+ console.log("");
37444
+ success("Stack stopped");
37445
+ console.log("");
37446
+ }
37447
+
37448
+ // src/commands/local.ts
37318
37449
  init_dev_state();
37319
37450
  init_node_manager();
37320
37451
  init_output();
@@ -37325,7 +37456,7 @@ function registerLocalCommand(program2) {
37325
37456
  return;
37326
37457
  await requireLocalNetwork();
37327
37458
  });
37328
- local.command("start").description("Start all local dev services (API, indexer, worker)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--no-worker", "Skip worker service").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("-f, --foreground", "Run in foreground (blocking)").action(async (options2) => {
37459
+ local.command("start").description("Start all local dev services (API, indexer, worker)").option("--indexer-port <port>", "Indexer port", "3700").option("--api-port <port>", "API port", "3800").option("--no-worker", "Skip worker service").option("--stacks-node", "Use port 3701 for indexer (avoids conflict with stacks-blockchain-api)").option("--foreground", "Run in foreground (blocking)").action(async (options2) => {
37329
37460
  const { runBackground: runBackground2, runForeground: runForeground2, isDevAlreadyRunning: isDevAlreadyRunning2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
37330
37461
  if (await isDevAlreadyRunning2()) {
37331
37462
  return;
@@ -37344,12 +37475,36 @@ function registerLocalCommand(program2) {
37344
37475
  const { restartDev: restartDev2 } = await Promise.resolve().then(() => (init_dev_impl(), exports_dev_impl));
37345
37476
  await restartDev2();
37346
37477
  });
37478
+ local.command("up").description("Start the full local stack (Stacks node + dev services)").option("--devnet", "Run against a local Clarinet devnet instead").option("--no-node", "Skip starting the Stacks node").option("--no-dev", "Skip starting dev services").option("--project <dir>", "[--devnet] Clarinet project directory").option("--image-tag <tag>", "[--devnet] Published image tag to run").option("--owner <owner>", "[--devnet] ghcr image owner to pull from").option("--no-up", "[--devnet] Patch config + write compose without starting").action(async (options2) => {
37479
+ if (options2.devnet) {
37480
+ await connect({
37481
+ project: options2.project,
37482
+ imageTag: options2.imageTag ?? DEFAULT_IMAGE_TAG,
37483
+ owner: options2.owner,
37484
+ up: options2.up
37485
+ });
37486
+ } else {
37487
+ await stackStart({ node: options2.node, dev: options2.dev });
37488
+ }
37489
+ });
37490
+ local.command("down").description("Stop the full local stack").option("--devnet", "Stop a local Clarinet devnet instead").option("--no-node", "Skip stopping the Stacks node").option("--no-dev", "Skip stopping dev services").option("--wait", "Wait for in-flight work to drain before stopping").option("--project <dir>", "[--devnet] Clarinet project directory").option("--purge", "[--devnet] Also remove volumes (wipes the local index)").action(async (options2) => {
37491
+ if (options2.devnet) {
37492
+ await down({ project: options2.project, purge: options2.purge });
37493
+ } else {
37494
+ await stackStop({
37495
+ node: options2.node,
37496
+ dev: options2.dev,
37497
+ wait: options2.wait
37498
+ });
37499
+ }
37500
+ });
37347
37501
  local.command("status").description("Show local environment status").action(async () => {
37348
37502
  await showLocalStatus();
37349
37503
  });
37350
37504
  local.command("logs").description("View local service logs (dev + node)").option("-s, --service <name>", "Filter by service (api, indexer, worker, subgraphs, node)").option("-f, --follow", "Follow log output").option("-n, --lines <n>", "Number of lines to show", "50").option("-q, --quiet", "Filter out common noise").action(async (options2) => {
37351
37505
  await showLocalLogs(options2);
37352
37506
  });
37507
+ addDbCommand(local);
37353
37508
  const node = local.command("node").description("Manage local Stacks node");
37354
37509
  node.command("setup").description("Interactive setup wizard for Stacks node").action(async () => {
37355
37510
  const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
@@ -37359,13 +37514,13 @@ function registerLocalCommand(program2) {
37359
37514
  const { startNode: startNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
37360
37515
  await startNode2(options2.path, options2.withIndexer);
37361
37516
  });
37362
- node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "Wait for in-flight work to drain first").action(async (options2) => {
37517
+ node.command("stop").description("Stop the Stacks node").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-y, --yes", "Skip confirmation").option("--wait", "Wait for in-flight work to drain first").action(async (options2) => {
37363
37518
  const { stopNode: stopNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
37364
- await stopNode2(options2.path, options2.force, options2.wait);
37519
+ await stopNode2(options2.path, options2.yes, options2.wait);
37365
37520
  });
37366
- node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-f, --force", "Skip confirmation").option("--wait", "Wait for in-flight work to drain before stopping").action(async (options2) => {
37521
+ node.command("restart").description("Restart the Stacks node (stop then start)").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("-y, --yes", "Skip confirmation").option("--wait", "Wait for in-flight work to drain before stopping").action(async (options2) => {
37367
37522
  const { restartNode: restartNode2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
37368
- await restartNode2(options2.path, options2.force, options2.wait);
37523
+ await restartNode2(options2.path, options2.yes, options2.wait);
37369
37524
  });
37370
37525
  node.command("status").description("Show Stacks node status").option("-p, --path <path>", "Path to stacks-blockchain-docker (overrides config)").option("--json", "Output as JSON").action(async (options2) => {
37371
37526
  const { showStatus: showStatus2 } = await Promise.resolve().then(() => (init_node_impl(), exports_node_impl));
@@ -37639,19 +37794,19 @@ async function writeActiveProject(slug, cwd) {
37639
37794
  }
37640
37795
 
37641
37796
  // src/commands/whoami.ts
37642
- init_session();
37797
+ init_resolve_auth();
37643
37798
  function registerWhoamiCommand(program2) {
37644
- program2.command("whoami").description("Show current authenticated account + active project").action(async () => {
37645
- const session = await readSession();
37646
- if (!session) {
37799
+ program2.command("whoami").description("Show the active account, credential source, and project").option("--json", "Output as JSON").action(async (options2) => {
37800
+ let auth;
37801
+ try {
37802
+ auth = await resolveAuth();
37803
+ } catch {
37647
37804
  error("Not logged in. Run: sl login");
37648
- process.exit(0);
37805
+ process.exit(1);
37649
37806
  }
37650
- const rows = [];
37651
- rows.push(["Email", session.email]);
37807
+ let account;
37652
37808
  try {
37653
- const account = await httpPlatform("/api/accounts/me");
37654
- rows.push(["Plan", account.plan]);
37809
+ account = await httpPlatform("/api/accounts/me");
37655
37810
  } catch (err) {
37656
37811
  if (err instanceof CliHttpError && err.code === "SESSION_EXPIRED") {
37657
37812
  error("Session expired. Run: sl login");
@@ -37661,13 +37816,34 @@ function registerWhoamiCommand(program2) {
37661
37816
  }
37662
37817
  const config = await loadConfig();
37663
37818
  const active = await readActiveProject(process.cwd(), config.defaultProject);
37664
- if (active) {
37665
- rows.push(["Project", active.slug]);
37666
- rows.push(["Project source", dim(active.resolvedFrom)]);
37667
- } else {
37668
- rows.push(["Project", dim("(none — run `sl project create <name>`)")]);
37669
- }
37670
- console.log(formatKeyValue(rows));
37819
+ const authSource = auth.fromEnv ? "API key (env)" : "session";
37820
+ output({
37821
+ json: options2.json,
37822
+ data: {
37823
+ email: account.email,
37824
+ plan: account.plan,
37825
+ apiUrl: auth.apiUrl,
37826
+ authSource,
37827
+ project: active ? { slug: active.slug, source: active.resolvedFrom } : null
37828
+ },
37829
+ human: () => {
37830
+ const rows = [];
37831
+ rows.push(["Email", account.email]);
37832
+ rows.push(["Plan", account.plan]);
37833
+ rows.push(["API URL", auth.apiUrl]);
37834
+ rows.push(["Auth", dim(authSource)]);
37835
+ if (active) {
37836
+ rows.push(["Project", active.slug]);
37837
+ rows.push(["Project source", dim(active.resolvedFrom)]);
37838
+ } else {
37839
+ rows.push([
37840
+ "Project",
37841
+ dim("(none — run `sl project create <name>`)")
37842
+ ]);
37843
+ }
37844
+ console.log(formatKeyValue(rows));
37845
+ }
37846
+ });
37671
37847
  });
37672
37848
  }
37673
37849
  // src/commands/logout.ts
@@ -37696,7 +37872,7 @@ init_config();
37696
37872
  import { input as input4 } from "@inquirer/prompts";
37697
37873
  init_output();
37698
37874
  function registerProjectCommand(program2) {
37699
- const project = program2.command("project").description("Manage Secondlayer projects");
37875
+ const project = program2.command("projects").alias("project").description("Manage Secondlayer projects");
37700
37876
  project.command("create [name]").description("Create a new project").option("--slug <slug>", "Project URL identifier").action(async (nameArg, options2 = {}) => {
37701
37877
  const name = nameArg ?? await input4({
37702
37878
  message: "Project name",
@@ -37726,24 +37902,30 @@ function registerProjectCommand(program2) {
37726
37902
  handleProjectError(err);
37727
37903
  }
37728
37904
  });
37729
- project.command("list").description("List projects in your account").action(async () => {
37905
+ project.command("list").alias("ls").description("List projects in your account").option("--json", "Output as JSON").action(async (options2) => {
37730
37906
  try {
37731
37907
  const res = await httpPlatform("/api/projects");
37732
- if (res.projects.length === 0) {
37733
- info("No projects yet — run `sl project create <name>` to start.");
37734
- return;
37735
- }
37736
37908
  const active = await readActiveProject(process.cwd(), (await loadConfig()).defaultProject);
37737
- const rows = res.projects.map((p) => [
37738
- p.slug === active?.slug ? `* ${p.slug}` : ` ${p.slug}`,
37739
- p.name,
37740
- p.network,
37741
- new Date(p.createdAt).toLocaleDateString()
37742
- ]);
37743
- console.log(formatTable(["", "Name", "Network", "Created"], rows));
37744
- if (active) {
37745
- console.log(dim(`Active: ${active.slug} (from ${active.resolvedFrom})`));
37746
- }
37909
+ output({
37910
+ json: options2.json,
37911
+ data: { projects: res.projects, active: active?.slug ?? null },
37912
+ human: () => {
37913
+ if (res.projects.length === 0) {
37914
+ info("No projects yet — run `sl project create <name>` to start.");
37915
+ return;
37916
+ }
37917
+ const rows = res.projects.map((p) => [
37918
+ p.slug === active?.slug ? `* ${p.slug}` : ` ${p.slug}`,
37919
+ p.name,
37920
+ p.network,
37921
+ new Date(p.createdAt).toLocaleDateString()
37922
+ ]);
37923
+ console.log(formatTable(["", "Name", "Network", "Created"], rows));
37924
+ if (active) {
37925
+ console.log(dim(`Active: ${active.slug} (from ${active.resolvedFrom})`));
37926
+ }
37927
+ }
37928
+ });
37747
37929
  } catch (err) {
37748
37930
  handleProjectError(err);
37749
37931
  }
@@ -37763,16 +37945,22 @@ function registerProjectCommand(program2) {
37763
37945
  info(dim(`Written to ${path2}`));
37764
37946
  info(dim("Tip: add `.secondlayer/` to .gitignore — it's account-personal."));
37765
37947
  });
37766
- project.command("current").description("Show the active project for this directory").action(async () => {
37948
+ project.command("get").description("Show the active project for this directory").option("--json", "Output as JSON").action(async (options2) => {
37767
37949
  const config = await loadConfig();
37768
37950
  const active = await readActiveProject(process.cwd(), config.defaultProject);
37769
- if (!active) {
37770
- info("No active project.");
37771
- info(dim("Run 'sl project create <name>' or 'sl project use <slug>'."));
37772
- return;
37773
- }
37774
- console.log(active.slug);
37775
- console.log(dim(`(from ${active.resolvedFrom})`));
37951
+ output({
37952
+ json: options2.json,
37953
+ data: active ? { slug: active.slug, source: active.resolvedFrom } : null,
37954
+ human: () => {
37955
+ if (!active) {
37956
+ info("No active project.");
37957
+ info(dim("Run 'sl project create <name>' or 'sl project use <slug>'."));
37958
+ return;
37959
+ }
37960
+ console.log(active.slug);
37961
+ console.log(dim(`(from ${active.resolvedFrom})`));
37962
+ }
37963
+ });
37776
37964
  });
37777
37965
  }
37778
37966
  function handleProjectError(err) {
@@ -37801,23 +37989,24 @@ function validateProjectSlug(slug) {
37801
37989
  }
37802
37990
  // src/cli.ts
37803
37991
  var { version } = package_default;
37804
- program.name("secondlayer").alias("sl").description("SecondLayer CLI — dedicated Stacks indexing + real-time subgraphs").version(version).option("--network <network>", "Override network (local, testnet, mainnet)");
37992
+ program.name("secondlayer").alias("sl").description("SecondLayer CLI — dedicated Stacks indexing + real-time subgraphs").version(version).option("--network <network>", "Override network (local, testnet, mainnet)").option("--api-key <key>", "API credential (overrides SL_API_KEY)").option("--api-url <url>", "API endpoint (overrides SL_API_URL)").showSuggestionAfterError(true).showHelpAfterError("(run `sl --help` to see available commands)");
37805
37993
  program.hook("preAction", (thisCommand) => {
37806
- const net3 = thisCommand.opts().network;
37807
- if (net3)
37808
- process.env.STACKS_NETWORK = net3;
37994
+ const { network, apiKey, apiUrl } = thisCommand.opts();
37995
+ if (network)
37996
+ process.env.STACKS_NETWORK = network;
37997
+ if (apiKey)
37998
+ process.env.SL_API_KEY = apiKey;
37999
+ if (apiUrl)
38000
+ process.env.SL_API_URL = apiUrl;
37809
38001
  });
37810
38002
  program.addHelpText("after", `
37811
38003
  Quickstart:
37812
38004
  $ sl login # Authenticate (magic-link email)
37813
- $ sl subgraphs new my-watcher --template sip-010-balances
38005
+ $ sl subgraphs create my-watcher --template sip-010-balances
37814
38006
  $ sl subgraphs deploy subgraphs/my-watcher.ts
37815
38007
  $ sl subgraphs status my-watcher
37816
38008
  `);
37817
- program.command("generate [files...]").aliases(["gen"]).description("Generate TypeScript interfaces from Clarity contracts").option("-c, --config <path>", "Path to config file").option("-o, --out <path>", "Output file path (required when using direct files)").option("-k, --api-key <key>", "Stacks node API key for direct RPC URLs").option("-w, --watch", "Watch for changes").action(async (files, options3) => {
37818
- const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
37819
- await generate2(files, options3);
37820
- });
38009
+ program.commandsGroup("Getting started:");
37821
38010
  program.command("init").description("Initialize a new secondlayer.config.ts file").action(async () => {
37822
38011
  const { init: init3 } = await Promise.resolve().then(() => (init_init(), exports_init));
37823
38012
  await init3();
@@ -37825,22 +38014,34 @@ program.command("init").description("Initialize a new secondlayer.config.ts file
37825
38014
  registerLoginCommand(program);
37826
38015
  registerLogoutCommand(program);
37827
38016
  registerWhoamiCommand(program);
37828
- registerProjectCommand(program);
38017
+ program.commandsGroup("Data products:");
37829
38018
  registerSubgraphsCommand(program);
37830
- registerCreateCommand(program);
37831
38019
  registerSubscriptionsCommand(program);
37832
38020
  registerStreamsCommand(program);
37833
38021
  registerDatasetsCommand(program);
38022
+ program.commandsGroup("Project & codegen:");
38023
+ registerProjectCommand(program);
38024
+ var configureGenerate = (cmd) => cmd.option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path (required when using direct files)").option("-k, --api-key <key>", "Stacks node API key for direct RPC URLs").option("-w, --watch", "Watch for changes").action(async (files, options3) => {
38025
+ options3.out = options3.output;
38026
+ const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
38027
+ await generate2(files, options3);
38028
+ });
38029
+ var contracts = program.command("contracts").description("Work with Clarity contracts");
38030
+ configureGenerate(contracts.command("generate [files...]").aliases(["gen"]).description("Generate TypeScript interfaces from Clarity contracts")).addHelpText("after", `
38031
+ Examples:
38032
+ $ sl contracts generate
38033
+ $ sl contracts generate ./contracts/pool.clar -o ./src/generated.ts
38034
+ $ sl contracts generate --config secondlayer.config.ts --watch`);
38035
+ program.commandsGroup("Local development:");
38036
+ registerLocalCommand(program);
38037
+ registerDevnetCommand(program);
38038
+ program.commandsGroup("Diagnostics:");
37834
38039
  registerStatusCommand(program);
37835
- registerStackCommand(program);
37836
- registerDbCommand(program);
37837
38040
  registerDoctorCommand(program);
37838
38041
  registerConfigCommand(program);
37839
- registerLocalCommand(program);
37840
- registerDevnetCommand(program);
38042
+ program.commandsGroup("Account:");
37841
38043
  registerAccountCommand(program);
37842
- registerBillingCommand(program);
37843
38044
  program.parse();
37844
38045
 
37845
- //# debugId=7F4D9295EECF14D064756E2164756E21
38046
+ //# debugId=E63D3732E427AF4164756E2164756E21
37846
38047
  //# sourceMappingURL=cli.js.map