@secondlayer/subgraphs 7.0.1 → 7.0.2

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/index.d.ts CHANGED
@@ -77,13 +77,24 @@ type ChainReadMethods<C extends AbiContract> = { [N in ExtractReadOnlyFunctions<
77
77
  * one and handlers get full inference.
78
78
  */
79
79
  interface ErasedChainReadClient {
80
+ /**
81
+ * Reads a contract's read-only functions at the block being processed.
82
+ *
83
+ * Results are untyped here. Call it through `readContractAt` to get typed
84
+ * results from the contract's ABI.
85
+ */
80
86
  contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
81
87
  read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>;
82
88
  };
83
89
  }
84
90
  /**
85
- * Typed read methods for one contract, from a handler.
91
+ * Reads a contract's read-only functions from a handler, with typed results.
86
92
  *
93
+ * Pass `ctx`, the contract id and its ABI. Every call is pinned to the block
94
+ * being processed. Set `options.cache` to `"contract-constant"` to fetch a
95
+ * value once per contract instead of once per block.
96
+ *
97
+ * @example
87
98
  * ```ts
88
99
  * const token = readContractAt(ctx, contractId, SIP010_ABI, {
89
100
  * cache: "contract-constant",
@@ -669,21 +680,53 @@ interface TypedSubgraphContext<S extends SubgraphSchema> {
669
680
  * `readContractAt(ctx, id, abi)` for full ABI typing at the call site.
670
681
  */
671
682
  client: ErasedChainReadClient;
683
+ /**
684
+ * Queues a new row for a table.
685
+ *
686
+ * Writes are batched and applied together when the block commits.
687
+ * `_block_height` and `_tx_id` are filled in for you.
688
+ */
672
689
  insert<T extends TableName<S>>(table: T, row: WriteRow<S[T]>): void;
690
+ /**
691
+ * Queues an update to the rows matching `where`.
692
+ *
693
+ * `set` holds only the columns to change.
694
+ */
673
695
  update<T extends TableName<S>>(table: T, where: RowWhere<S, T>, set: Partial<WriteRow<S[T]>>): void;
696
+ /**
697
+ * Inserts a row, or updates the one with the same key.
698
+ *
699
+ * `key` should match a `uniqueKeys` constraint of the table. Without one the
700
+ * write falls back to a lookup first and logs a warning.
701
+ */
674
702
  upsert<
675
703
  T extends TableName<S>,
676
704
  K extends Partial<WriteRow<S[T]>>
677
705
  >(table: T, key: K, row: Omit<WriteRow<S[T]>, keyof K> & Partial<WriteRow<S[T]>>): void;
706
+ /** Queues deletion of the rows matching `where`. */
678
707
  delete<T extends TableName<S>>(table: T, where: RowWhere<S, T>): void;
679
708
  /**
680
- * Atomic accumulator — `INSERT … ON CONFLICT (key) DO UPDATE SET col =
681
- * COALESCE(col,0) + delta`. Deltas commute, so it's the reorg-safe primitive
682
- * for running totals (per-cycle aggregates, balances). Requires a `uniqueKeys`
683
- * constraint matching `key`; deltas may be `number` or `bigint`.
709
+ * Adds signed deltas to a counter row, creating it if missing.
710
+ *
711
+ * It compiles to `INSERT … ON CONFLICT (key) DO UPDATE SET col =
712
+ * COALESCE(col,0) + delta`. Deltas commute, so it is the reorg-safe way to
713
+ * keep running totals such as per-cycle aggregates and balances. It needs a
714
+ * `uniqueKeys` constraint matching `key`, and deltas may be `number` or
715
+ * `bigint`.
684
716
  */
685
717
  increment<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, deltas: Partial<Record<ColumnName<S, T>, bigint | number>>): void;
718
+ /**
719
+ * Returns the first row matching `where`, or `null`.
720
+ *
721
+ * Reads see the writes queued earlier in the same block, and rows come back
722
+ * in insertion order.
723
+ */
686
724
  findOne<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]> | null>;
