@secondlayer/cli 5.7.0 → 5.8.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
@@ -15419,8 +15419,8 @@ var require_to_regex_range = __commonJS((exports, module) => {
15419
15419
  let relax = String(opts.relaxZeros);
15420
15420
  let shorthand = String(opts.shorthand);
15421
15421
  let capture = String(opts.capture);
15422
- let wrap = String(opts.wrap);
15423
- let cacheKey = min + ":" + max + "=" + relax + shorthand + capture + wrap;
15422
+ let wrap2 = String(opts.wrap);
15423
+ let cacheKey = min + ":" + max + "=" + relax + shorthand + capture + wrap2;
15424
15424
  if (toRegexRange.cache.hasOwnProperty(cacheKey)) {
15425
15425
  return toRegexRange.cache[cacheKey].result;
15426
15426
  }
@@ -15700,9 +15700,9 @@ var require_fill_range = __commonJS((exports, module) => {
15700
15700
  };
15701
15701
  var toRegex = (start, end, options2) => {
15702
15702
  if (Array.isArray(start)) {
15703
- let wrap = options2.wrap === true;
15703
+ let wrap2 = options2.wrap === true;
15704
15704
  let prefix = options2.capture ? "" : "?:";
15705
- return wrap ? `(${prefix}${start.join("|")})` : start.join("|");
15705
+ return wrap2 ? `(${prefix}${start.join("|")})` : start.join("|");
15706
15706
  }
15707
15707
  return toRegexRange(start, end, options2);
15708
15708
  };
@@ -22353,9 +22353,9 @@ function requireLines() {
22353
22353
  }
22354
22354
  function requireWrap() {
22355
22355
  if (hasRequiredWrap)
22356
- return wrap;
22356
+ return wrap2;
22357
22357
  hasRequiredWrap = 1;
22358
- wrap = (msg, opts = {}) => {
22358
+ wrap2 = (msg, opts = {}) => {
22359
22359
  const tab = Number.isSafeInteger(parseInt(opts.margin)) ? new Array(parseInt(opts.margin)).fill(" ").join("") : opts.margin || "";
22360
22360
  const width = opts.width;
22361
22361
  return (msg || "").split(/\r?\n/g).map((line) => line.split(/\s+/g).reduce((arr, w2) => {
@@ -22368,7 +22368,7 @@ function requireWrap() {
22368
22368
  `)).join(`
22369
22369
  `);
22370
22370
  };
22371
- return wrap;
22371
+ return wrap2;
22372
22372
  }
22373
22373
  function requireEntriesToDisplay() {
22374
22374
  if (hasRequiredEntriesToDisplay)
@@ -22660,7 +22660,7 @@ function requireSelect() {
22660
22660
  hasRequiredSelect = 1;
22661
22661
  const color = requireKleur();
22662
22662
  const Prompt = requirePrompt();
22663
- const { style: style2, clear: clear2, figures, wrap: wrap2, entriesToDisplay: entriesToDisplay2 } = requireUtil();
22663
+ const { style: style2, clear: clear2, figures, wrap: wrap3, entriesToDisplay: entriesToDisplay2 } = requireUtil();
22664
22664
  const { cursor } = requireSrc();
22665
22665
 
22666
22666
  class SelectPrompt extends Prompt {
@@ -22791,7 +22791,7 @@ function requireSelect() {
22791
22791
  desc = ` - ${v2.description}`;
22792
22792
  if (prefix.length + title.length + desc.length >= this.out.columns || v2.description.split(/\r?\n/).length > 1) {
22793
22793
  desc = `
22794
- ` + wrap2(v2.description, { margin: 3, width: this.out.columns });
22794
+ ` + wrap3(v2.description, { margin: 3, width: this.out.columns });
22795
22795
  }
22796
22796
  }
22797
22797
  }
@@ -23557,7 +23557,7 @@ function requireMultiselect() {
23557
23557
  const color = requireKleur();
23558
23558
  const { cursor } = requireSrc();
23559
23559
  const Prompt = requirePrompt();
23560
- const { clear: clear2, figures, style: style2, wrap: wrap2, entriesToDisplay: entriesToDisplay2 } = requireUtil();
23560
+ const { clear: clear2, figures, style: style2, wrap: wrap3, entriesToDisplay: entriesToDisplay2 } = requireUtil();
23561
23561
 
23562
23562
  class MultiselectPrompt extends Prompt {
23563
23563
  constructor(opts = {}) {
@@ -23715,7 +23715,7 @@ Instructions:
23715
23715
  desc = ` - ${v2.description}`;
23716
23716
  if (prefix.length + title.length + desc.length >= this.out.columns || v2.description.split(/\r?\n/).length > 1) {
23717
23717
  desc = `
23718
- ` + wrap2(v2.description, { margin: prefix.length, width: this.out.columns });
23718
+ ` + wrap3(v2.description, { margin: prefix.length, width: this.out.columns });
23719
23719
  }
23720
23720
  }
23721
23721
  }
@@ -23788,7 +23788,7 @@ function requireAutocomplete() {
23788
23788
  const color = requireKleur();
23789
23789
  const Prompt = requirePrompt();
23790
23790
  const { erase, cursor } = requireSrc();
23791
- const { style: style2, clear: clear2, figures, wrap: wrap2, entriesToDisplay: entriesToDisplay2 } = requireUtil();
23791
+ const { style: style2, clear: clear2, figures, wrap: wrap3, entriesToDisplay: entriesToDisplay2 } = requireUtil();
23792
23792
  const getVal = (arr, i2) => arr[i2] && (arr[i2].value || arr[i2].title || arr[i2]);
23793
23793
  const getTitle = (arr, i2) => arr[i2] && (arr[i2].title || arr[i2].value || arr[i2]);
23794
23794
  const getIndex = (arr, valOrTitle) => {
@@ -23975,7 +23975,7 @@ function requireAutocomplete() {
23975
23975
  desc = ` - ${v2.description}`;
23976
23976
  if (prefix.length + title.length + desc.length >= this.out.columns || v2.description.split(/\r?\n/).length > 1) {
23977
23977
  desc = `
23978
- ` + wrap2(v2.description, { margin: 3, width: this.out.columns });
23978
+ ` + wrap3(v2.description, { margin: 3, width: this.out.columns });
23979
23979
  }
23980
23980
  }
23981
23981
  return prefix + " " + title + color.gray(desc || "");
@@ -24929,7 +24929,7 @@ async function detect2({ autoInstall, programmatic, cwd } = {}) {
24929
24929
  }
24930
24930
  return agent;
24931
24931
  }
24932
- var ini$1, hasRequiredIni, iniExports, prompts$2, kleur, hasRequiredKleur, action, hasRequiredAction, strip, hasRequiredStrip, src, hasRequiredSrc, clear, hasRequiredClear, figures_1, hasRequiredFigures, style, hasRequiredStyle, lines, hasRequiredLines, wrap, hasRequiredWrap, entriesToDisplay, hasRequiredEntriesToDisplay, util, hasRequiredUtil, prompt, hasRequiredPrompt, text, hasRequiredText, select4, hasRequiredSelect, toggle, hasRequiredToggle, datepart, hasRequiredDatepart, meridiem, hasRequiredMeridiem, day, hasRequiredDay, hours, hasRequiredHours, milliseconds, hasRequiredMilliseconds, minutes, hasRequiredMinutes, month, hasRequiredMonth, seconds, hasRequiredSeconds, year, hasRequiredYear, dateparts, hasRequiredDateparts, date, hasRequiredDate, number, hasRequiredNumber, multiselect, hasRequiredMultiselect, autocomplete, hasRequiredAutocomplete, autocompleteMultiselect, hasRequiredAutocompleteMultiselect, confirm6, hasRequiredConfirm, elements, hasRequiredElements, hasRequiredPrompts$1, lib$1, hasRequiredLib$1, prompts$1, hasRequiredPrompts, promptsExports, prompts, isBrowser, platform, OSC = "\x1B]", BEL = "\x07", SEP = ";", link = (text2, url) => [
24932
+ var ini$1, hasRequiredIni, iniExports, prompts$2, kleur, hasRequiredKleur, action, hasRequiredAction, strip, hasRequiredStrip, src, hasRequiredSrc, clear, hasRequiredClear, figures_1, hasRequiredFigures, style, hasRequiredStyle, lines, hasRequiredLines, wrap2, hasRequiredWrap, entriesToDisplay, hasRequiredEntriesToDisplay, util, hasRequiredUtil, prompt, hasRequiredPrompt, text, hasRequiredText, select4, hasRequiredSelect, toggle, hasRequiredToggle, datepart, hasRequiredDatepart, meridiem, hasRequiredMeridiem, day, hasRequiredDay, hours, hasRequiredHours, milliseconds, hasRequiredMilliseconds, minutes, hasRequiredMinutes, month, hasRequiredMonth, seconds, hasRequiredSeconds, year, hasRequiredYear, dateparts, hasRequiredDateparts, date, hasRequiredDate, number, hasRequiredNumber, multiselect, hasRequiredMultiselect, autocomplete, hasRequiredAutocomplete, autocompleteMultiselect, hasRequiredAutocompleteMultiselect, confirm6, hasRequiredConfirm, elements, hasRequiredElements, hasRequiredPrompts$1, lib$1, hasRequiredLib$1, prompts$1, hasRequiredPrompts, promptsExports, prompts, isBrowser, platform, OSC = "\x1B]", BEL = "\x07", SEP = ";", link = (text2, url) => [
24933
24933
  OSC,
24934
24934
  "8",
24935
24935
  SEP,
@@ -32321,7 +32321,7 @@ var {
32321
32321
  // package.json
32322
32322
  var package_default = {
32323
32323
  name: "@secondlayer/cli",
32324
- version: "5.7.0",
32324
+ version: "5.8.0",
32325
32325
  repository: {
32326
32326
  type: "git",
32327
32327
  url: "git+https://github.com/ryanwaits/secondlayer.git",
@@ -32370,10 +32370,10 @@ var package_default = {
32370
32370
  dependencies: {
32371
32371
  "@inquirer/prompts": "^8.2.0",
32372
32372
  "@secondlayer/bundler": "^0.3.7",
32373
- "@secondlayer/sdk": "^5.0.0",
32373
+ "@secondlayer/sdk": "^5.6.0",
32374
32374
  "@secondlayer/shared": "^6.9.0",
32375
32375
  "@secondlayer/stacks": "^2.3.0",
32376
- "@secondlayer/subgraphs": "^3.3.0",
32376
+ "@secondlayer/subgraphs": "^3.4.0",
32377
32377
  "@biomejs/js-api": "^0.7.0",
32378
32378
  "@biomejs/wasm-nodejs": "^1.9.0",
32379
32379
  esbuild: "^0.19.0",
@@ -34444,6 +34444,7 @@ import { confirm as confirm4 } from "@inquirer/prompts";
34444
34444
 
34445
34445
  // src/generators/subgraph-scaffold.ts
34446
34446
  init_format();
34447
+ import { classifyContract } from "@secondlayer/stacks/clarity";
34447
34448
 
34448
34449
  // src/generators/clarity-to-subgraph.ts
34449
34450
  import {
@@ -34496,65 +34497,121 @@ function mapType(abiType, nullable) {
34496
34497
  function toCamelCase2(str) {
34497
34498
  return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
34498
34499
  }
34499
- async function generateSubgraphScaffold(input2) {
34500
- const { contractId, functions } = input2;
34501
- const contractParts = contractId.split(".");
34502
- const contractName = contractParts[contractParts.length - 1] ?? contractId;
34503
- const subgraphName = input2.subgraphName ?? contractName;
34504
- const publicFunctions = functions.filter((f) => f.access === "public");
34505
- if (publicFunctions.length === 0) {
34506
- throw new Error(`No public functions found in ${contractId}`);
34507
- }
34508
- const sourceEntries = publicFunctions.map((fn) => {
34509
- const sourceName = toCamelCase2(fn.name);
34510
- return ` ${sourceName}: { type: 'contract_call', contractId: '${contractId}', functionName: '${fn.name}' }`;
34511
- });
34512
- const sourcesBlock = sourceEntries.join(`,
34513
- `);
34514
- const tables = publicFunctions.map((fn) => {
34515
- const columns = fn.args.map((arg) => {
34516
- const mapped = clarityTypeToSubgraphColumn(arg.type);
34517
- const nullable = mapped.nullable ? ", nullable: true" : "";
34518
- return ` ${arg.name.replace(/-/g, "_")}: { type: '${mapped.type}'${nullable} }`;
34519
- }).join(`,
34520
- `);
34521
- const tableName = fn.name.replace(/-/g, "_");
34522
- return ` ${tableName}: {
34523
- columns: {
34524
- ${columns || " _placeholder: { type: 'text' }"}
34525
- }
34526
- }`;
34527
- });
34528
- const schemaBlock = tables.join(`,
34529
- `);
34530
- const handlerEntries = publicFunctions.map((fn) => {
34531
- const sourceName = toCamelCase2(fn.name);
34532
- return ` ${sourceName}: async (event, ctx) => {
34533
- // TODO: implement ${fn.name} handler
34534
- // event.args contains the function arguments
34535
- // ctx.insert('${fn.name.replace(/-/g, "_")}', { ... })
34536
- }`;
34537
- });
34538
- const handlersBlock = handlerEntries.join(`,
34539
-
34540
- `);
34541
- const code = `
34500
+ function snake(str) {
34501
+ return str.replace(/-/g, "_");
34502
+ }
34503
+ function wrap(name, sources, schema, handlers) {
34504
+ return `
34542
34505
  import { defineSubgraph } from '@secondlayer/subgraphs';
34543
34506
 
34544
34507
  export default defineSubgraph({
34545
- name: '${subgraphName}',
34508
+ name: '${name}',
34546
34509
  sources: {
34547
- ${sourcesBlock}
34510
+ ${sources}
34548
34511
  },
34549
34512
  schema: {
34550
- ${schemaBlock}
34513
+ ${schema}
34551
34514
  },
34552
34515
  handlers: {
34553
- ${handlersBlock}
34516
+ ${handlers}
34554
34517
  }
34555
34518
  });
34556
34519
  `.trimStart();
34557
- return formatCode(code);
34520
+ }
34521
+ function tokenScaffold(name, source) {
34522
+ const isFt = source.type === "ft_transfer";
34523
+ const scope = source.trait ? `trait: '${source.trait}'` : `assetIdentifier: '${source.assetIdentifier}'`;
34524
+ const cols = isFt ? ` sender: { type: 'principal' },
34525
+ recipient: { type: 'principal' },
34526
+ amount: { type: 'uint' },
34527
+ asset_identifier: { type: 'principal', indexed: true }` : ` sender: { type: 'principal' },
34528
+ recipient: { type: 'principal' },
34529
+ token_id: { type: 'text' },
34530
+ asset_identifier: { type: 'principal', indexed: true }`;
34531
+ const insert = isFt ? `{ sender: event.sender, recipient: event.recipient, amount: event.amount, asset_identifier: event.assetIdentifier }` : `{ sender: event.sender, recipient: event.recipient, token_id: String(event.tokenId), asset_identifier: event.assetIdentifier }`;
34532
+ return wrap(name, ` transfers: { type: '${source.type}', ${scope} }`, ` transfers: {
34533
+ columns: {
34534
+ ${cols}
34535
+ }
34536
+ }`, ` transfers: (event, ctx) => {
34537
+ ctx.insert('transfers', ${insert});
34538
+ }`);
34539
+ }
34540
+ function genericCallsScaffold(name, contractId) {
34541
+ return wrap(name, ` calls: { type: 'contract_call', contractId: '${contractId}' }`, ` calls: {
34542
+ columns: {
34543
+ function_name: { type: 'text', indexed: true },
34544
+ sender: { type: 'principal' },
34545
+ args: { type: 'jsonb' }
34546
+ }
34547
+ }`, ` calls: (event, ctx) => {
34548
+ ctx.insert('calls', { function_name: event.functionName, sender: event.sender, args: { values: event.args } });
34549
+ }`);
34550
+ }
34551
+ function functionsScaffold(name, contractId, abi, fnNames) {
34552
+ const fns = abi.functions.filter((f) => f.access === "public" && fnNames.includes(f.name));
34553
+ if (fns.length === 0) {
34554
+ throw new Error(`none of --functions [${fnNames.join(", ")}] are public functions of ${contractId}`);
34555
+ }
34556
+ const sources = fns.map((f) => ` ${toCamelCase2(f.name)}: { type: 'contract_call', contractId: '${contractId}', functionName: '${f.name}' }`).join(`,
34557
+ `);
34558
+ const schema = fns.map((f) => {
34559
+ const cols = f.args.map((arg) => {
34560
+ const m = clarityTypeToSubgraphColumn(arg.type);
34561
+ return ` ${snake(arg.name)}: { type: '${m.type}'${m.nullable ? ", nullable: true" : ""} }`;
34562
+ }).join(`,
34563
+ `);
34564
+ return ` ${snake(f.name)}: {
34565
+ columns: {
34566
+ ${cols || " sender: { type: 'principal' }"}
34567
+ }
34568
+ }`;
34569
+ }).join(`,
34570
+ `);
34571
+ const handlers = fns.map((f) => {
34572
+ const inserts = f.args.map((arg, i) => {
34573
+ const m = clarityTypeToSubgraphColumn(arg.type);
34574
+ const ts = m.type === "uint" || m.type === "int" ? "bigint" : m.type === "boolean" ? "boolean" : "string";
34575
+ return `${snake(arg.name)}: event.args[${i}] as ${ts}`;
34576
+ }).join(", ");
34577
+ return ` ${toCamelCase2(f.name)}: (event, ctx) => {
34578
+ ctx.insert('${snake(f.name)}', { ${inserts} });
34579
+ }`;
34580
+ }).join(`,
34581
+
34582
+ `);
34583
+ return wrap(name, sources, schema, handlers);
34584
+ }
34585
+ async function generateSubgraphScaffold(input2) {
34586
+ if (input2.trait) {
34587
+ const name2 = input2.subgraphName ?? `${input2.trait}-transfers`;
34588
+ const type = input2.trait === "sip-009" ? "nft_transfer" : "ft_transfer";
34589
+ return formatCode(tokenScaffold(name2, { type, trait: input2.trait }));
34590
+ }
34591
+ const { contractId, abi } = input2;
34592
+ if (!contractId || !abi) {
34593
+ throw new Error("scaffold requires a contractId + abi (or --trait)");
34594
+ }
34595
+ const name = input2.subgraphName ?? contractId.split(".").pop() ?? contractId;
34596
+ if (input2.functions && input2.functions.length > 0) {
34597
+ return formatCode(functionsScaffold(name, contractId, abi, input2.functions));
34598
+ }
34599
+ const standards = classifyContract(abi);
34600
+ if (standards.includes("sip-010")) {
34601
+ const asset = abi.fungible_tokens?.[0]?.name;
34602
+ return formatCode(tokenScaffold(name, {
34603
+ type: "ft_transfer",
34604
+ assetIdentifier: asset ? `${contractId}::${asset}` : contractId
34605
+ }));
34606
+ }
34607
+ if (standards.includes("sip-009")) {
34608
+ const asset = abi.non_fungible_tokens?.[0]?.name;
34609
+ return formatCode(tokenScaffold(name, {
34610
+ type: "nft_transfer",
34611
+ assetIdentifier: asset ? `${contractId}::${asset}` : contractId
34612
+ }));
34613
+ }
34614
+ return formatCode(genericCallsScaffold(name, contractId));
34558
34615
  }
34559
34616
 
34560
34617
  // src/utils/case-conversion.ts
@@ -36011,24 +36068,41 @@ ${rows.length} row(s)`));
36011
36068
  handleApiError(err, "delete subgraph");
36012
36069
  }
36013
36070
  });
36014
- subgraphs.command("scaffold <contractAddress>").description("Scaffold a defineSubgraph() file from a contract ABI").option("-o, --output <path>", "Output file path (required)").option("--api-key <key>", "Stacks node API key for direct RPC URLs").option("--no-install", "Skip bun install after writing package.json").action(async (contractAddress, options2) => {
36071
+ 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) => {
36015
36072
  try {
36016
36073
  if (!options2.output) {
36017
36074
  error("--output <path> is required");
36018
36075
  process.exit(1);
36019
36076
  }
36077
+ const trait = options2.trait;
36078
+ if (trait && !["sip-009", "sip-010", "sip-013"].includes(trait)) {
36079
+ error("--trait must be one of: sip-009, sip-010, sip-013");
36080
+ process.exit(1);
36081
+ }
36082
+ if (!trait && !contractAddress) {
36083
+ error("a <contractAddress> is required (or use --trait)");
36084
+ process.exit(1);
36085
+ }
36020
36086
  const outPath = resolve2(options2.output);
36021
- const network = inferNetwork(contractAddress) ?? "mainnet";
36022
- const apiKey = options2.apiKey ?? process.env.STACKS_NODE_API_KEY ?? process.env.HIRO_API_KEY;
36023
- const client = new StacksApiClient(network, apiKey);
36024
- info(`Fetching ABI for ${contractAddress} via ${client.describeContractInfoSource()}...`);
36025
- const contractInfo = await client.getContractInfo(contractAddress);
36026
- const abi = parseApiResponse(contractInfo);
36027
- info("Generating scaffold...");
36028
- const content = await generateSubgraphScaffold({
36029
- contractId: contractAddress,
36030
- functions: abi.functions
36031
- });
36087
+ let content;
36088
+ if (trait) {
36089
+ info(`Generating trait-scoped scaffold for ${trait}...`);
36090
+ content = await generateSubgraphScaffold({ trait });
36091
+ } else {
36092
+ const address = contractAddress;
36093
+ const network = inferNetwork(address) ?? "mainnet";
36094
+ const apiKey = options2.apiKey ?? process.env.STACKS_NODE_API_KEY ?? process.env.HIRO_API_KEY;
36095
+ const client = new StacksApiClient(network, apiKey);
36096
+ info(`Fetching ABI for ${address} via ${client.describeContractInfoSource()}...`);
36097
+ const contractInfo = await client.getContractInfo(address);
36098
+ const abi = parseApiResponse(contractInfo);
36099
+ info("Generating scaffold...");
36100
+ content = await generateSubgraphScaffold({
36101
+ contractId: address,
36102
+ abi,
36103
+ functions: options2.functions?.split(",").map((f) => f.trim()).filter(Boolean)
36104
+ });
36105
+ }
36032
36106
  const dir = resolve2(outPath, "..");
36033
36107
  if (!existsSync2(dir))
36034
36108
  mkdirSync2(dir, { recursive: true });
@@ -36399,6 +36473,60 @@ function registerStreamsCommand(program2) {
36399
36473
  }
36400
36474
  });
36401
36475
  }
36476
+ // src/commands/datasets.ts
36477
+ init_output();
36478
+ import { CURSOR_SLUGS, Datasets } from "@secondlayer/sdk";
36479
+ var DEFAULT_BASE_URL2 = "https://api.secondlayer.tools";
36480
+ function client2() {
36481
+ return new Datasets({ baseUrl: process.env.SL_API_URL ?? DEFAULT_BASE_URL2 });
36482
+ }
36483
+ function parseFilters(pairs) {
36484
+ const out = {};
36485
+ for (const pair of pairs ?? []) {
36486
+ const eq = pair.indexOf("=");
36487
+ if (eq <= 0) {
36488
+ throw new Error(`invalid --filter "${pair}" (expected key=value)`);
36489
+ }
36490
+ out[pair.slice(0, eq)] = pair.slice(eq + 1);
36491
+ }
36492
+ return out;
36493
+ }
36494
+ function registerDatasetsCommand(program2) {
36495
+ const datasets = program2.command("datasets").description("Query Foundation Datasets (sBTC, BNS, PoX-4, STX transfers)");
36496
+ datasets.command("list").description("List the dataset catalog + freshness").action(async () => {
36497
+ try {
36498
+ const catalog = await client2().listDatasets();
36499
+ process.stdout.write(`${JSON.stringify(catalog, null, 2)}
36500
+ `);
36501
+ } catch (err) {
36502
+ error(`Failed to list datasets: ${err}`);
36503
+ process.exit(1);
36504
+ }
36505
+ });
36506
+ 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) => {
36507
+ try {
36508
+ const params = parseFilters(options2.filter);
36509
+ if (options2.limit)
36510
+ params.limit = Number.parseInt(options2.limit, 10);
36511
+ if (options2.cursor)
36512
+ params.cursor = options2.cursor;
36513
+ const env = await client2().query(dataset, params);
36514
+ if (options2.json) {
36515
+ process.stdout.write(`${JSON.stringify(env, null, 2)}
36516
+ `);
36517
+ } else {
36518
+ process.stdout.write(`${JSON.stringify(env.rows, null, 2)}
36519
+ `);
36520
+ if (env.next_cursor) {
36521
+ info(`next_cursor: ${env.next_cursor}`);
36522
+ }
36523
+ }
36524
+ } catch (err) {
36525
+ error(`Failed to query dataset: ${err}`);
36526
+ process.exit(1);
36527
+ }
36528
+ });
36529
+ }
36402
36530
  // src/commands/doctor.ts
36403
36531
  init_config();
36404
36532
 
@@ -37265,6 +37393,7 @@ registerSubgraphsCommand(program);
37265
37393
  registerCreateCommand(program);
37266
37394
  registerSubscriptionsCommand(program);
37267
37395
  registerStreamsCommand(program);
37396
+ registerDatasetsCommand(program);
37268
37397
  registerStatusCommand(program);
37269
37398
  registerStackCommand(program);
37270
37399
  registerDbCommand(program);
@@ -37275,5 +37404,5 @@ registerAccountCommand(program);
37275
37404
  registerBillingCommand(program);
37276
37405
  program.parse();
37277
37406
 
37278
- //# debugId=74377287407FCAB564756E2164756E21
37407
+ //# debugId=BC7D4D440C943F4464756E2164756E21
37279
37408
  //# sourceMappingURL=cli.js.map