@secondlayer/cli 5.6.6 → 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/README.md +81 -172
- package/dist/cli.js +259 -84
- package/dist/cli.js.map +7 -6
- package/package.json +5 -5
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
|
|
15423
|
-
let cacheKey = min + ":" + max + "=" + relax + shorthand + capture +
|
|
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
|
|
15703
|
+
let wrap2 = options2.wrap === true;
|
|
15704
15704
|
let prefix = options2.capture ? "" : "?:";
|
|
15705
|
-
return
|
|
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
|
|
22356
|
+
return wrap2;
|
|
22357
22357
|
hasRequiredWrap = 1;
|
|
22358
|
-
|
|
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
|
|
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:
|
|
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
|
-
` +
|
|
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:
|
|
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
|
-
` +
|
|
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:
|
|
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
|
-
` +
|
|
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,
|
|
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.
|
|
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.
|
|
32374
|
-
"@secondlayer/shared": "^6.
|
|
32375
|
-
"@secondlayer/stacks": "^2.
|
|
32376
|
-
"@secondlayer/subgraphs": "^3.
|
|
32373
|
+
"@secondlayer/sdk": "^5.6.0",
|
|
32374
|
+
"@secondlayer/shared": "^6.9.0",
|
|
32375
|
+
"@secondlayer/stacks": "^2.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
|
-
|
|
34500
|
-
|
|
34501
|
-
|
|
34502
|
-
|
|
34503
|
-
|
|
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: '${
|
|
34508
|
+
name: '${name}',
|
|
34546
34509
|
sources: {
|
|
34547
|
-
${
|
|
34510
|
+
${sources}
|
|
34548
34511
|
},
|
|
34549
34512
|
schema: {
|
|
34550
|
-
${
|
|
34513
|
+
${schema}
|
|
34551
34514
|
},
|
|
34552
34515
|
handlers: {
|
|
34553
|
-
${
|
|
34516
|
+
${handlers}
|
|
34554
34517
|
}
|
|
34555
34518
|
});
|
|
34556
34519
|
`.trimStart();
|
|
34557
|
-
|
|
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
|
|
@@ -35475,7 +35532,7 @@ Stopped watching.`);
|
|
|
35475
35532
|
});
|
|
35476
35533
|
await new Promise(() => {});
|
|
35477
35534
|
});
|
|
35478
|
-
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("--strict", "Run `tsc --noEmit` against the handler before deploy (slower; catches TS type errors)").action(async (file, options2) => {
|
|
35535
|
+
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) => {
|
|
35479
35536
|
try {
|
|
35480
35537
|
const absPath = resolve2(file);
|
|
35481
35538
|
const config = await loadConfig();
|
|
@@ -35518,6 +35575,9 @@ Stopped watching.`);
|
|
|
35518
35575
|
return;
|
|
35519
35576
|
}
|
|
35520
35577
|
const deployStartBlock = startBlock ?? effectiveDef.startBlock;
|
|
35578
|
+
if (options2.databaseUrl) {
|
|
35579
|
+
info("BYO data plane: schema + rows will live in your database. The server verifies the connection before deploying.");
|
|
35580
|
+
}
|
|
35521
35581
|
const result = await deploySubgraphApi({
|
|
35522
35582
|
name: effectiveDef.name,
|
|
35523
35583
|
version: undefined,
|
|
@@ -35526,7 +35586,8 @@ Stopped watching.`);
|
|
|
35526
35586
|
schema: effectiveDef.schema,
|
|
35527
35587
|
handlerCode,
|
|
35528
35588
|
sourceCode: source,
|
|
35529
|
-
...deployStartBlock !== undefined ? { startBlock: deployStartBlock } : {}
|
|
35589
|
+
...deployStartBlock !== undefined ? { startBlock: deployStartBlock } : {},
|
|
35590
|
+
...options2.databaseUrl ? { databaseUrl: options2.databaseUrl } : {}
|
|
35530
35591
|
});
|
|
35531
35592
|
const printDeployFooter = async () => {
|
|
35532
35593
|
try {
|
|
@@ -35772,6 +35833,48 @@ Synced — exiting watch.`));
|
|
|
35772
35833
|
process.exit(1);
|
|
35773
35834
|
}
|
|
35774
35835
|
});
|
|
35836
|
+
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) => {
|
|
35837
|
+
try {
|
|
35838
|
+
const target = options2.target ?? "prisma";
|
|
35839
|
+
if (target !== "prisma" && target !== "drizzle") {
|
|
35840
|
+
error(`Unsupported --target "${target}" (supported: prisma, drizzle). For Kysely, run kysely-codegen against your database.`);
|
|
35841
|
+
process.exit(1);
|
|
35842
|
+
}
|
|
35843
|
+
const absPath = resolve2(file);
|
|
35844
|
+
if (!existsSync2(absPath)) {
|
|
35845
|
+
error(`File not found: ${absPath}`);
|
|
35846
|
+
process.exit(1);
|
|
35847
|
+
}
|
|
35848
|
+
const { readFile: readFile3 } = await import("node:fs/promises");
|
|
35849
|
+
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
35850
|
+
const { generatePrismaSchema, generateDrizzleSchema } = await import("@secondlayer/subgraphs");
|
|
35851
|
+
const source = await readFile3(absPath, "utf8");
|
|
35852
|
+
const bundled = await bundleSubgraphCode(source);
|
|
35853
|
+
const def = {
|
|
35854
|
+
name: bundled.name,
|
|
35855
|
+
version: bundled.version,
|
|
35856
|
+
description: bundled.description,
|
|
35857
|
+
sources: bundled.sources,
|
|
35858
|
+
schema: bundled.schema,
|
|
35859
|
+
handlers: {}
|
|
35860
|
+
};
|
|
35861
|
+
const out = target === "drizzle" ? generateDrizzleSchema(def, { schemaName: options2.schema }) : generatePrismaSchema(def, {
|
|
35862
|
+
schemaName: options2.schema,
|
|
35863
|
+
datasourceEnv: options2.env,
|
|
35864
|
+
modelsOnly: options2.modelsOnly
|
|
35865
|
+
});
|
|
35866
|
+
if (options2.output) {
|
|
35867
|
+
await writeTextFile(resolve2(options2.output), out);
|
|
35868
|
+
success(`Wrote ${target} schema to ${options2.output}`);
|
|
35869
|
+
info("Next: point its datasource at your BYO database, then `prisma generate`.");
|
|
35870
|
+
} else {
|
|
35871
|
+
process.stdout.write(out);
|
|
35872
|
+
}
|
|
35873
|
+
} catch (err) {
|
|
35874
|
+
error(`Failed to generate schema: ${err}`);
|
|
35875
|
+
process.exit(1);
|
|
35876
|
+
}
|
|
35877
|
+
});
|
|
35775
35878
|
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) => {
|
|
35776
35879
|
try {
|
|
35777
35880
|
const fromBlock = options2.from ? Number.parseInt(options2.from, 10) : undefined;
|
|
@@ -35965,24 +36068,41 @@ ${rows.length} row(s)`));
|
|
|
35965
36068
|
handleApiError(err, "delete subgraph");
|
|
35966
36069
|
}
|
|
35967
36070
|
});
|
|
35968
|
-
subgraphs.command("scaffold
|
|
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) => {
|
|
35969
36072
|
try {
|
|
35970
36073
|
if (!options2.output) {
|
|
35971
36074
|
error("--output <path> is required");
|
|
35972
36075
|
process.exit(1);
|
|
35973
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
|
+
}
|
|
35974
36086
|
const outPath = resolve2(options2.output);
|
|
35975
|
-
|
|
35976
|
-
|
|
35977
|
-
|
|
35978
|
-
|
|
35979
|
-
|
|
35980
|
-
|
|
35981
|
-
|
|
35982
|
-
|
|
35983
|
-
|
|
35984
|
-
|
|
35985
|
-
|
|
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
|
+
}
|
|
35986
36106
|
const dir = resolve2(outPath, "..");
|
|
35987
36107
|
if (!existsSync2(dir))
|
|
35988
36108
|
mkdirSync2(dir, { recursive: true });
|
|
@@ -36007,7 +36127,7 @@ ${rows.length} row(s)`));
|
|
|
36007
36127
|
process.exit(1);
|
|
36008
36128
|
}
|
|
36009
36129
|
});
|
|
36010
|
-
subgraphs.command("
|
|
36130
|
+
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) => {
|
|
36011
36131
|
try {
|
|
36012
36132
|
if (!options2.output) {
|
|
36013
36133
|
error("--output <path> is required");
|
|
@@ -36353,6 +36473,60 @@ function registerStreamsCommand(program2) {
|
|
|
36353
36473
|
}
|
|
36354
36474
|
});
|
|
36355
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
|
+
}
|
|
36356
36530
|
// src/commands/doctor.ts
|
|
36357
36531
|
init_config();
|
|
36358
36532
|
|
|
@@ -37203,7 +37377,7 @@ Quickstart:
|
|
|
37203
37377
|
$ sl subgraphs deploy subgraphs/my-watcher.ts
|
|
37204
37378
|
$ sl subgraphs status my-watcher
|
|
37205
37379
|
`);
|
|
37206
|
-
program.command("generate [files...]").aliases(["gen"
|
|
37380
|
+
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) => {
|
|
37207
37381
|
const { generate: generate2 } = await Promise.resolve().then(() => (init_generate(), exports_generate));
|
|
37208
37382
|
await generate2(files, options3);
|
|
37209
37383
|
});
|
|
@@ -37219,6 +37393,7 @@ registerSubgraphsCommand(program);
|
|
|
37219
37393
|
registerCreateCommand(program);
|
|
37220
37394
|
registerSubscriptionsCommand(program);
|
|
37221
37395
|
registerStreamsCommand(program);
|
|
37396
|
+
registerDatasetsCommand(program);
|
|
37222
37397
|
registerStatusCommand(program);
|
|
37223
37398
|
registerStackCommand(program);
|
|
37224
37399
|
registerDbCommand(program);
|
|
@@ -37229,5 +37404,5 @@ registerAccountCommand(program);
|
|
|
37229
37404
|
registerBillingCommand(program);
|
|
37230
37405
|
program.parse();
|
|
37231
37406
|
|
|
37232
|
-
//# debugId=
|
|
37407
|
+
//# debugId=BC7D4D440C943F4464756E2164756E21
|
|
37233
37408
|
//# sourceMappingURL=cli.js.map
|