725
+ /**
726
+ * Returns every row matching `where`, in insertion order.
727
+ *
728
+ * Reads see the writes queued earlier in the same block.
729
+ */
687
730
  findMany<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]>[]>;
688
731
  }
689
732
  /** Infer a typed client object from a subgraph definition shape */
@@ -911,8 +954,10 @@ type TypedSubgraphDefinition<
911
954
  handlers: TypedHandlers<Sources, S>;
912
955
  };
913
956
  /**
914
- * Identity function that preserves `sources` and `schema` literal types so
915
- * handlers are typed per source and the schema drives query-client inference.
957
+ * Declares a subgraph and keeps its source and schema literal types.
958
+ *
959
+ * Handlers are typed per source, and the schema drives query-client inference.
960
+ * It returns its argument unchanged.
916
961
  *
917
962
  * @example
918
963
  * ```ts
@@ -934,9 +979,14 @@ declare function defineSubgraph<
934
979
  const S extends SubgraphSchema
935
980
  >(def: TypedSubgraphDefinition<Sources, S>): TypedSubgraphDefinition<Sources, S>;
936
981
  /**
937
- * Identity helper that preserves a schema literal's exact types so it can be
938
- * HOISTED out of the `defineSubgraph()` call and reused:
982
+ * Declares a schema you can hoist out of `defineSubgraph()` and reuse.
983
+ *
984
+ * It keeps the schema's literal types, so table names and row columns stay
985
+ * checked in helpers typed `TypedSubgraphContext<typeof schema>`. `as const`
986
+ * alone does not work: it produces `readonly` arrays that a mutable
987
+ * `uniqueKeys` rejects, and a bare literal widens `type` to `string`.
939
988
  *
989
+ * @example
940
990
  * ```ts
941
991
  * const schema = defineSchema({
942
992
  * balances: {
@@ -945,19 +995,14 @@ declare function defineSubgraph<
945
995
  * },
946
996
  * });
947
997
  *
948
- * // An extracted helper keeps the full typed surface — table names and row
949
- * // columns are still checked:
998
+ * // An extracted helper keeps the full typed surface: table names and row
999
+ * // columns are still checked.
950
1000
  * function credit(ctx: TypedSubgraphContext<typeof schema>, holder: string) {
951
1001
  * ctx.increment("balances", { holder }, { amount: 1n });
952
1002
  * }
953
1003
  *
954
1004
  * defineSubgraph({ name: "balances", schema, sources, handlers });
955
1005
  * ```
956
- *
957
- * `as const` alone does not work here (it produces `readonly` arrays that a
958
- * mutable `uniqueKeys` rejected) and a bare literal widens `type` to `string`.
959
- * That gap is why the shipped starter typed its helper `ctx: any` — and in
960
- * doing so modelled a non-commutative read-modify-write the docs warn against.
961
1006
  */
962
1007
  declare function defineSchema<const S extends SubgraphSchema>(schema: S): S;
963
1008
  /**
@@ -976,14 +1021,18 @@ type InferContext<D> = D extends {
976
1021
  schema: infer S extends SubgraphSchema;
977
1022
  } ? TypedSubgraphContext<S> : never;
978
1023
  /**
979
- * Validates a subgraph definition, returning the parsed result or throwing on failure.
1024
+ * Validates a subgraph definition and returns the parsed result.
1025
+ *
1026
+ * It throws when the definition is invalid.
980
1027
  */
981
1028
  declare function validateSubgraphDefinition(def: unknown): SubgraphDefinition;
982
1029
  /**
983
- * Per-source-type field vocabulary, DERIVED from
984
- * {@link SubgraphFilterSchema}. Agent-facing surfaces (the MCP filters
985
- * reference) used to hand-maintain a parallel copy of this list; deriving it
986
- * means adding a field to a filter can never leave the documentation behind.
1030
+ * Lists the fields each source filter type accepts.
1031
+ *
1032
+ * The list is derived from {@link SubgraphFilterSchema}. Agent-facing surfaces
1033
+ * such as the MCP filters reference used to keep a parallel copy by hand;
1034
+ * deriving it means adding a field to a filter can never leave the
1035
+ * documentation behind.
987
1036
  */
