@secondlayer/cli 8.9.0 → 8.10.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 +148 -17
- package/dist/cli.js.map +4 -4
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -18083,8 +18083,8 @@ var require_pattern = __commonJS((exports) => {
|
|
|
18083
18083
|
}
|
|
18084
18084
|
exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
18085
18085
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
18086
|
-
const
|
|
18087
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
18086
|
+
const basename2 = path3.basename(pattern);
|
|
18087
|
+
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename2);
|
|
18088
18088
|
}
|
|
18089
18089
|
exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
18090
18090
|
function expandPatternsWithBraceExpansion(patterns) {
|
|
@@ -31588,8 +31588,8 @@ async function parseInputs(inputs) {
|
|
|
31588
31588
|
};
|
|
31589
31589
|
}
|
|
31590
31590
|
function deriveContractName(filePath) {
|
|
31591
|
-
const
|
|
31592
|
-
return
|
|
31591
|
+
const basename2 = path11.basename(filePath, ".clar");
|
|
31592
|
+
return basename2.replace(/[-_](.)/g, (_2, char) => char.toUpperCase()).replace(/^(.)/, (_2, char) => char.toLowerCase()).replace(/^\d/, "_$&");
|
|
31593
31593
|
}
|
|
31594
31594
|
async function buildConfigFromInputs(parsedInputs, outPath, apiKey, defaultAddress) {
|
|
31595
31595
|
const contracts = [];
|
|
@@ -31811,7 +31811,7 @@ var {
|
|
|
31811
31811
|
// package.json
|
|
31812
31812
|
var package_default = {
|
|
31813
31813
|
name: "@secondlayer/cli",
|
|
31814
|
-
version: "8.
|
|
31814
|
+
version: "8.10.0",
|
|
31815
31815
|
repository: {
|
|
31816
31816
|
type: "git",
|
|
31817
31817
|
url: "git+https://github.com/ryanwaits/secondlayer.git",
|
|
@@ -31860,11 +31860,11 @@ var package_default = {
|
|
|
31860
31860
|
dependencies: {
|
|
31861
31861
|
"@inquirer/prompts": "^8.2.0",
|
|
31862
31862
|
"@secondlayer/bundler": "^0.3.7",
|
|
31863
|
-
"@secondlayer/scaffold": "^1.
|
|
31864
|
-
"@secondlayer/sdk": "^6.
|
|
31865
|
-
"@secondlayer/shared": "^6.
|
|
31863
|
+
"@secondlayer/scaffold": "^1.3.0",
|
|
31864
|
+
"@secondlayer/sdk": "^6.22.0",
|
|
31865
|
+
"@secondlayer/shared": "^6.32.0",
|
|
31866
31866
|
"@secondlayer/stacks": "^2.5.1",
|
|
31867
|
-
"@secondlayer/subgraphs": "^3.
|
|
31867
|
+
"@secondlayer/subgraphs": "^3.14.0",
|
|
31868
31868
|
"@biomejs/js-api": "^0.7.0",
|
|
31869
31869
|
"@biomejs/wasm-nodejs": "^1.9.0",
|
|
31870
31870
|
esbuild: "^0.19.0",
|
|
@@ -32041,6 +32041,9 @@ async function querySubgraphTableCount(name, table, params = {}) {
|
|
|
32041
32041
|
async function getSubgraphGaps(name, opts) {
|
|
32042
32042
|
return (await getPlatformClient()).subgraphs.gaps(name, opts);
|
|
32043
32043
|
}
|
|
32044
|
+
async function getContractPrintSchema(contractId) {
|
|
32045
|
+
return (await getPlatformClient()).index.printSchema(contractId);
|
|
32046
|
+
}
|
|
32044
32047
|
async function getAccountProfile() {
|
|
32045
32048
|
return httpPlatform("/api/accounts/me");
|
|
32046
32049
|
}
|
|
@@ -34109,9 +34112,13 @@ import {
|
|
|
34109
34112
|
watch,
|
|
34110
34113
|
writeFileSync as writeFileSync4
|
|
34111
34114
|
} from "node:fs";
|
|
34112
|
-
import { dirname as dirname5, join as join7, resolve as resolve2 } from "node:path";
|
|
34115
|
+
import { basename, dirname as dirname5, extname, join as join7, resolve as resolve2 } from "node:path";
|
|
34113
34116
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
34114
34117
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
34118
|
+
import {
|
|
34119
|
+
generatePrintPayloadTypes,
|
|
34120
|
+
generatePrintSchemaSubgraph
|
|
34121
|
+
} from "@secondlayer/scaffold";
|
|
34115
34122
|
import { ByoBreakingChangeError } from "@secondlayer/sdk";
|
|
34116
34123
|
import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
|
|
34117
34124
|
|
|
@@ -34875,6 +34882,7 @@ function decodeBuffUtf8(value: unknown): string | null {
|
|
|
34875
34882
|
|
|
34876
34883
|
// src/commands/subgraphs.ts
|
|
34877
34884
|
init_api();
|
|
34885
|
+
init_format();
|
|
34878
34886
|
async function loadSubgraphWithDepCheck(absPath) {
|
|
34879
34887
|
try {
|
|
34880
34888
|
return await import(absPath);
|
|
@@ -34933,6 +34941,84 @@ function parseVisibilityOption(value) {
|
|
|
34933
34941
|
return value;
|
|
34934
34942
|
throw new Error('--visibility must be "public" or "private"');
|
|
34935
34943
|
}
|
|
34944
|
+
function collectPinnedPrintSources(sources) {
|
|
34945
|
+
const out = [];
|
|
34946
|
+
for (const [sourceName, raw] of Object.entries(sources ?? {})) {
|
|
34947
|
+
const s = raw;
|
|
34948
|
+
if (s?.type !== "print_event")
|
|
34949
|
+
continue;
|
|
34950
|
+
if (typeof s.contractId !== "string" || s.contractId.length === 0)
|
|
34951
|
+
continue;
|
|
34952
|
+
if (s.trait)
|
|
34953
|
+
continue;
|
|
34954
|
+
out.push({
|
|
34955
|
+
sourceName,
|
|
34956
|
+
contractId: s.contractId,
|
|
34957
|
+
...typeof s.topic === "string" ? { topic: s.topic } : {}
|
|
34958
|
+
});
|
|
34959
|
+
}
|
|
34960
|
+
return out;
|
|
34961
|
+
}
|
|
34962
|
+
var ORM_ONLY_CODEGEN_FLAGS = {
|
|
34963
|
+
target: "--target",
|
|
34964
|
+
schema: "--schema",
|
|
34965
|
+
env: "--env",
|
|
34966
|
+
modelsOnly: "--models-only"
|
|
34967
|
+
};
|
|
34968
|
+
function ormFlagsConflictingWithPayloads(getOptionValueSource) {
|
|
34969
|
+
return Object.entries(ORM_ONLY_CODEGEN_FLAGS).filter(([key]) => getOptionValueSource(key) === "cli").map(([, flag]) => flag);
|
|
34970
|
+
}
|
|
34971
|
+
async function runPayloadsCodegen(file, output2) {
|
|
34972
|
+
const absPath = resolve2(file);
|
|
34973
|
+
if (!existsSync4(absPath)) {
|
|
34974
|
+
error(`File not found: ${absPath}`);
|
|
34975
|
+
process.exit(1);
|
|
34976
|
+
}
|
|
34977
|
+
const { readFile: readFile3 } = await import("node:fs/promises");
|
|
34978
|
+
const { bundleSubgraphCode } = await import("@secondlayer/bundler");
|
|
34979
|
+
const source = await readFile3(absPath, "utf8");
|
|
34980
|
+
const bundled = await bundleSubgraphCode(source);
|
|
34981
|
+
const pinned = collectPinnedPrintSources(bundled.sources ?? {});
|
|
34982
|
+
if (pinned.length === 0) {
|
|
34983
|
+
error("No pinned print_event sources (contractId set, no trait) — nothing to generate payload types for.");
|
|
34984
|
+
process.exit(1);
|
|
34985
|
+
}
|
|
34986
|
+
const schemas = new Map;
|
|
34987
|
+
for (const contractId of new Set(pinned.map((p) => p.contractId))) {
|
|
34988
|
+
info(`Fetching print schema for ${contractId}...`);
|
|
34989
|
+
try {
|
|
34990
|
+
schemas.set(contractId, await getContractPrintSchema(contractId));
|
|
34991
|
+
} catch (err) {
|
|
34992
|
+
handleApiError(err, "fetch contract print schema");
|
|
34993
|
+
}
|
|
34994
|
+
}
|
|
34995
|
+
const sources = [];
|
|
34996
|
+
for (const p of pinned) {
|
|
34997
|
+
const schema = schemas.get(p.contractId);
|
|
34998
|
+
if (!schema || schema.topics.length === 0) {
|
|
34999
|
+
warn(`No print events observed for ${p.contractId} — skipping source "${p.sourceName}"`);
|
|
35000
|
+
continue;
|
|
35001
|
+
}
|
|
35002
|
+
const topics = p.topic ? schema.topics.filter((t) => t.topic === p.topic) : schema.topics;
|
|
35003
|
+
if (topics.length === 0) {
|
|
35004
|
+
warn(`Topic "${p.topic}" never observed on ${p.contractId} — skipping source "${p.sourceName}"`);
|
|
35005
|
+
continue;
|
|
35006
|
+
}
|
|
35007
|
+
sources.push({
|
|
35008
|
+
sourceName: p.sourceName,
|
|
35009
|
+
contractId: p.contractId,
|
|
35010
|
+
topics
|
|
35011
|
+
});
|
|
35012
|
+
}
|
|
35013
|
+
if (sources.length === 0) {
|
|
35014
|
+
error("No print schemas available for any pinned source. Check the contract ids and that the contracts have emitted print events.");
|
|
35015
|
+
process.exit(1);
|
|
35016
|
+
}
|
|
35017
|
+
const out = generatePrintPayloadTypes({ sources });
|
|
35018
|
+
const outPath = resolve2(output2 ?? join7(dirname5(absPath), `${basename(absPath, extname(absPath))}.payloads.d.ts`));
|
|
35019
|
+
await writeTextFile(outPath, out);
|
|
35020
|
+
success(`Wrote print payload types to ${outPath}`);
|
|
35021
|
+
}
|
|
34936
35022
|
function parseSubgraphSpecFormat(value) {
|
|
34937
35023
|
const format = value ?? "openapi";
|
|
34938
35024
|
if (format === "openapi" || format === "agent" || format === "markdown") {
|
|
@@ -35229,12 +35315,22 @@ function formatSubgraphSync(sync) {
|
|
|
35229
35315
|
}
|
|
35230
35316
|
function registerSubgraphsCommand(program2) {
|
|
35231
35317
|
const subgraphs = program2.command("subgraphs").description("Manage materialized subgraphs");
|
|
35232
|
-
subgraphs.command("create <name>").description("Create a new subgraph definition file").option("--template <slug>", `Starter template (one of: ${SUBGRAPH_TEMPLATE_SLUGS.join(", ")})`).addHelpText("after", `
|
|
35318
|
+
subgraphs.command("create <name>").description("Create a new subgraph definition file").option("--template <slug>", `Starter template (one of: ${SUBGRAPH_TEMPLATE_SLUGS.join(", ")})`).option("--from-contract <contractId>", "Generate sources/schema/handlers from the contract's observed print events (requires network)").option("--table-per-topic", "With --from-contract: one table per print topic instead of a single wide table").addHelpText("after", `
|
|
35233
35319
|
Examples:
|
|
35234
35320
|
$ sl subgraphs create my-graph
|
|
35235
|
-
$ sl subgraphs create token-balances --template sip-010-balances
|
|
35321
|
+
$ sl subgraphs create token-balances --template sip-010-balances
|
|
35322
|
+
$ sl subgraphs create sbtc-flows --from-contract SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry
|
|
35323
|
+
$ sl subgraphs create sbtc-flows --from-contract SM3....sbtc-registry --table-per-topic`).action(async (name, opts) => {
|
|
35324
|
+
if (opts.fromContract && opts.template) {
|
|
35325
|
+
error("--from-contract and --template are mutually exclusive");
|
|
35326
|
+
process.exit(1);
|
|
35327
|
+
}
|
|
35328
|
+
if (opts.tablePerTopic && !opts.fromContract) {
|
|
35329
|
+
error("--table-per-topic requires --from-contract");
|
|
35330
|
+
process.exit(1);
|
|
35331
|
+
}
|
|
35236
35332
|
const slug = opts.template ?? "basic";
|
|
35237
|
-
if (!SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
|
|
35333
|
+
if (!opts.fromContract && !SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
|
|
35238
35334
|
error(`Unknown template "${opts.template}". Available templates:
|
|
35239
35335
|
${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESCRIPTIONS[s]}`).join(`
|
|
35240
35336
|
`)}`);
|
|
@@ -35246,13 +35342,37 @@ ${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESC
|
|
|
35246
35342
|
error(`File already exists: ${filePath}`);
|
|
35247
35343
|
process.exit(1);
|
|
35248
35344
|
}
|
|
35345
|
+
let content;
|
|
35346
|
+
if (opts.fromContract) {
|
|
35347
|
+
info(`Fetching print schema for ${opts.fromContract}...`);
|
|
35348
|
+
let schema;
|
|
35349
|
+
try {
|
|
35350
|
+
schema = await getContractPrintSchema(opts.fromContract);
|
|
35351
|
+
} catch (err) {
|
|
35352
|
+
handleApiError(err, "fetch contract print schema");
|
|
35353
|
+
}
|
|
35354
|
+
if (!schema || schema.topics.length === 0) {
|
|
35355
|
+
error(`No print events observed for ${opts.fromContract}.
|
|
35356
|
+
Check the contract id, and that the contract has emitted print events (schemas are inferred from indexed on-chain events).`);
|
|
35357
|
+
process.exit(1);
|
|
35358
|
+
}
|
|
35359
|
+
content = await formatCode(generatePrintSchemaSubgraph({
|
|
35360
|
+
contractId: opts.fromContract,
|
|
35361
|
+
name,
|
|
35362
|
+
topics: schema.topics,
|
|
35363
|
+
tablePerTopic: opts.tablePerTopic
|
|
35364
|
+
}));
|
|
35365
|
+
} else {
|
|
35366
|
+
content = generateSubgraphTemplate(name, slug);
|
|
35367
|
+
}
|
|
35249
35368
|
if (!existsSync4(dir)) {
|
|
35250
35369
|
mkdirSync3(dir, { recursive: true });
|
|
35251
35370
|
}
|
|
35252
|
-
const content = generateSubgraphTemplate(name, slug);
|
|
35253
35371
|
await writeTextFile(filePath, content);
|
|
35254
35372
|
success(`Created ${filePath}`);
|
|
35255
|
-
if (
|
|
35373
|
+
if (opts.fromContract) {
|
|
35374
|
+
info(`Schema inferred from ${opts.fromContract} print events (${opts.tablePerTopic ? "table per topic" : "single wide table"})`);
|
|
35375
|
+
} else if (slug !== "basic") {
|
|
35256
35376
|
info(`Template: ${slug} — ${SUBGRAPH_TEMPLATE_DESCRIPTIONS[slug]}`);
|
|
35257
35377
|
}
|
|
35258
35378
|
info(`Next: sl subgraphs deploy subgraphs/${name}.ts`);
|
|
@@ -35392,6 +35512,8 @@ Stopped watching.`);
|
|
|
35392
35512
|
if (result.start_block_clamped) {
|
|
35393
35513
|
info(` Free tier indexes forward from deploy (start block ${result.start_block}) — upgrade for genesis backfill.`);
|
|
35394
35514
|
}
|
|
35515
|
+
for (const w of result.warnings ?? [])
|
|
35516
|
+
warn(w);
|
|
35395
35517
|
const printDeployFooter = async () => {
|
|
35396
35518
|
try {
|
|
35397
35519
|
const { apiUrl } = await resolveAuth();
|
|
@@ -35612,7 +35734,16 @@ Synced — exiting watch.`));
|
|
|
35612
35734
|
handleApiError(err, "generate subgraph spec");
|
|
35613
35735
|
}
|
|
35614
35736
|
});
|
|
35615
|
-
subgraphs.command("codegen <file>").description("Generate an ORM schema (Prisma, Drizzle, or Kysely) for a subgraph's tables — point it at your BYO database").option("--target <orm>", "ORM target: prisma | drizzle | kysely", "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) => {
|
|
35737
|
+
subgraphs.command("codegen <file>").description("Generate an ORM schema (Prisma, Drizzle, or Kysely) for a subgraph's tables — point it at your BYO database").option("--target <orm>", "ORM target: prisma | drizzle | kysely", "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("--payloads", "Emit a .d.ts of print payload types for pinned print_event sources, inferred from observed on-chain events (requires network)").option("-o, --output <path>", "Write to a file (defaults to stdout)").action(async (file, options2, command) => {
|
|
35738
|
+
if (options2.payloads) {
|
|
35739
|
+
const conflicts = ormFlagsConflictingWithPayloads((key) => command.getOptionValueSource(key));
|
|
35740
|
+
if (conflicts.length > 0) {
|
|
35741
|
+
error(`--payloads cannot be combined with ${conflicts.join(", ")} — those flags apply to ORM targets only.`);
|
|
35742
|
+
process.exit(1);
|
|
35743
|
+
}
|
|
35744
|
+
await runPayloadsCodegen(file, options2.output);
|
|
35745
|
+
return;
|
|
35746
|
+
}
|
|
35616
35747
|
try {
|
|
35617
35748
|
const target = options2.target ?? "prisma";
|
|
35618
35749
|
if (target !== "prisma" && target !== "drizzle" && target !== "kysely") {
|
|
@@ -37963,5 +38094,5 @@ registerAccountCommand(program);
|
|
|
37963
38094
|
registerKeysCommand(program);
|
|
37964
38095
|
program.parse();
|
|
37965
38096
|
|
|
37966
|
-
//# debugId=
|
|
38097
|
+
//# debugId=D198B46A9AA7918164756E2164756E21
|
|
37967
38098
|
//# sourceMappingURL=cli.js.map
|