@secondlayer/subgraphs 4.4.1 → 5.0.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.
Files changed (64) hide show
  1. package/README.md +13 -21
  2. package/dist/{src/index.d.ts → index.d.ts} +59 -189
  3. package/dist/index.js +2151 -0
  4. package/dist/index.js.map +24 -0
  5. package/dist/{src/runtime → runtime}/emitter.d.ts +1 -1
  6. package/dist/{src/runtime → runtime}/emitter.js +8 -12
  7. package/dist/{src/runtime → runtime}/emitter.js.map +3 -3
  8. package/dist/{src/runtime → runtime}/replay.d.ts +1 -1
  9. package/dist/{src/runtime → runtime}/replay.js +342 -683
  10. package/dist/{src/runtime → runtime}/replay.js.map +5 -5
  11. package/dist/{src/schema → schema}/index.d.ts +10 -69
  12. package/dist/{src/schema → schema}/index.js +188 -281
  13. package/dist/schema/index.js.map +13 -0
  14. package/dist/{src/testing → testing}/index.d.ts +65 -115
  15. package/dist/{src/testing → testing}/index.js +554 -968
  16. package/dist/testing/index.js.map +21 -0
  17. package/dist/{src/types.d.ts → types.d.ts} +10 -66
  18. package/dist/{src/validate.d.ts → validate.d.ts} +11 -69
  19. package/dist/{src/validate.js → validate.js} +18 -98
  20. package/dist/validate.js.map +10 -0
  21. package/package.json +18 -26
  22. package/dist/src/index.js +0 -6081
  23. package/dist/src/index.js.map +0 -44
  24. package/dist/src/runtime/block-processor.d.ts +0 -559
  25. package/dist/src/runtime/block-processor.js +0 -3810
  26. package/dist/src/runtime/block-processor.js.map +0 -31
  27. package/dist/src/runtime/catchup.d.ts +0 -473
  28. package/dist/src/runtime/catchup.js +0 -4228
  29. package/dist/src/runtime/catchup.js.map +0 -35
  30. package/dist/src/runtime/clarity.d.ts +0 -15
  31. package/dist/src/runtime/clarity.js +0 -41
  32. package/dist/src/runtime/clarity.js.map +0 -10
  33. package/dist/src/runtime/context.d.ts +0 -325
  34. package/dist/src/runtime/context.js +0 -936
  35. package/dist/src/runtime/context.js.map +0 -13
  36. package/dist/src/runtime/processor.d.ts +0 -11
  37. package/dist/src/runtime/processor.js +0 -5372
  38. package/dist/src/runtime/processor.js.map +0 -40
  39. package/dist/src/runtime/reindex.d.ts +0 -539
  40. package/dist/src/runtime/reindex.js +0 -4802
  41. package/dist/src/runtime/reindex.js.map +0 -37
  42. package/dist/src/runtime/reorg.d.ts +0 -432
  43. package/dist/src/runtime/reorg.js +0 -4355
  44. package/dist/src/runtime/reorg.js.map +0 -36
  45. package/dist/src/runtime/runner.d.ts +0 -719
  46. package/dist/src/runtime/runner.js +0 -1332
  47. package/dist/src/runtime/runner.js.map +0 -16
  48. package/dist/src/runtime/source-matcher.d.ts +0 -304
  49. package/dist/src/runtime/source-matcher.js +0 -335
  50. package/dist/src/runtime/source-matcher.js.map +0 -10
  51. package/dist/src/runtime/stats.d.ts +0 -23
  52. package/dist/src/runtime/stats.js +0 -71
  53. package/dist/src/runtime/stats.js.map +0 -10
  54. package/dist/src/schema/index.js.map +0 -13
  55. package/dist/src/service.d.ts +0 -0
  56. package/dist/src/service.js +0 -5398
  57. package/dist/src/service.js.map +0 -41
  58. package/dist/src/testing/index.js.map +0 -22
  59. package/dist/src/triggers/index.d.ts +0 -381
  60. package/dist/src/triggers/index.js +0 -31
  61. package/dist/src/triggers/index.js.map +0 -10
  62. package/dist/src/validate.js.map +0 -10
  63. /package/dist/{src/types.js → types.js} +0 -0
  64. /package/dist/{src/types.js.map → types.js.map} +0 -0
@@ -39,22 +39,6 @@ interface SubgraphColumn {
39
39
  default?: string | number | boolean;
40
40
  }
41
41
  /**
42
- * A foreign-key relation to another table in the same subgraph. Drives DDL FK
43
- * constraints and ORM codegen (`@relation` in Prisma, `relations()` in Drizzle)
44
- * so generated clients get typed joins. The referenced columns must form a
45
- * `uniqueKeys` entry on the target table.
46
- */
47
- interface SubgraphRelation {
48
- /** Relation field name on this table's generated model (e.g. "pool"). */
49
- name: string;
50
- /** Target table name in this subgraph. */
51
- references: string;
52
- /** Local column(s) holding the foreign key. */
53
- fields: string[];
54
- /** Target column(s) the fields point at (a uniqueKeys entry on the target). */
55
- referencedColumns: string[];
56
- }
57
- /**
58
42
  * Table definition within a subgraph schema.
59
43
  *
60
44
  * The array fields are `readonly` so a schema literal can be hoisted out of
@@ -70,8 +54,6 @@ interface SubgraphTable {
70
54
  indexes?: readonly (readonly string[])[];
71
55
  /** Unique key constraints (each entry is an array of column names). Required for upsert. */
72
56
  uniqueKeys?: readonly (readonly string[])[];
73
- /** Foreign-key relations to other tables (for typed ORM joins). */
74
- relations?: readonly SubgraphRelation[];
75
57
  }
76
58
  /** Subgraph schema — maps table names to table definitions */
77
59
  type SubgraphSchema = Record<string, SubgraphTable>;