988
1037
  declare function filterFieldsByType(): Array<{
989
1038
  type: string;
@@ -1029,8 +1078,12 @@ interface InferredTopicSchema {
1029
1078
  non_tuple: boolean;
1030
1079
  fields: InferredPrintField[];
1031
1080
  }
1032
- /** Recursively camelize object keys with the print-payload helper (not ABI
1033
- * `toCamelCase` — that one strips `-STX` and prefixes leading digits). */
1081
+ /**
1082
+ * Camelizes object keys recursively, the way print payloads are.
1083
+ *
1084
+ * It uses the print-payload helper, not ABI `toCamelCase`, which strips `-STX`
1085
+ * and prefixes leading digits.
1086
+ */
1034
1087
  declare function camelizeKeys(obj: unknown): unknown;
1035
1088
  /**
1036
1089
  * Infers per-topic field schemas from sampled print events. Counts and
@@ -1062,6 +1115,7 @@ interface HandlerFinding {
1062
1115
  /** 1-based. */
1063
1116
  column: number;
1064
1117
  }
1118
+ /** Formats a handler finding as `file:line:column name: reason`. */
1065
1119
  declare function formatFinding(f: HandlerFinding): string;
1066
1120
  /**
1067
1121
  * Derive how far a subgraph's rows can be checked. Level = the highest any
@@ -1072,8 +1126,10 @@ declare function formatFinding(f: HandlerFinding): string;
1072
1126
  */
1073
1127
  declare function deriveVerification(def: Pick<SubgraphDefinition, "sources" | "backfillMode">, findings?: readonly HandlerFinding[]): SubgraphVerification;
1074
1128
  /**
1075
- * True when the deploy must be refused: the sources are provable (`state`), so
1076
- * the determinism contract is enforced, and the scan broke it.
1129
+ * Tells whether a deploy must be refused for breaking determinism.
1130
+ *
1131
+ * It is refused when the sources are provable (`state`), so the determinism
1132
+ * contract is enforced, and the scan broke it.
1077
1133
  */
1078
1134
  declare function isDeterminismViolation(v: SubgraphVerification): boolean;
