@secondlayer/cli 8.9.0 → 8.10.1

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
@@ -18083,8 +18083,8 @@ var require_pattern = __commonJS((exports) => {
18083
18083
  }
18084
18084
  exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
18085
18085
  function isAffectDepthOfReadingPattern(pattern) {
18086
- const basename = path3.basename(pattern);
18087
- return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
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 basename = path11.basename(filePath, ".clar");
31592
- return basename.replace(/[-_](.)/g, (_2, char) => char.toUpperCase()).replace(/^(.)/, (_2, char) => char.toLowerCase()).replace(/^\d/, "_$&");
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.9.0",
31814
+ version: "8.10.1",
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.2.0",
31864
- "@secondlayer/sdk": "^6.21.2",
31865
- "@secondlayer/shared": "^6.31.0",
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.12.0",
31867
+ "@secondlayer/subgraphs": "^3.14.1",
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,15 @@ 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
+ let client;
32046
+ try {
32047
+ client = await getPlatformClient();
32048
+ } catch {
32049
+ client = new SecondLayer({ baseUrl: resolveApiUrl() });
32050
+ }
32051
+ return client.index.printSchema(contractId);
32052
+ }
32044
32053
  async function getAccountProfile() {
32045
32054
  return httpPlatform("/api/accounts/me");
32046
32055
  }
@@ -34109,9 +34118,13 @@ import {
34109
34118
  watch,
34110
34119
  writeFileSync as writeFileSync4
34111
34120
  } from "node:fs";
34112
- import { dirname as dirname5, join as join7, resolve as resolve2 } from "node:path";
34121
+ import { basename, dirname as dirname5, extname, join as join7, resolve as resolve2 } from "node:path";
34113
34122
  import { fileURLToPath as fileURLToPath2 } from "node:url";
34114
34123
  import { confirm as confirm3 } from "@inquirer/prompts";
34124
+ import {
34125
+ generatePrintPayloadTypes,
34126
+ generatePrintSchemaSubgraph
34127
+ } from "@secondlayer/scaffold";
34115
34128
  import { ByoBreakingChangeError } from "@secondlayer/sdk";
34116
34129
  import { TRAIT_STANDARDS } from "@secondlayer/stacks/clarity";
34117
34130
 
@@ -34875,6 +34888,7 @@ function decodeBuffUtf8(value: unknown): string | null {
34875
34888
 
34876
34889
  // src/commands/subgraphs.ts
34877
34890
  init_api();
34891
+ init_format();
34878
34892
  async function loadSubgraphWithDepCheck(absPath) {
34879
34893
  try {
34880
34894
  return await import(absPath);
@@ -34933,6 +34947,84 @@ function parseVisibilityOption(value) {
34933
34947
  return value;
34934
34948
  throw new Error('--visibility must be "public" or "private"');
34935
34949
  }
34950
+ function collectPinnedPrintSources(sources) {
34951
+ const out = [];
34952
+ for (const [sourceName, raw] of Object.entries(sources ?? {})) {
34953
+ const s = raw;
34954
+ if (s?.type !== "print_event")
34955
+ continue;
34956
+ if (typeof s.contractId !== "string" || s.contractId.length === 0)
34957
+ continue;
34958
+ if (s.trait)
34959
+ continue;
34960
+ out.push({
34961
+ sourceName,
34962
+ contractId: s.contractId,
34963
+ ...typeof s.topic === "string" ? { topic: s.topic } : {}
34964
+ });
34965
+ }
34966
+ return out;
34967
+ }
34968
+ var ORM_ONLY_CODEGEN_FLAGS = {
34969
+ target: "--target",
34970
+ schema: "--schema",
34971
+ env: "--env",
34972
+ modelsOnly: "--models-only"
34973
+ };
34974
+ function ormFlagsConflictingWithPayloads(getOptionValueSource) {
34975
+ return Object.entries(ORM_ONLY_CODEGEN_FLAGS).filter(([key]) => getOptionValueSource(key) === "cli").map(([, flag]) => flag);
34976
+ }
34977
+ async function runPayloadsCodegen(file, output2) {
34978
+ const absPath = resolve2(file);
34979
+ if (!existsSync4(absPath)) {
34980
+ error(`File not found: ${absPath}`);
34981
+ process.exit(1);
34982
+ }
34983
+ const { readFile: readFile3 } = await import("node:fs/promises");
34984
+ const { bundleSubgraphCode } = await import("@secondlayer/bundler");
34985
+ const source = await readFile3(absPath, "utf8");
34986
+ const bundled = await bundleSubgraphCode(source);
34987
+ const pinned = collectPinnedPrintSources(bundled.sources ?? {});
34988
+ if (pinned.length === 0) {
34989
+ error("No pinned print_event sources (contractId set, no trait) — nothing to generate payload types for.");
34990
+ process.exit(1);
34991
+ }
34992
+ const schemas = new Map;
34993
+ for (const contractId of new Set(pinned.map((p) => p.contractId))) {
34994
+ info(`Fetching print schema for ${contractId}...`);
34995
+ try {
34996
+ schemas.set(contractId, await getContractPrintSchema(contractId));
34997
+ } catch (err) {
34998
+ handleApiError(err, "fetch contract print schema");
34999
+ }
35000
+ }
35001
+ const sources = [];
35002
+ for (const p of pinned) {
35003
+ const schema = schemas.get(p.contractId);
35004
+ if (!schema || schema.topics.length === 0) {
35005
+ warn(`No print events observed for ${p.contractId} — skipping source "${p.sourceName}"`);
35006
+ continue;
35007
+ }
35008
+ const topics = p.topic ? schema.topics.filter((t) => t.topic === p.topic) : schema.topics;
35009
+ if (topics.length === 0) {
35010
+ warn(`Topic "${p.topic}" never observed on ${p.contractId} — skipping source "${p.sourceName}"`);
35011
+ continue;
35012
+ }
35013
+ sources.push({
35014
+ sourceName: p.sourceName,
35015
+ contractId: p.contractId,
35016
+ topics
35017
+ });
35018
+ }
35019
+ if (sources.length === 0) {
35020
+ error("No print schemas available for any pinned source. Check the contract ids and that the contracts have emitted print events.");
35021
+ process.exit(1);
35022
+ }
35023
+ const out = generatePrintPayloadTypes({ sources });
35024
+ const outPath = resolve2(output2 ?? join7(dirname5(absPath), `${basename(absPath, extname(absPath))}.payloads.d.ts`));
35025
+ await writeTextFile(outPath, out);
35026
+ success(`Wrote print payload types to ${outPath}`);
35027
+ }
34936
35028
  function parseSubgraphSpecFormat(value) {
34937
35029
  const format = value ?? "openapi";
34938
35030
  if (format === "openapi" || format === "agent" || format === "markdown") {
@@ -35229,12 +35321,22 @@ function formatSubgraphSync(sync) {
35229
35321
  }
35230
35322
  function registerSubgraphsCommand(program2) {
35231
35323
  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", `
35324
+ 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
35325
  Examples:
35234
35326
  $ sl subgraphs create my-graph
35235
- $ sl subgraphs create token-balances --template sip-010-balances`).action(async (name, opts) => {
35327
+ $ sl subgraphs create token-balances --template sip-010-balances
35328
+ $ sl subgraphs create sbtc-flows --from-contract SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry
35329
+ $ sl subgraphs create sbtc-flows --from-contract SM3....sbtc-registry --table-per-topic`).action(async (name, opts) => {
35330
+ if (opts.fromContract && opts.template) {
35331
+ error("--from-contract and --template are mutually exclusive");
35332
+ process.exit(1);
35333
+ }
35334
+ if (opts.tablePerTopic && !opts.fromContract) {
35335
+ error("--table-per-topic requires --from-contract");
35336
+ process.exit(1);
35337
+ }
35236
35338
  const slug = opts.template ?? "basic";
35237
- if (!SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
35339
+ if (!opts.fromContract && !SUBGRAPH_TEMPLATE_SLUGS.includes(slug)) {
35238
35340
  error(`Unknown template "${opts.template}". Available templates:
35239
35341
  ${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESCRIPTIONS[s]}`).join(`
35240
35342
  `)}`);
@@ -35246,13 +35348,37 @@ ${SUBGRAPH_TEMPLATE_SLUGS.map((s) => ` ${s.padEnd(20)} ${SUBGRAPH_TEMPLATE_DESC
35246
35348
  error(`File already exists: ${filePath}`);
35247
35349
  process.exit(1);
35248
35350
  }
35351
+ let content;
35352
+ if (opts.fromContract) {
35353
+ info(`Fetching print schema for ${opts.fromContract}...`);
35354
+ let schema;
35355
+ try {
35356
+ schema = await getContractPrintSchema(opts.fromContract);
35357
+ } catch (err) {
35358
+ handleApiError(err, "fetch contract print schema");
35359
+ }
35360
+ if (!schema || schema.topics.length === 0) {
35361
+ error(`No print events observed for ${opts.fromContract}.
35362
+ Check the contract id, and that the contract has emitted print events (schemas are inferred from indexed on-chain events).`);
35363
+ process.exit(1);
35364
+ }
35365
+ content = await formatCode(generatePrintSchemaSubgraph({
35366
+ contractId: opts.fromContract,
35367
+ name,
35368
+ topics: schema.topics,
35369
+ tablePerTopic: opts.tablePerTopic
35370
+ }));
35371
+ } else {
35372
+ content = generateSubgraphTemplate(name, slug);
35373
+ }
35249
35374
  if (!existsSync4(dir)) {
35250
35375
  mkdirSync3(dir, { recursive: true });
35251
35376
  }
35252
- const content = generateSubgraphTemplate(name, slug);
35253
35377
  await writeTextFile(filePath, content);
35254
35378
  success(`Created ${filePath}`);
35255
- if (slug !== "basic") {
35379
+ if (opts.fromContract) {
35380
+ info(`Schema inferred from ${opts.fromContract} print events (${opts.tablePerTopic ? "table per topic" : "single wide table"})`);
35381
+ } else if (slug !== "basic") {
35256
35382
  info(`Template: ${slug} — ${SUBGRAPH_TEMPLATE_DESCRIPTIONS[slug]}`);
35257
35383
  }
35258
35384
  info(`Next: sl subgraphs deploy subgraphs/${name}.ts`);
@@ -35392,6 +35518,8 @@ Stopped watching.`);
35392
35518
  if (result.start_block_clamped) {
35393
35519
  info(` Free tier indexes forward from deploy (start block ${result.start_block}) — upgrade for genesis backfill.`);
35394
35520
  }
35521
+ for (const w of result.warnings ?? [])
35522
+ warn(w);
35395
35523
  const printDeployFooter = async () => {
35396
35524
  try {
35397
35525
  const { apiUrl } = await resolveAuth();
@@ -35612,7 +35740,16 @@ Synced — exiting watch.`));
35612
35740
  handleApiError(err, "generate subgraph spec");
35613
35741
  }
35614
35742
  });
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) => {
35743
+ 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) => {
35744
+ if (options2.payloads) {
35745
+ const conflicts = ormFlagsConflictingWithPayloads((key) => command.getOptionValueSource(key));
35746
+ if (conflicts.length > 0) {
35747
+ error(`--payloads cannot be combined with ${conflicts.join(", ")} — those flags apply to ORM targets only.`);
35748
+ process.exit(1);
35749
+ }
35750
+ await runPayloadsCodegen(file, options2.output);
35751
+ return;
35752
+ }
35616
35753
  try {
35617
35754
  const target = options2.target ?? "prisma";
35618
35755
  if (target !== "prisma" && target !== "drizzle" && target !== "kysely") {
@@ -37963,5 +38100,5 @@ registerAccountCommand(program);
37963
38100
  registerKeysCommand(program);
37964
38101
  program.parse();
37965
38102
 
37966
- //# debugId=C1F218ABB7E9AF8864756E2164756E21
38103
+ //# debugId=07E11A04E219197464756E2164756E21
37967
38104
  //# sourceMappingURL=cli.js.map