@@ -234,9 +216,8 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
234
216
  /**
235
217
  * One contract id, or a SET of them (max 20) — the standard DeFi shape is
236
218
  * a router plus N pools, which used to cost N near-identical sources and
237
- * handlers, or the `"*"` catch-all that erases per-source typing. Payload
238
- * types are identical per `type`, so one handler serves the set and
239
- * `event.contractId` disambiguates.
219
+ * handlers. Payload types are identical per `type`, so one handler serves
220
+ * the set and `event.contractId` disambiguates.
240
221
  *
241
222
  * Supports `*` wildcards (e.g. `"SP1ABC….pool-*"`). Mutually exclusive
242
223
  * with `trait`, which resolves its own set per block.
@@ -250,8 +231,11 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
250
231
  * definition and used at runtime to decode args by name. Omit to keep
251
232
  * `event.args` as a positional `unknown[]`.
252
233
  *
253
- * Deploy validation requires `abi` whenever `functionName` is set
254
- * (`normalizeAbi()` from `@secondlayer/stacks/clarity`).
234
+ * Required whenever `functionName` is set. `secondlayer subgraphs deploy`
235
+ * fills it in from the deployed contract for a single concrete
236
+ * `contractId`; pass it yourself for wildcard, multi-contract or trait
237
+ * sources, or a local deploy (`normalizeAbi()` from
238
+ * `@secondlayer/stacks/clarity`).
255
239
  */
256
240
  abi?: AbiContract2;
257
241
  }
@@ -308,29 +292,9 @@ type PrintField = ColumnType | {
308
292
  * is skipped and logged rather than written as nulls.
309
293
  */
310
294
  type PrintEventPrints = Record<string, Record<string, PrintField>>;
311
- /**
312
- * One column in a static identity map. Literals only — the bundler never
313
- * executes user code, so `{ from: "tokenX" }` is valid and `from("tokenX")`
314
- * is not.
315
- */
316
- type MaterializeColumn = {
317
- from: string
318
- } | {
319
- fromTx: "sender" | "txId"
320
- } | {
321
- fromBlock: "height" | "hash" | "timestamp"
322
- };
323
- /** Static insert from a source event — replaces a 1:1 handler. */
324
- interface MaterializeSpec {
325
- table: string;
326
- /** Keys = schema column names (snake). */
327
- columns: Record<string, MaterializeColumn>;
328
- }
329
295
  type PrintEventFields = FactoryScope & {
330
296
  type: "print_event"
331
297
  topic?: string
332
- /** Identity map: insert without a handler function. XOR with handlers[name]. */
333
- materialize?: MaterializeSpec
334
298
  };
335
299
  /**
336
300
  * Pinned to one or more contract ids with no trait — `prints` is required so
@@ -376,8 +340,6 @@ interface TxMeta {
376
340
  }
377
341
  /** Scalar types that can appear as row values */
378
342
  type RowValue = string | number | bigint | boolean | null | undefined | Record<string, unknown> | unknown[];
379
- /** Value or computed function that receives existing row */
380
- type ComputedValue = RowValue | ((existing: Record<string, unknown> | null) => unknown);
381
343
  /** Context passed to subgraph handlers during event processing */
382
344
  interface SubgraphContext {
383
345
  block: {
@@ -408,27 +370,11 @@ interface SubgraphContext {
408
370
  * Atomic counter update — the blessed accumulator primitive. Applies
409
371
  * `col = COALESCE(col, 0) + delta` per column (insert-or-add); deltas may
410
372
  * be negative. Requires a uniqueKeys constraint matching `key`. Prefer
411
- * this over patchOrInsert with functional updaters for running totals.
373
+ * this over read-modify-write handlers for running totals.
412
374
  */
413
375
  increment(table: string, key: Record<string, unknown>, deltas: Record<string, bigint | number>): void;
414
- /** Partial update — sets only specified fields, preserves others */
415
- patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
416
- /** Find-then-merge-or-insert. Values can be functions: (existing) => newValue */
417
- patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
418
376
  findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
419
377
  findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
420
- /** Format a bigint amount with decimal places */
421
- formatUnits(value: bigint, decimals: number): string;
422
- /** Count rows matching filter */
423
- count(table: string, where?: Record<string, unknown>): Promise<number>;
424
- /** Sum a numeric column */
425
- sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
426
- /** Min of a numeric column */
427
- min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
428
- /** Max of a numeric column */
429
- max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
430
- /** Count distinct values in a column */
431
- countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
432
378
  }
433
379
  /** Handler function that processes events and writes to the subgraph */
434
380
  type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) => Promise<void> | void;
@@ -436,8 +382,6 @@ type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) =>
436
382
  interface SubgraphDefinition {
437
383
  /** Unique subgraph name (lowercase, alphanumeric + hyphens) */
438
384
  name: string;
439
- /** Semantic version */
440
- version?: string;
441
385
  /** Human description */
442
386
  description?: string;
443
387
  /** Block height to start indexing from (default: 1) */
@@ -449,7 +393,7 @@ interface SubgraphDefinition {
449
393
  sources: Record<string, SubgraphFilter>;
450
394
  /** Tables in this subgraph */
451
395
  schema: SubgraphSchema;
452
- /** Handler functions — keys must match source names (or "*" for catch-all) */
396
+ /** Handler functions, one per source, keyed by source name */
453
397
  handlers: Record<string, SubgraphHandler>;
454
398
  }
455
- export { VarSetFilter, UnpinnedPrintEventFilter, TxMeta, TraitPrintEventFilter, SubgraphTable, SubgraphSchema, SubgraphRelation, SubgraphHandler, SubgraphFilter, SubgraphDefinition, SubgraphContext, SubgraphColumn, StxTransferFilter, StxMintFilter, StxLockFilter, StxBurnFilter, RowValue, PrintField, PrintEventPrints, PrintEventFilter, PinnedPrintEventFilter, NftTransferFilter, NftMintFilter, NftBurnFilter, NestedContractCallFilter, MaterializeSpec, MaterializeColumn, MapWriteFilter, FtTransferFilter, FtMintFilter, FtBurnFilter, FactoryScope, ContractDeployFilter, ContractCallFilter, ContractCallEvent, ComputedValue, ColumnType };
399
+ export { ColumnType, ContractCallEvent, ContractCallFilter, ContractDeployFilter, FactoryScope, FtBurnFilter, FtMintFilter, FtTransferFilter, MapWriteFilter, NestedContractCallFilter, NftBurnFilter, NftMintFilter, NftTransferFilter, PinnedPrintEventFilter, PrintEventFilter, PrintEventPrints, PrintField, RowValue, StxBurnFilter, StxLockFilter, StxMintFilter, StxTransferFilter, SubgraphColumn, SubgraphContext, SubgraphDefinition, SubgraphFilter, SubgraphHandler, SubgraphSchema, SubgraphTable, TraitPrintEventFilter, TxMeta, UnpinnedPrintEventFilter, VarSetFilter };
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
2
3
  import { AssetIdentifier } from "@secondlayer/stacks/filters";
3
4
  /**
@@ -39,22 +40,6 @@ interface SubgraphColumn {
39
40
  default?: string | number | boolean;
40
41
  }
41
42
  /**
42
- * A foreign-key relation to another table in the same subgraph. Drives DDL FK
43
- * constraints and ORM codegen (`@relation` in Prisma, `relations()` in Drizzle)
44
- * so generated clients get typed joins. The referenced columns must form a
45
- * `uniqueKeys` entry on the target table.
46
- */
47
- interface SubgraphRelation {
48
- /** Relation field name on this table's generated model (e.g. "pool"). */
49
- name: string;
50
- /** Target table name in this subgraph. */
51
- references: string;
52
- /** Local column(s) holding the foreign key. */
53
- fields: string[];
54
- /** Target column(s) the fields point at (a uniqueKeys entry on the target). */
55
- referencedColumns: string[];
56
- }
57
- /**
58
43
  * Table definition within a subgraph schema.
59
44
  *
60
45
  * The array fields are `readonly` so a schema literal can be hoisted out of
@@ -70,8 +55,6 @@ interface SubgraphTable {
70
55
  indexes?: readonly (readonly string[])[];
71
56
  /** Unique key constraints (each entry is an array of column names). Required for upsert. */
72
57
  uniqueKeys?: readonly (readonly string[])[];
73
- /** Foreign-key relations to other tables (for typed ORM joins). */
74
- relations?: readonly SubgraphRelation[];
75
58
  }
76
59
  /** Subgraph schema — maps table names to table definitions */
77
60
  type SubgraphSchema = Record<string, SubgraphTable>;
@@ -193,9 +176,8 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
193
176
  /**
194
177
  * One contract id, or a SET of them (max 20) — the standard DeFi shape is
195
178
  * a router plus N pools, which used to cost N near-identical sources and
196
- * handlers, or the `"*"` catch-all that erases per-source typing. Payload
197
- * types are identical per `type`, so one handler serves the set and
198
- * `event.contractId` disambiguates.
179
+ * handlers. Payload types are identical per `type`, so one handler serves
180
+ * the set and `event.contractId` disambiguates.
199
181
  *
200
182
  * Supports `*` wildcards (e.g. `"SP1ABC….pool-*"`). Mutually exclusive
201
183
  * with `trait`, which resolves its own set per block.
@@ -209,8 +191,11 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
209
191
  * definition and used at runtime to decode args by name. Omit to keep
210
192
  * `event.args` as a positional `unknown[]`.
211
193
  *
212
- * Deploy validation requires `abi` whenever `functionName` is set
213
- * (`normalizeAbi()` from `@secondlayer/stacks/clarity`).
194
+ * Required whenever `functionName` is set. `secondlayer subgraphs deploy`
195
+ * fills it in from the deployed contract for a single concrete
196
+ * `contractId`; pass it yourself for wildcard, multi-contract or trait
197
+ * sources, or a local deploy (`normalizeAbi()` from
198
+ * `@secondlayer/stacks/clarity`).
214
199
  */
215
200
  abi?: AbiContract2;
216
201
  }