1079
1135
  interface PinInput {
@@ -1109,9 +1165,10 @@ declare class HandlerReadError extends Error {
1109
1165
  name: string;
1110
1166
  }
1111
1167
  /**
1112
- * Evaluate a bundled handler (ESM, as stored in `handler_code`) inside a
1113
- * fresh deterministic realm and return its definition with every handler
1114
- * wrapped to receive the {@link deterministicContext} facade.
1168
+ * Loads a bundled handler into a fresh deterministic realm.
1169
+ *
1170
+ * The bundle is ESM, as stored in `handler_code`. The returned definition has
1171
+ * every handler wrapped to receive the {@link deterministicContext} facade.
1115
1172
  */
1116
1173
  declare function loadDeterministicDefinition(handlerCode: string): Promise<SubgraphDefinition>;
1117
1174
  interface GeneratedSQL {
@@ -1135,15 +1192,23 @@ interface PrismaGenOptions {
1135
1192
  */
1136
1193
  modelsOnly?: boolean;
1137
1194
  }
1195
+ /**
1196
+ * Generates a Prisma schema for a subgraph's tables.
1197
+ *
1198
+ * Set `modelsOnly` to emit just the `model` blocks, to compose with your own
1199
+ * schema.
1200
+ */
1138
1201
  declare function generatePrismaSchema(def: SubgraphDefinition, opts?: PrismaGenOptions): string;
1139
1202
  interface DrizzleGenOptions {
1140
1203
  schemaName?: string;
1141
1204
  }
1205
+ /** Generates Drizzle table definitions for a subgraph's tables. */
1142
1206
  declare function generateDrizzleSchema(def: SubgraphDefinition, opts?: DrizzleGenOptions): string;
1143
1207
  interface KyselyGenOptions {
1144
1208
  /** Postgres schema the tables live in (account-scoped). */
1145
1209
  schemaName?: string;
1146
1210
  }
1211
+ /** Generates Kysely table interfaces for a subgraph's tables. */
1147
1212
  declare function generateKyselySchema(def: SubgraphDefinition, opts?: KyselyGenOptions): string;
1148
1213
  /**
1149
1214
  * Emit a portable, typed schema for the public Index read domain (blocks,
@@ -1166,6 +1231,12 @@ interface IndexCodegenOptions {
1166
1231
  /** Prisma only: datasource url env var (default DATABASE_URL). */
1167
1232
  datasourceEnv?: string;
1168
1233
  }
1234
+ /**
1235
+ * Generates a typed schema for Index tables.
1236
+ *
1237
+ * `target` picks Prisma, Kysely, Drizzle or JSON Schema. Use `tables` to limit
1238
+ * the output. Prisma omits tables with no read-set key.
1239
+ */
1169
1240
  declare function generateIndexSchema(target: IndexCodegenTarget, opts?: IndexCodegenOptions): string;
1170
1241
  import { pgSchemaName } from "@secondlayer/shared/db/queries/subgraphs";
1171
1242
  import { Database as Database2 } from "@secondlayer/shared/db";
@@ -1209,10 +1280,11 @@ interface ConstraintDiff {
1209
1280
  */
1210
1281
  declare function diffSchema(existing: SubgraphSchema, incoming: SubgraphSchema): TableDiff;
1211
1282
  /**
1212
- * Returns true if the diff contains any breaking changes
1213
- * (removed tables, removed columns, changed column types, or removed
1214
- * uniqueKeys — handler upserts `ON CONFLICT` against those).
1215
- * Index-flag and composite-index changes are never breaking.
1283
+ * Tells whether a schema diff is breaking, with the reasons.
1284
+ *
1285
+ * Breaking means removed tables, removed columns, changed column types or
1286
+ * removed `uniqueKeys`, which handler upserts conflict on. Index-flag and
1287
+ * composite-index changes are never breaking.
1216
1288
  */
1217
1289
  declare function hasBreakingChanges(diff: TableDiff): {
1218
1290
  breaking: boolean;
@@ -1241,11 +1313,12 @@ interface DeployPlan {
1241
1313
  */
1242
1314
  declare function renderDeployPlan(def: SubgraphDefinition, schemaName?: string): DeployPlan;
1243
1315
  /**
1244
- * Deploy a subgraph schema to the database.
1245
- * - New subgraph → CREATE SCHEMA + tables + register
1246
- * - Same hash → no-op (handler path updated)
1247
- * - Additive change → ALTER TABLE ADD COLUMN / CREATE TABLE for new tables
1248
- * - Breaking change → auto-reindex (drop + recreate)
1316
+ * Deploys a subgraph schema to the database.
1317
+ *
1318
+ * A new subgraph gets its schema and tables created and registered. The same
1319
+ * schema hash only updates the handler path. An additive change adds columns
1320
+ * and tables in place, and a breaking change reindexes by dropping and
1321
+ * recreating the tables.
1249
1322
  */
1250
1323
  declare function deploySchema(db: AnyDb, def: SubgraphDefinition, handlerPath: string, opts?: {
1251
1324
  forceReindex?: boolean;
@@ -1275,14 +1348,20 @@ type SparseProbeTarget = {
1275
1348
  eventType: string;
1276
1349
  contractId?: string;
1277
1350
  };
1278
- /** Sparse scanning is sound only when EVERY source is an event-type filter —
1279
- * a contract_call/contract_deploy source matches transactions, which the
1280
- * event probe can't see. */
1351
+ /**
1352
+ * Tells whether a subgraph can skip blocks without its events.
1353
+ *
1354
+ * Sparse scanning is sound only when every source is an event-type filter. A
1355
+ * `contract_call` or `contract_deploy` source matches transactions, which the
1356
+ * event probe cannot see.
1357
+ */
1281
1358
  declare function canSparseScan(subgraph: SubgraphDefinition): boolean;
1282
1359
  /**
1283
- * The (decoded event type, contract scope) pairs a subgraph's filters can
1284
- * match. One function feeds BOTH the sparse probe and the event walks, so a
1285
- * new contract-pinning filter field is added here once.
1360
+ * Lists the event types and contract scopes a subgraph's filters match.
1361
+ *
1362
+ * Each target is a decoded event type with an optional contract scope. One
1363
+ * function feeds both the sparse probe and the event walks, so a new
1364
+ * contract-pinning filter field is added here once.
1286
1365
  *
1287
1366
  * Per event type: if ANY filter for it is unscoped, a single unscoped target
1288
1367
  * covers everything (today's behavior); otherwise one target per distinct
@@ -1290,12 +1369,13 @@ declare function canSparseScan(subgraph: SubgraphDefinition): boolean;
1290
1369
  */
1291
1370
  declare function sparseProbeTargets(subgraph: SubgraphDefinition): SparseProbeTarget[];
1292
1371
  /**
1293
- * streams-index eligibility: every source must be a known event-type or
1294
- * contract_call/contract_deploy filter (no array-style sources, which leak the
1295
- * unreconstructable `_eventId`). Trait scope IS allowed — trait resolution
1296
- * reads the contract registry on the platform DB (`targetDb`), which the
1297
- * processor always holds, so it's source-independent. Everything else stays on
1298
- * the DB tap.
1372
+ * Tells whether a subgraph's sources can be read from the Streams index.
1373
+ *
1374
+ * Every source must be a known event-type, `contract_call` or
1375
+ * `contract_deploy` filter, and array-style sources never qualify because they
1376
+ * leak the unreconstructable `_eventId`. Trait scope is allowed: trait
1377
+ * resolution reads the contract registry on the platform database, which the
1378
+ * processor always holds. Everything else stays on the database tap.
1299
1379
  */
1300
1380
  declare function isStreamsIndexEligible(subgraph: SubgraphDefinition): boolean;
1301
1381
  interface ReindexOptions {
package/dist/index.js CHANGED
@@ -787,7 +787,7 @@ import { createHash } from "node:crypto";
787
787
  // package.json
788
788
  var package_default = {
789
789
  name: "@secondlayer/subgraphs",
790
- version: "7.0.1",
790
+ version: "7.0.2",
791
791
  description: "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
792
792
  license: "MIT",
793
793
  repository: {
@@ -843,12 +843,13 @@ var package_default = {
843
843
  dev: "bunup --watch",
844
844
  test: "bun test",
845
845
  typecheck: "tsc --noEmit",
846
+ openpkg: "bun scripts/sync-openpkg.ts",
846
847
  prepublishOnly: "bun run build"
847
848
  },
848
849
  dependencies: {
849
- "@secondlayer/shared": "^12.0.0",
850
- "@secondlayer/stacks": "^6.2.0",
851
- "@secondlayer/verify": "^0.5.0",
850
+ "@secondlayer/shared": "^12.1.1",
851
+ "@secondlayer/stacks": "^6.2.1",
852
+ "@secondlayer/verify": "^0.5.3",
852
853
  esbuild: "^0.28.2",
853
854
  kysely: "0.28.17",
854
855
  zod: "^4.3.6"
@@ -2948,5 +2949,5 @@ export {
2948
2949
  validateSubgraphDefinition
2949
2950
  };
2950
2951
 
2951
- //# debugId=576C0AFC5A24E02A64756E2164756E21
2952
+ //# debugId=C76A905109964E7E64756E2164756E21
2952
2953
  //# sourceMappingURL=index.js.map