@@ -267,29 +252,9 @@ type PrintField = ColumnType | {
267
252
  * is skipped and logged rather than written as nulls.
268
253
  */
269
254
  type PrintEventPrints = Record<string, Record<string, PrintField>>;
270
- /**
271
- * One column in a static identity map. Literals only — the bundler never
272
- * executes user code, so `{ from: "tokenX" }` is valid and `from("tokenX")`
273
- * is not.
274
- */
275
- type MaterializeColumn = {
276
- from: string
277
- } | {
278
- fromTx: "sender" | "txId"
279
- } | {
280
- fromBlock: "height" | "hash" | "timestamp"
281
- };
282
- /** Static insert from a source event — replaces a 1:1 handler. */
283
- interface MaterializeSpec {
284
- table: string;
285
- /** Keys = schema column names (snake). */
286
- columns: Record<string, MaterializeColumn>;
287
- }
288
255
  type PrintEventFields = FactoryScope & {
289
256
  type: "print_event"
290
257
  topic?: string
291
- /** Identity map: insert without a handler function. XOR with handlers[name]. */
292
- materialize?: MaterializeSpec
293
258
  };
294
259
  /**
295
260
  * Pinned to one or more contract ids with no trait — `prints` is required so
@@ -333,10 +298,6 @@ interface TxMeta {
333
298
  contractId?: string | null;
334
299
  functionName?: string | null;
335
300
  }
336
- /** Scalar types that can appear as row values */
337
- type RowValue = string | number | bigint | boolean | null | undefined | Record<string, unknown> | unknown[];
338
- /** Value or computed function that receives existing row */
339
- type ComputedValue = RowValue | ((existing: Record<string, unknown> | null) => unknown);
340
301
  /** Context passed to subgraph handlers during event processing */
341
302
  interface SubgraphContext {
342
303
  block: {
@@ -367,27 +328,11 @@ interface SubgraphContext {
367
328
  * Atomic counter update — the blessed accumulator primitive. Applies
368
329
  * `col = COALESCE(col, 0) + delta` per column (insert-or-add); deltas may
369
330
  * be negative. Requires a uniqueKeys constraint matching `key`. Prefer
370
- * this over patchOrInsert with functional updaters for running totals.
331
+ * this over read-modify-write handlers for running totals.
371
332
  */
372
333
  increment(table: string, key: Record<string, unknown>, deltas: Record<string, bigint | number>): void;
373
- /** Partial update — sets only specified fields, preserves others */
374
- patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
375
- /** Find-then-merge-or-insert. Values can be functions: (existing) => newValue */
376
- patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
377
334
  findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
378
335
  findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
379
- /** Format a bigint amount with decimal places */
380
- formatUnits(value: bigint, decimals: number): string;
381
- /** Count rows matching filter */
382
- count(table: string, where?: Record<string, unknown>): Promise<number>;
383
- /** Sum a numeric column */
384
- sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
385
- /** Min of a numeric column */
386
- min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
387
- /** Max of a numeric column */
388
- max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
389
- /** Count distinct values in a column */
390
- countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
391
336
  }
392
337
  /** Handler function that processes events and writes to the subgraph */
393
338
  type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) => Promise<void> | void;
@@ -395,8 +340,6 @@ type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) =>
395
340
  interface SubgraphDefinition {
396
341
  /** Unique subgraph name (lowercase, alphanumeric + hyphens) */
397
342
  name: string;
398
- /** Semantic version */
399
- version?: string;
400
343
  /** Human description */
401
344
  description?: string;
402
345
  /** Block height to start indexing from (default: 1) */
@@ -408,10 +351,9 @@ interface SubgraphDefinition {
408
351
  sources: Record<string, SubgraphFilter>;
409
352
  /** Tables in this subgraph */
410
353
  schema: SubgraphSchema;
411
- /** Handler functions — keys must match source names (or "*" for catch-all) */
354
+ /** Handler functions, one per source, keyed by source name */
412
355
  handlers: Record<string, SubgraphHandler>;
413
356
  }
414
- import { z } from "zod";
415
357
  declare const SubgraphNameSchema: z.ZodType<string>;
416
358
  /**
417
359
  * A safe SQL identifier (table or column name). Mirrors the runtime guard in
@@ -466,4 +408,4 @@ declare function filterFieldsByType(): Array<{
466
408
  type: string
467
409
  fields: string[]
468
410
  }>;
469
- export { validateSubgraphDefinition, filterFieldsByType, VALID_FILTER_TYPES, SubgraphTableSchema, SubgraphSchemaSchema, SubgraphNameSchema, SubgraphFilterSchema, SubgraphDefinitionSchema, SubgraphColumnSchema, SqlIdentifierSchema, PrintFieldSchema, ColumnTypeSchema, AbiContractSchema };
411
+ export { AbiContractSchema, ColumnTypeSchema, PrintFieldSchema, SqlIdentifierSchema, SubgraphColumnSchema, SubgraphDefinitionSchema, SubgraphFilterSchema, SubgraphNameSchema, SubgraphSchemaSchema, SubgraphTableSchema, VALID_FILTER_TYPES, filterFieldsByType, validateSubgraphDefinition };
@@ -1,6 +1,3 @@
1
- import { createRequire } from "node:module";
2
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
-
4
1
  // src/validate.ts
5
2
  import { z } from "zod";
6
3
  var SubgraphNameSchema = z.string().min(1).max(63).regex(/^[a-z][a-z0-9-]*$/, "Must start with lowercase letter, contain only lowercase alphanumeric and hyphens");
@@ -62,13 +59,7 @@ var SubgraphColumnSchema = z.object({
62
59
  var SubgraphTableSchema = z.object({
63
60
  columns: z.record(SqlIdentifierSchema, SubgraphColumnSchema).refine((c) => Object.keys(c).length > 0, "Table must have at least one column"),
64
61
  indexes: z.array(z.array(SqlIdentifierSchema)).optional(),
65
- uniqueKeys: z.array(z.array(SqlIdentifierSchema)).optional(),
66
- relations: z.array(z.object({
67
- name: SqlIdentifierSchema,
68
- references: SqlIdentifierSchema,
69
- fields: z.array(SqlIdentifierSchema).min(1),
70
- referencedColumns: z.array(SqlIdentifierSchema).min(1)
71
- })).optional()
62
+ uniqueKeys: z.array(z.array(SqlIdentifierSchema)).optional()
72
63
  });
73
64
  var SubgraphSchemaSchema = z.record(SqlIdentifierSchema, SubgraphTableSchema).refine((s) => Object.keys(s).length > 0, "Schema must have at least one table");
74
65
  var VALID_FILTER_TYPES = [
@@ -103,15 +94,6 @@ var amountRange = {
103
94
  minAmount: z.bigint().optional(),
104
95
  maxAmount: z.bigint().optional()
105
96
  };
106
- var MaterializeColumnSchema = z.union([
107
- z.object({ from: z.string().min(1) }).strict(),
108
- z.object({ fromTx: z.enum(["sender", "txId"]) }).strict(),
109
- z.object({ fromBlock: z.enum(["height", "hash", "timestamp"]) }).strict()
110
- ]);
111
- var MaterializeSpecSchema = z.object({
112
- table: z.string().min(1),
113
- columns: z.record(z.string(), MaterializeColumnSchema)
114
- }).strict();
115
97
  var SubgraphFilterUnion = z.discriminatedUnion("type", [
116
98
  z.object({
117
99
  type: z.literal("stx_transfer"),
@@ -194,7 +176,6 @@ var SubgraphFilterUnion = z.discriminatedUnion("type", [
194
176
  contractId: contractIdField.optional(),
195
177
  topic: z.string().optional(),
196
178
  prints: z.record(z.string(), z.record(z.string(), PrintFieldSchema)).optional(),
197
- materialize: MaterializeSpecSchema.optional(),
198
179
  ...traitScope,
199
180
  ...factoryScope
200
181
  }).strict(),
@@ -244,54 +225,6 @@ function hasPinnedContractId(contractId) {
244
225
  return contractId.length > 0;
245
226
  return false;
246
227
  }
247
- function printMaterializeFromKeys(prints) {
248
- const keys = new Set(["topic"]);
249
- if (prints) {
250
- for (const fields of Object.values(prints)) {
251
- for (const k of Object.keys(fields))
252
- keys.add(k);
253
- }
254
- }
255
- return [...keys].sort();
256
- }
257
- function refineMaterialize(name, filter, schema, ctx) {
258
- if (!("materialize" in filter) || filter.materialize === undefined)
259
- return;
260
- const spec = filter.materialize;
261
- const table = schema[spec.table];
262
- if (!table) {
263
- ctx.addIssue({
264
- code: "custom",
265
- path: ["sources", name, "materialize", "table"],
266
- message: `materialize table "${spec.table}" is not in schema`
267
- });
268
- return;
269
- }
270
- for (const col of Object.keys(spec.columns)) {
271
- if (!(col in table.columns)) {
272
- ctx.addIssue({
273
- code: "custom",
274
- path: ["sources", name, "materialize", "columns", col],
275
- message: `materialize column "${col}" is not on schema table "${spec.table}"`
276
- });
277
- }
278
- }
279
- if (filter.type === "print_event") {
280
- const known = printMaterializeFromKeys(filter.prints);
281
- const knownSet = new Set(known);
282
- for (const [col, mapping] of Object.entries(spec.columns)) {
283
- if (!("from" in mapping))
284
- continue;
285
- if (!knownSet.has(mapping.from)) {
286
- ctx.addIssue({
287
- code: "custom",
288
- path: ["sources", name, "materialize", "columns", col, "from"],
289
- message: `materialize from "${mapping.from}" is not a known print field — known: ${known.join(", ")}`
290
- });
291
- }
292
- }
293
- }
294
- }
295
228
  function refineDeployGates(def, ctx) {
296
229
  for (const [name, filter] of Object.entries(def.sources)) {
297
230
  if (filter.type === "print_event") {
@@ -312,36 +245,23 @@ function refineDeployGates(def, ctx) {
312
245
  ctx.addIssue({
313
246
  code: "custom",
314
247
  path: ["sources", name, "abi"],
315
- message: `contract_call source "${name}" has functionName but no abi — pass a canonical ABI (normalizeAbi() from @secondlayer/stacks/clarity).`
248
+ message: `contract_call source "${name}" has functionName but no abi. \`secondlayer subgraphs deploy\` fills it in from the deployed contract; otherwise pass abi (normalizeAbi() from @secondlayer/stacks/clarity).`
316
249
  });
317
250
  }
318
251
  }
319
- refineMaterialize(name, filter, def.schema, ctx);
320
252
  }
321
- const hasCatchAll = def.handlers["*"] != null;
322
- for (const [name, filter] of Object.entries(def.sources)) {
323
- const hasMaterialize = "materialize" in filter && filter.materialize !== undefined;
324
- const hasHandler = def.handlers[name] != null;
325
- if (hasMaterialize && hasHandler) {
326
- ctx.addIssue({
327
- code: "custom",
328
- path: ["handlers", name],
329
- message: `source "${name}" has both materialize and a handler — use one or the other`
330
- });
331
- continue;
332
- }
333
- if (!hasHandler && !hasMaterialize && !hasCatchAll) {
253
+ for (const name of Object.keys(def.sources)) {
254
+ if (def.handlers[name] == null) {
334
255
  ctx.addIssue({
335
256
  code: "custom",
336
257
  path: ["handlers", name],
337
- message: `source "${name}" has no handler (and no "*") — events will be skipped and the table stay empty.`
258
+ message: `source "${name}" has no handler. Add handlers.${name}, or its events are skipped and the table stays empty.`
338
259
  });
339
260
  }
340
261
  }
341
262
  }
342
263
  var SubgraphDefinitionSchema = z.object({
343
264
  name: SubgraphNameSchema,
344
- version: z.string().optional(),
345
265
  description: z.string().optional(),
346
266
  startBlock: z.number().int().nonnegative().optional(),
347
267
  backfillMode: z.enum(["blocking", "concurrent"]).optional(),
@@ -372,20 +292,20 @@ function filterFieldsByType() {
372
292
  return out;
373
293
  }
374
294
  export {
375
- validateSubgraphDefinition,
376
- filterFieldsByType,
377
- VALID_FILTER_TYPES,
378
- SubgraphTableSchema,
379
- SubgraphSchemaSchema,
380
- SubgraphNameSchema,
381
- SubgraphFilterSchema,
382
- SubgraphDefinitionSchema,
383
- SubgraphColumnSchema,
384
- SqlIdentifierSchema,
385
- PrintFieldSchema,
295
+ AbiContractSchema,
386
296
  ColumnTypeSchema,
387
- AbiContractSchema
297
+ PrintFieldSchema,
298
+ SqlIdentifierSchema,
299
+ SubgraphColumnSchema,
300
+ SubgraphDefinitionSchema,
301
+ SubgraphFilterSchema,
302
+ SubgraphNameSchema,
303
+ SubgraphSchemaSchema,
304
+ SubgraphTableSchema,
305
+ VALID_FILTER_TYPES,
306
+ filterFieldsByType,
307
+ validateSubgraphDefinition
388
308
  };
389
309
 
390
- //# debugId=13B997638E1D491964756E2164756E21
310
+ //# debugId=BFED63A6F6DDAA5F64756E2164756E21
391
311
  //# sourceMappingURL=validate.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/validate.ts"],
4
+ "sourcesContent": [
5
+ "import { z } from \"zod\";\nimport type {\n\tColumnType,\n\tSubgraphColumn,\n\tSubgraphDefinition,\n\tSubgraphFilter,\n\tSubgraphSchema,\n\tSubgraphTable,\n} from \"./types.ts\";\n\nexport const SubgraphNameSchema: z.ZodType<string> = z\n\t.string()\n\t.min(1)\n\t.max(63)\n\t.regex(\n\t\t/^[a-z][a-z0-9-]*$/,\n\t\t\"Must start with lowercase letter, contain only lowercase alphanumeric and hyphens\",\n\t);\n\n/**\n * A safe SQL identifier (table or column name). Mirrors the runtime guard in\n * runtime/context.ts (validateColumnName) so the schema validator can never\n * accept a name the runtime would reject — and closes the deploy-time DDL\n * injection path in schema/generator.ts, which interpolates these names raw.\n */\nexport const SqlIdentifierSchema: z.ZodType<string> = z\n\t.string()\n\t.min(1)\n\t.max(63) // Postgres truncates identifiers > 63 bytes; reject rather than collide.\n\t.regex(\n\t\t/^[a-z_][a-z0-9_]*$/i,\n\t\t\"Must be a valid SQL identifier: start with a letter or underscore, then letters/digits/underscores only\",\n\t);\n\nexport const ColumnTypeSchema: z.ZodType<ColumnType> = z.enum([\n\t\"text\",\n\t\"uint\",\n\t\"int\",\n\t\"principal\",\n\t\"boolean\",\n\t\"timestamp\",\n\t\"jsonb\",\n]);\n\n/**\n * One declared print field: a bare column type, or a composite (optional,\n * nested tuple, list). Recursive — real print payloads nest, and a vocabulary\n * that could only say `\"jsonb\"` is what let a flat-field declaration pass\n * while every event decoded to null.\n */\nexport const PrintFieldSchema: z.ZodType<unknown> = z.lazy(() =>\n\tz.union([\n\t\tColumnTypeSchema,\n\t\tz.object({ type: PrintFieldSchema, optional: z.literal(true) }),\n\t\tz.object({ tuple: z.record(z.string(), PrintFieldSchema) }),\n\t\tz.object({ list: PrintFieldSchema }),\n\t]),\n);\n\n/**\n * A Clarity ABI type: a primitive name, or one of the composite shapes.\n * Recursive, so nested tuples/lists/optionals are checked all the way down.\n */\nconst AbiTypeSchema: z.ZodType<unknown> = z.lazy(() =>\n\tz.union([\n\t\tz.string(),\n\t\tz.object({ buff: z.object({ length: z.number() }) }),\n\t\tz.object({ \"string-ascii\": z.object({ length: z.number() }) }),\n\t\tz.object({ \"string-utf8\": z.object({ length: z.number() }) }),\n\t\tz.object({ optional: AbiTypeSchema }),\n\t\tz.object({\n\t\t\tlist: z.object({ type: AbiTypeSchema, length: z.number() }),\n\t\t}),\n\t\tz.object({\n\t\t\ttuple: z.array(z.object({ name: z.string(), type: AbiTypeSchema })),\n\t\t}),\n\t\tz.object({\n\t\t\tresponse: z.object({ ok: AbiTypeSchema, error: AbiTypeSchema }),\n\t\t}),\n\t]),\n);\n\n/**\n * The canonical `AbiContract` shape, validated at deploy time.\n *\n * This used to be `z.record(z.string(), z.any())`, which accepted a raw\n * Hiro/Clarinet ABI (`read_only` access, `buffer` types, outputs wrapped as\n * `{ type: … }`) and let it through — the deploy succeeded and `event.input`\n * then mis-decoded at RUNTIME, per event, forever. Reject it here instead,\n * and name the fix: run it through `normalizeAbi` from\n * `@secondlayer/stacks/clarity`.\n */\nexport const AbiContractSchema: z.ZodType<unknown> = z.object({\n\tfunctions: z.array(\n\t\tz.object({\n\t\t\tname: z.string(),\n\t\t\taccess: z.enum([\"public\", \"read-only\", \"private\"], {\n\t\t\t\tmessage:\n\t\t\t\t\t\"ABI access must be public | read-only | private — a raw Hiro/Clarinet ABI uses `read_only`. Normalize it first: normalizeAbi() from @secondlayer/stacks/clarity.\",\n\t\t\t}),\n\t\t\targs: z.array(z.object({ name: z.string(), type: AbiTypeSchema })),\n\t\t\t// Canonical shape is a bare AbiType; raw ABIs wrap it as `{ type: … }`.\n\t\t\toutputs: AbiTypeSchema,\n\t\t}),\n\t),\n\tmaps: z.array(z.unknown()).optional(),\n\tvariables: z.array(z.unknown()).optional(),\n\tfungible_tokens: z.array(z.unknown()).optional(),\n\tnon_fungible_tokens: z.array(z.unknown()).optional(),\n\timplemented_traits: z.array(z.unknown()).optional(),\n\tdefined_traits: z.array(z.unknown()).optional(),\n});\n\nexport const SubgraphColumnSchema: z.ZodType<SubgraphColumn> = z.object({\n\ttype: ColumnTypeSchema,\n\tnullable: z.boolean().optional(),\n\tindexed: z.boolean().optional(),\n\tsearch: z.boolean().optional(),\n\tdefault: z.union([z.string(), z.number(), z.boolean()]).optional(),\n}) as z.ZodType<SubgraphColumn>;\n\nexport const SubgraphTableSchema: z.ZodType<SubgraphTable> = z.object({\n\tcolumns: z\n\t\t.record(SqlIdentifierSchema, SubgraphColumnSchema)\n\t\t.refine(\n\t\t\t(c) => Object.keys(c).length > 0,\n\t\t\t\"Table must have at least one column\",\n\t\t),\n\tindexes: z.array(z.array(SqlIdentifierSchema)).optional(),\n\tuniqueKeys: z.array(z.array(SqlIdentifierSchema)).optional(),\n}) as z.ZodType<SubgraphTable>;\n\nexport const SubgraphSchemaSchema: z.ZodType<Record<string, SubgraphTable>> = z\n\t.record(SqlIdentifierSchema, SubgraphTableSchema)\n\t.refine(\n\t\t(s) => Object.keys(s).length > 0,\n\t\t\"Schema must have at least one table\",\n\t) as z.ZodType<Record<string, SubgraphTable>>;\n\nexport const VALID_FILTER_TYPES = [\n\t\"stx_transfer\",\n\t\"stx_mint\",\n\t\"stx_burn\",\n\t\"stx_lock\",\n\t\"ft_transfer\",\n\t\"ft_mint\",\n\t\"ft_burn\",\n\t\"nft_transfer\",\n\t\"nft_mint\",\n\t\"nft_burn\",\n\t\"contract_call\",\n\t\"contract_deploy\",\n\t\"print_event\",\n\t\"nested_contract_call\",\n\t\"var_set\",\n\t\"map_set\",\n\t\"map_insert\",\n\t\"map_delete\",\n] as const;\n\n/** A contract id, or a set of them (max 20, matching the Index API cap). */\nconst contractIdField = z.union([\n\tz.string(),\n\tz.array(z.string()).min(1).max(20),\n]);\n\n/** Fields shared by the trait-scopable filters. */\nconst traitScope = { trait: z.string().optional() };\n/** Dynamic address set discovered from another source's events. */\nconst factoryScope = {\n\tfactory: z\n\t\t.object({ from: z.string().min(1), field: z.string().min(1) })\n\t\t.strict()\n\t\t.optional(),\n};\nconst amountRange = {\n\tminAmount: z.bigint().optional(),\n\tmaxAmount: z.bigint().optional(),\n};\n\n/**\n * A REAL discriminated union — one member per source type, each `.strict()`\n * with only the fields that type actually supports.\n *\n * It used to be one flat object with every field optional, so\n * `{ type: \"contract_deploy\", assetIdentifier: \"SP…\", minAmount: 1n }`\n * validated clean at deploy and then matched nothing, forever. The runtime\n * union already knew better; only the validator didn't.\n */\nconst SubgraphFilterUnion = z.discriminatedUnion(\"type\", [\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_transfer\"),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...amountRange,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_mint\"),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_burn\"),\n\t\t\tsender: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"stx_lock\"),\n\t\t\tlockedAddress: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_transfer\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_mint\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"ft_burn\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\tminAmount: z.bigint().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_transfer\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_mint\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\trecipient: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nft_burn\"),\n\t\t\tassetIdentifier: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\t...traitScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"contract_call\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tfunctionName: z.string().optional(),\n\t\t\tcaller: z.string().optional(),\n\t\t\tabi: AbiContractSchema.optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"contract_deploy\"),\n\t\t\tdeployer: z.string().optional(),\n\t\t\tcontractName: z.string().optional(),\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"print_event\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\ttopic: z.string().optional(),\n\t\t\tprints: z\n\t\t\t\t.record(z.string(), z.record(z.string(), PrintFieldSchema))\n\t\t\t\t.optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"nested_contract_call\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tfunctionName: z.string().optional(),\n\t\t\tcaller: z.string().optional(),\n\t\t\tsender: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"var_set\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tvarName: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_set\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_insert\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\ttype: z.literal(\"map_delete\"),\n\t\t\tcontractId: contractIdField.optional(),\n\t\t\tmap: z.string().optional(),\n\t\t\t...traitScope,\n\t\t\t...factoryScope,\n\t\t})\n\t\t.strict(),\n]);\n\n/**\n * `trait` and `contractId` compose rather than conflict: the matcher ANDs\n * them, so the pair means \"contracts conforming to this trait, narrowed to\n * these ids\". (The Index READ API refuses the combination because its query\n * planner picks one index path — that's an API constraint, not a semantic\n * one, and subgraph sources are not bound by it.)\n */\nexport const SubgraphFilterSchema: z.ZodType<SubgraphFilter> =\n\tSubgraphFilterUnion as unknown as z.ZodType<SubgraphFilter>;\n\n/** Pinned contractId: a non-empty string or a non-empty array of ids. */\nfunction hasPinnedContractId(\n\tcontractId: string | readonly string[] | undefined,\n): boolean {\n\tif (typeof contractId === \"string\") return contractId.length > 0;\n\tif (Array.isArray(contractId)) return contractId.length > 0;\n\treturn false;\n}\n\n/**\n * Deploy gates beyond the per-filter union: pinned print_event needs a\n * non-empty `prints` map, contract_call+functionName needs `abi`, and every\n * source needs a handler of the same name.\n */\nfunction refineDeployGates(\n\tdef: {\n\t\tsources: Record<string, SubgraphFilter>;\n\t\thandlers: Record<string, unknown>;\n\t\tschema: SubgraphSchema;\n\t},\n\tctx: z.RefinementCtx,\n): void {\n\tfor (const [name, filter] of Object.entries(def.sources)) {\n\t\tif (filter.type === \"print_event\") {\n\t\t\t// Trait / unpinned (no contractId) may omit prints — no single schema.\n\t\t\tconst pinned = hasPinnedContractId(filter.contractId) && !filter.trait;\n\t\t\tif (pinned) {\n\t\t\t\tconst prints = filter.prints;\n\t\t\t\tif (\n\t\t\t\t\tprints === undefined ||\n\t\t\t\t\ttypeof prints !== \"object\" ||\n\t\t\t\t\tObject.keys(prints).length === 0\n\t\t\t\t) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tpath: [\"sources\", name, \"prints\"],\n\t\t\t\t\t\tmessage: `print_event source \"${name}\" has no prints map — field names would be untyped and empty tables would typecheck. Declare prints from index_print_schema / create --from-contract.`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (filter.type === \"contract_call\" && filter.functionName !== undefined) {\n\t\t\tif (filter.abi === undefined) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\tpath: [\"sources\", name, \"abi\"],\n\t\t\t\t\tmessage: `contract_call source \"${name}\" has functionName but no abi. \\`secondlayer subgraphs deploy\\` fills it in from the deployed contract; otherwise pass abi (normalizeAbi() from @secondlayer/stacks/clarity).`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const name of Object.keys(def.sources)) {\n\t\tif (def.handlers[name] == null) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [\"handlers\", name],\n\t\t\t\tmessage: `source \"${name}\" has no handler. Add handlers.${name}, or its events are skipped and the table stays empty.`,\n\t\t\t});\n\t\t}\n\t}\n}\n\nexport const SubgraphDefinitionSchema: z.ZodType<SubgraphDefinition> = z\n\t.object({\n\t\tname: SubgraphNameSchema,\n\t\tdescription: z.string().optional(),\n\t\tstartBlock: z.number().int().nonnegative().optional(),\n\t\t// 'concurrent' = tip-first deploy: go live at tip immediately, fill\n\t\t// history via a background backfill. Only safe for order-tolerant\n\t\t// handlers (commutative or insert-only writes).\n\t\tbackfillMode: z.enum([\"blocking\", \"concurrent\"]).optional(),\n\t\tsources: z\n\t\t\t.record(z.string(), SubgraphFilterSchema)\n\t\t\t.refine(\n\t\t\t\t(s) => Object.keys(s).length > 0,\n\t\t\t\t\"Must have at least one source\",\n\t\t\t),\n\t\tschema: SubgraphSchemaSchema,\n\t\thandlers: z.record(z.string(), z.any()),\n\t})\n\t.superRefine((def, ctx) => {\n\t\trefineDeployGates(\n\t\t\tdef as {\n\t\t\t\tsources: Record<string, SubgraphFilter>;\n\t\t\t\thandlers: Record<string, unknown>;\n\t\t\t\tschema: SubgraphSchema;\n\t\t\t},\n\t\t\tctx,\n\t\t);\n\t}) as unknown as z.ZodType<SubgraphDefinition>;\n\n/**\n * Validates a subgraph definition, returning the parsed result or throwing on failure.\n */\nexport function validateSubgraphDefinition(def: unknown): SubgraphDefinition {\n\treturn SubgraphDefinitionSchema.parse(def);\n}\n\n/**\n * Per-source-type field vocabulary, DERIVED from\n * {@link SubgraphFilterSchema}. Agent-facing surfaces (the MCP filters\n * reference) used to hand-maintain a parallel copy of this list; deriving it\n * means adding a field to a filter can never leave the documentation behind.\n */\nexport function filterFieldsByType(): Array<{\n\ttype: string;\n\tfields: string[];\n}> {\n\t// Read the UNION directly (SubgraphFilterSchema wraps it in superRefine).\n\t// biome-ignore lint/suspicious/noExplicitAny: reading zod's internal option shapes\n\tconst options = (SubgraphFilterUnion as any)?._def?.options ?? [];\n\tconst out: Array<{ type: string; fields: string[] }> = [];\n\tfor (const option of options) {\n\t\t// `.superRefine()` wraps the union, so unwrap one level when present.\n\t\tconst shape = option?.shape ?? option?._def?.shape;\n\t\tif (!shape) continue;\n\t\tconst literal =\n\t\t\tshape.type?._def?.values?.[0] ?? shape.type?._def?.value ?? undefined;\n\t\tif (typeof literal !== \"string\") continue;\n\t\tout.push({\n\t\t\ttype: literal,\n\t\t\tfields: Object.keys(shape).filter((k) => k !== \"type\"),\n\t\t});\n\t}\n\treturn out;\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "BFED63A6F6DDAA5F64756E2164756E21",
9
+ "names": []
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/subgraphs",
3
- "version": "4.4.1",
3
+ "version": "5.0.0",
4
4
  "description": "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -10,44 +10,36 @@
10
10
  },
11
11
  "homepage": "https://github.com/ryanwaits/secondlayer/tree/main/packages/subgraphs#readme",
12
12
  "type": "module",
13
- "main": "./dist/src/index.js",
14
- "types": "./dist/src/index.d.ts",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
15
  "exports": {
16
16
  ".": {
17
- "types": "./dist/src/index.d.ts",
18
- "import": "./dist/src/index.js"
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
19
  },
20
20
  "./types": {
21
- "types": "./dist/src/types.d.ts",
22
- "import": "./dist/src/types.js"
21
+ "types": "./dist/types.d.ts",
22
+ "import": "./dist/types.js"
23
23
  },
24
24
  "./schema": {
25
- "types": "./dist/src/schema/index.d.ts",
26
- "import": "./dist/src/schema/index.js"
25
+ "types": "./dist/schema/index.d.ts",
26
+ "import": "./dist/schema/index.js"
27
27
  },
28
28
  "./validate": {
29
- "types": "./dist/src/validate.d.ts",
30
- "import": "./dist/src/validate.js"
31
- },
32
- "./triggers": {
33
- "types": "./dist/src/triggers/index.d.ts",
34
- "import": "./dist/src/triggers/index.js"
35
- },
36
- "./runtime/source-matcher": {
37
- "types": "./dist/src/runtime/source-matcher.d.ts",
38
- "import": "./dist/src/runtime/source-matcher.js"
29
+ "types": "./dist/validate.d.ts",
30
+ "import": "./dist/validate.js"
39
31
  },
40
32
  "./runtime/replay": {
41
- "types": "./dist/src/runtime/replay.d.ts",
42
- "import": "./dist/src/runtime/replay.js"
33
+ "types": "./dist/runtime/replay.d.ts",
34
+ "import": "./dist/runtime/replay.js"
43
35
  },
44
36
  "./runtime/emitter": {
45
- "types": "./dist/src/runtime/emitter.d.ts",
46
- "import": "./dist/src/runtime/emitter.js"
37
+ "types": "./dist/runtime/emitter.d.ts",
38
+ "import": "./dist/runtime/emitter.js"
47
39
  },
48
40
  "./testing": {
49
- "types": "./dist/src/testing/index.d.ts",
50
- "import": "./dist/src/testing/index.js"
41
+ "types": "./dist/testing/index.d.ts",
42
+ "import": "./dist/testing/index.js"
51
43
  }
52
44
  },
53
45
  "files": ["dist"],
@@ -59,7 +51,7 @@
59
51
  "prepublishOnly": "bun run build"
60
52
  },
61
53
  "dependencies": {
62
- "@secondlayer/shared": "^11.7.1",
54
+ "@secondlayer/shared": "^11.8.0",
63
55
  "@secondlayer/stacks": "^6.1.0",
64
56
  "esbuild": "^0.28.2",
65
57
  "kysely": "0.28.17",