@secondlayer/subgraphs 4.4.1 → 5.0.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/README.md +13 -21
- package/dist/{src/index.d.ts → index.d.ts} +59 -189
- package/dist/index.js +2151 -0
- package/dist/index.js.map +24 -0
- package/dist/{src/runtime → runtime}/emitter.d.ts +17 -11
- package/dist/{src/runtime → runtime}/emitter.js +58 -18
- package/dist/runtime/emitter.js.map +19 -0
- package/dist/{src/runtime → runtime}/replay.d.ts +15 -1
- package/dist/{src/runtime → runtime}/replay.js +418 -723
- package/dist/{src/runtime → runtime}/replay.js.map +6 -6
- package/dist/{src/schema → schema}/index.d.ts +10 -69
- package/dist/{src/schema → schema}/index.js +188 -281
- package/dist/schema/index.js.map +13 -0
- package/dist/{src/testing → testing}/index.d.ts +65 -115
- package/dist/{src/testing → testing}/index.js +554 -968
- package/dist/testing/index.js.map +21 -0
- package/dist/{src/types.d.ts → types.d.ts} +10 -66
- package/dist/{src/validate.d.ts → validate.d.ts} +11 -69
- package/dist/{src/validate.js → validate.js} +18 -98
- package/dist/validate.js.map +10 -0
- package/package.json +18 -26
- package/dist/src/index.js +0 -6081
- package/dist/src/index.js.map +0 -44
- package/dist/src/runtime/block-processor.d.ts +0 -559
- package/dist/src/runtime/block-processor.js +0 -3810
- package/dist/src/runtime/block-processor.js.map +0 -31
- package/dist/src/runtime/catchup.d.ts +0 -473
- package/dist/src/runtime/catchup.js +0 -4228
- package/dist/src/runtime/catchup.js.map +0 -35
- package/dist/src/runtime/clarity.d.ts +0 -15
- package/dist/src/runtime/clarity.js +0 -41
- package/dist/src/runtime/clarity.js.map +0 -10
- package/dist/src/runtime/context.d.ts +0 -325
- package/dist/src/runtime/context.js +0 -936
- package/dist/src/runtime/context.js.map +0 -13
- package/dist/src/runtime/emitter.js.map +0 -19
- package/dist/src/runtime/processor.d.ts +0 -11
- package/dist/src/runtime/processor.js +0 -5372
- package/dist/src/runtime/processor.js.map +0 -40
- package/dist/src/runtime/reindex.d.ts +0 -539
- package/dist/src/runtime/reindex.js +0 -4802
- package/dist/src/runtime/reindex.js.map +0 -37
- package/dist/src/runtime/reorg.d.ts +0 -432
- package/dist/src/runtime/reorg.js +0 -4355
- package/dist/src/runtime/reorg.js.map +0 -36
- package/dist/src/runtime/runner.d.ts +0 -719
- package/dist/src/runtime/runner.js +0 -1332
- package/dist/src/runtime/runner.js.map +0 -16
- package/dist/src/runtime/source-matcher.d.ts +0 -304
- package/dist/src/runtime/source-matcher.js +0 -335
- package/dist/src/runtime/source-matcher.js.map +0 -10
- package/dist/src/runtime/stats.d.ts +0 -23
- package/dist/src/runtime/stats.js +0 -71
- package/dist/src/runtime/stats.js.map +0 -10
- package/dist/src/schema/index.js.map +0 -13
- package/dist/src/service.d.ts +0 -0
- package/dist/src/service.js +0 -5398
- package/dist/src/service.js.map +0 -41
- package/dist/src/testing/index.js.map +0 -22
- package/dist/src/triggers/index.d.ts +0 -381
- package/dist/src/triggers/index.js +0 -31
- package/dist/src/triggers/index.js.map +0 -10
- package/dist/src/validate.js.map +0 -10
- /package/dist/{src/types.js → types.js} +0 -0
- /package/dist/{src/types.js.map → types.js.map} +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/schema/generator.ts", "../src/schema/utils.ts", "../src/schema/deployer.ts", "../src/validate.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { createHash } from \"node:crypto\";\nimport type {\n\tColumnType,\n\tSubgraphDefinition,\n\tSubgraphTable,\n} from \"../types.ts\";\nimport { pgSchemaName, quotePgIdent } from \"./utils.ts\";\n\nexport const TYPE_MAP: Record<ColumnType, string> = {\n\ttext: \"TEXT\",\n\tuint: \"NUMERIC\",\n\tint: \"NUMERIC\",\n\tprincipal: \"TEXT\",\n\tboolean: \"BOOLEAN\",\n\ttimestamp: \"TIMESTAMPTZ\",\n\tjsonb: \"JSONB\",\n};\n\nexport interface GeneratedSQL {\n\tstatements: string[];\n\thash: string;\n}\n\n// Postgres truncates identifiers over 63 bytes. schema/table/column names are\n// each individually capped at 63 (SqlIdentifierSchema / SubgraphNameSchema),\n// but concatenated (`idx_<schema>_<table>_<col>_id`, plus an optional\n// account-scoped schema prefix) they can exceed that — two different columns\n// could then truncate to the same name and silently collide on CREATE INDEX.\n// Route the sort-composite name through here: short names pass through\n// unchanged (human-readable, matches the single-column naming style); an\n// oversized name is truncated and given a content hash suffix so it can't\n// collide with a different oversized name that happens to share a prefix.\nconst MAX_IDENT_BYTES = 63;\nfunction safeIndexName(name: string): string {\n\tif (name.length <= MAX_IDENT_BYTES) return name;\n\tconst hash = createHash(\"sha256\").update(name).digest(\"hex\").slice(0, 8);\n\treturn `${name.slice(0, MAX_IDENT_BYTES - hash.length - 1)}_${hash}`;\n}\n\n/**\n * Plain equality index + `/v1` keyset composite `(col, _id)` for one\n * `indexed` column. Single source for {@link emitTableDDL} and additive\n * deploy — a missing composite on the add/flag-flip path made deep\n * `?_sort=` pages Filter/re-sort instead of an index-only scan.\n */\nexport function emitIndexedColumnIndexDDL(\n\tschemaName: string,\n\ttableName: string,\n\tcolName: string,\n\topts?: { concurrently?: boolean },\n): { create: string[]; drop: string[] } {\n\tconst concurrently = opts?.concurrently ? \" CONCURRENTLY\" : \"\";\n\tconst qualified = `${quotePgIdent(schemaName)}.${quotePgIdent(tableName)}`;\n\tconst plain = `idx_${schemaName}_${tableName}_${colName}`;\n\tconst composite = safeIndexName(\n\t\t`idx_${schemaName}_${tableName}_${colName}_id`,\n\t);\n\tconst col = quotePgIdent(colName);\n\tconst id = quotePgIdent(\"_id\");\n\treturn {\n\t\tcreate: [\n\t\t\t`CREATE INDEX${concurrently} IF NOT EXISTS ${quotePgIdent(plain)} ON ${qualified} (${col})`,\n\t\t\t`CREATE INDEX${concurrently} IF NOT EXISTS ${quotePgIdent(composite)} ON ${qualified} (${col}, ${id})`,\n\t\t],\n\t\tdrop: [\n\t\t\t`DROP INDEX${concurrently} IF EXISTS ${quotePgIdent(schemaName)}.${quotePgIdent(plain)}`,\n\t\t\t`DROP INDEX${concurrently} IF EXISTS ${quotePgIdent(schemaName)}.${quotePgIdent(composite)}`,\n\t\t],\n\t};\n}\n\nfunction escapeLiteralDefault(value: unknown): string {\n\tif (value === null || value === undefined) return \"NULL\";\n\tif (typeof value === \"number\" || typeof value === \"bigint\")\n\t\treturn String(value);\n\tif (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n\treturn `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\n/** True if any column on the table uses full-text `search` (needs the pg_trgm\n * extension before its GIN index can be created). */\nexport function tableNeedsTrgm(tableDef: SubgraphTable): boolean {\n\treturn Object.values(tableDef.columns).some((col) => col.search);\n}\n\n/**\n * All per-table DDL for ONE table — create + meta/user/composite indexes + UNIQUE\n * constraints. Single-sourced so the full\n * generator and the deployer's additive-create path can't drift — a missing\n * UNIQUE or DEFAULT here would make a handler `upsert ON CONFLICT` fail at runtime.\n */\nexport function emitTableDDL(\n\tschemaName: string,\n\ttableName: string,\n\ttableDef: SubgraphTable,\n): string[] {\n\tconst qualifiedName = `${quotePgIdent(schemaName)}.${quotePgIdent(tableName)}`;\n\tconst statements: string[] = [];\n\n\tconst columnDefs: string[] = [\n\t\t\"_id BIGSERIAL PRIMARY KEY\",\n\t\t\"_block_height BIGINT NOT NULL\",\n\t\t\"_tx_id TEXT NOT NULL\",\n\t\t\"_created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\",\n\t];\n\tfor (const [colName, col] of Object.entries(tableDef.columns)) {\n\t\tconst sqlType = TYPE_MAP[col.type];\n\t\tconst nullable = col.nullable ? \"\" : \" NOT NULL\";\n\t\tlet colDef = `${quotePgIdent(colName)} ${sqlType}${nullable}`;\n\t\tif (col.default !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${escapeLiteralDefault(col.default)}`;\n\t\t}\n\t\t// uint is unsigned by definition — fail loudly instead of silently\n\t\t// storing a negative (fix-f040 B4). Handlers run in chain order, so a\n\t\t// legitimate same-block receive-then-spend never trips this.\n\t\tif (col.type === \"uint\") {\n\t\t\tcolDef += ` CHECK (${quotePgIdent(colName)} >= 0)`;\n\t\t}\n\t\tcolumnDefs.push(colDef);\n\t}\n\tstatements.push(\n\t\t`CREATE TABLE IF NOT EXISTS ${qualifiedName} (\\n ${columnDefs.join(\",\\n \")}\\n)`,\n\t);\n\n\t// Auto-indexes on meta columns.\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_block_height`)} ON ${qualifiedName} (_block_height)`,\n\t);\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_tx_id`)} ON ${qualifiedName} (_tx_id)`,\n\t);\n\n\t// Single-column indexes, plus a composite `(col, \"_id\")` sort index.\n\t// `/v1`'s `?_sort=<col>&_order=` keyset predicate compares `(col, \"_id\")`\n\t// and orders by `col, \"_id\"` — a composite index matches that exactly, so\n\t// deep pages on a low-cardinality column become an index-only scan instead\n\t// of a Filter/re-sort within each value group. The single-column index\n\t// stays too: it still serves plain equality filters (`?col=value`).\n\tfor (const [colName, col] of Object.entries(tableDef.columns)) {\n\t\tif (col.indexed) {\n\t\t\tstatements.push(\n\t\t\t\t...emitIndexedColumnIndexDDL(schemaName, tableName, colName).create,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Trigram GIN indexes for search columns.\n\tfor (const [colName, col] of Object.entries(tableDef.columns)) {\n\t\tif (col.search) {\n\t\t\tstatements.push(\n\t\t\t\t`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_${colName}_trgm`)} ON ${qualifiedName} USING gin (${quotePgIdent(colName)} gin_trgm_ops)`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Composite indexes.\n\tif (tableDef.indexes) {\n\t\tfor (let i = 0; i < tableDef.indexes.length; i++) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst cols = tableDef.indexes[i]!;\n\t\t\tconst idxName = quotePgIdent(\n\t\t\t\t`idx_${schemaName}_${tableName}_composite_${i}`,\n\t\t\t);\n\t\t\tstatements.push(\n\t\t\t\t`CREATE INDEX IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.map(quotePgIdent).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Unique constraints (required for upsert ON CONFLICT).\n\tif (tableDef.uniqueKeys) {\n\t\tfor (let i = 0; i < tableDef.uniqueKeys.length; i++) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\t\tconst cols = tableDef.uniqueKeys[i]!;\n\t\t\tconst constraintName = quotePgIdent(\n\t\t\t\t`uq_${schemaName}_${tableName}_${cols.join(\"_\")}`,\n\t\t\t);\n\t\t\tstatements.push(\n\t\t\t\t`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.map(quotePgIdent).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn statements;\n}\n\n/**\n * Per-schema revert journal. Before every keyed mutation (upsert / increment /\n * update / delete) the flush records the row's prior state; a reorg restores\n * those states instead of deleting whole rows by `_block_height` — which is\n * only correct for append-only tables, not accumulators (fix-f040 B2).\n * `prev_row IS NULL` marks a row first created by the journaled op.\n */\nexport function emitJournalDDL(schemaName: string): string[] {\n\treturn [\n\t\t`CREATE TABLE IF NOT EXISTS ${schemaName}._journal (\n _jid BIGSERIAL PRIMARY KEY,\n block_height BIGINT NOT NULL,\n table_name TEXT NOT NULL,\n row_key JSONB NOT NULL,\n prev_row JSONB,\n _created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n)`,\n\t\t`CREATE INDEX IF NOT EXISTS idx_${schemaName}_journal_height ON ${schemaName}._journal (block_height)`,\n\t];\n}\n\n/**\n * Storage for factory-discovered addresses.\n *\n * `block_height` is what makes the set reorg-scoped: the reorg handler\n * deletes rows at or above the fork alongside the data tables, so an address\n * revealed on an orphaned chain does not linger in the matcher forever\n * (the failure mode a set kept outside the rollback model would have).\n */\nexport function emitFactoryDDL(schemaName: string): string[] {\n\treturn [\n\t\t`CREATE TABLE IF NOT EXISTS ${schemaName}._factory_addresses (\n source_name TEXT NOT NULL,\n address TEXT NOT NULL,\n block_height BIGINT NOT NULL,\n _created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (source_name, address)\n)`,\n\t\t`CREATE INDEX IF NOT EXISTS idx_${schemaName}_factory_height ON ${schemaName}._factory_addresses (block_height)`,\n\t];\n}\n\n/**\n * Generates PostgreSQL DDL statements for a subgraph definition.\n * Creates a dedicated schema `subgraph_<name>` with one table per schema entry,\n * each with auto-columns and indexes.\n */\nexport function generateSubgraphSQL(\n\tdef: SubgraphDefinition,\n\tschemaNameOverride?: string,\n): GeneratedSQL {\n\tconst schemaName = schemaNameOverride ?? pgSchemaName(def.name);\n\tconst statements: string[] = [];\n\n\t// Check if any column uses search (trigram)\n\tconst needsTrgm = Object.values(def.schema).some((table) =>\n\t\tObject.values(table.columns).some((col) => col.search),\n\t);\n\n\tif (needsTrgm) {\n\t\tstatements.push(\"CREATE EXTENSION IF NOT EXISTS pg_trgm\");\n\t}\n\n\t// Schema namespace\n\tstatements.push(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`);\n\n\t// One table per schema entry (single-sourced per-table DDL).\n\tfor (const [tableName, tableDef] of Object.entries(def.schema)) {\n\t\tstatements.push(...emitTableDDL(schemaName, tableName, tableDef));\n\t}\n\n\t// Revert journal (one per schema) — see emitJournalDDL.\n\tstatements.push(...emitJournalDDL(schemaName));\n\t// Only when a source actually uses a factory — no dead table otherwise.\n\tif (\n\t\tObject.values(def.sources ?? {}).some(\n\t\t\t(src) => (src as { factory?: unknown }).factory !== undefined,\n\t\t)\n\t) {\n\t\tstatements.push(...emitFactoryDDL(schemaName));\n\t}\n\n\t// Hash based on schema structure only — version intentionally excluded\n\t// so server-managed version bumps don't look like schema changes\n\tconst hashInput = JSON.stringify(\n\t\t{\n\t\t\tname: def.name,\n\t\t\tschema: def.schema,\n\t\t\tsources: def.sources,\n\t\t},\n\t\t(_key, value) => (typeof value === \"bigint\" ? value.toString() : value),\n\t);\n\t// node crypto (not Bun.hash) so the published node-runtime `sl` CLI can\n\t// compute schema hashes too (e.g. `sl subgraphs spec`).\n\tconst hash = createHash(\"sha256\").update(hashInput).digest(\"hex\");\n\n\treturn { statements, hash };\n}\n",
|
|
6
|
+
"// Re-export canonical pgSchemaName from shared\nexport { pgSchemaName } from \"@secondlayer/shared/db/queries/subgraphs\";\n\n/**\n * Double-quotes a Postgres identifier unless it's already a safe bare\n * identifier, escaping any embedded double quotes. Defense-in-depth for the\n * DDL emitters: every name reaching them (schema/table/column names, and the\n * composite names generator.ts builds from them) is validated upstream\n * (`SqlIdentifierSchema` / `SubgraphNameSchema`), so this is a no-op for every\n * currently-valid name — output stays byte-identical. It only changes\n * anything if a hostile name (embedded quote, semicolon, whitespace, ...)\n * somehow reached this far, turning it into an inert quoted identifier\n * instead of raw SQL.\n */\nexport function quotePgIdent(name: string): string {\n\tif (/^[a-z_][a-z0-9_]*$/i.test(name)) return name;\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** `user_account` → `userAccount`. Column and variable names in every emitted\n * ORM surface go through this. */\nexport function snakeToCamel(name: string): string {\n\treturn name.replace(/_([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n\n/** `user_account` → `UserAccount`. Type/model names for one table must agree\n * across the Prisma, Drizzle, Kysely, and index-codegen emitters — a user can\n * import from more than one, so this lives here rather than per-generator. */\nexport function pascalCase(name: string): string {\n\tconst camel = snakeToCamel(name);\n\treturn camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n",
|
|
7
|
+
"import type { Database } from \"@secondlayer/shared/db\";\nimport { type Kysely, sql } from \"kysely\";\nimport type {\n\tSubgraphDefinition,\n\tSubgraphSchema,\n\tSubgraphTable,\n} from \"../types.ts\";\nimport { validateSubgraphDefinition } from \"../validate.ts\";\nimport {\n\tTYPE_MAP,\n\temitIndexedColumnIndexDDL,\n\temitTableDDL,\n\tgenerateSubgraphSQL,\n\ttableNeedsTrgm,\n} from \"./generator.ts\";\nimport { pgSchemaName } from \"./utils.ts\";\n\ntype AnyDb = Kysely<Database>;\n\n/** Deep-clone an object, converting BigInts to strings for JSON serialization. */\nfunction toJsonSafe(obj: unknown): unknown {\n\treturn JSON.parse(\n\t\tJSON.stringify(obj, (_key, value) =>\n\t\t\ttypeof value === \"bigint\" ? value.toString() : value,\n\t\t),\n\t);\n}\n\nexport interface TableDiff {\n\t/** Tables added to the schema */\n\taddedTables: string[];\n\t/** Tables removed from the schema */\n\tremovedTables: string[];\n\t/** Per-table column diffs (only for tables present in both) */\n\ttables: Record<string, ColumnDiff>;\n\t/** Per-table uniqueKeys / composite-index diffs (tables present in both) */\n\tconstraints: Record<string, ConstraintDiff>;\n}\n\nexport interface ColumnDiff {\n\tadded: string[];\n\tremoved: string[];\n\t/** Data-shape changes (type/nullable/default) — breaking. */\n\tchanged: string[];\n\t/** Only the `indexed`/`search` flags differ — index DDL, never a rebuild. */\n\tindexChanged: string[];\n}\n\nexport interface ConstraintDiff {\n\t/** New uniqueKeys entries → `ALTER TABLE … ADD CONSTRAINT` (additive). */\n\taddedUniqueKeys: string[][];\n\t/** Removed uniqueKeys entries — breaking: handler upserts may target them. */\n\tremovedUniqueKeys: string[][];\n\t/** New composite `indexes` entries → CREATE INDEX (additive). */\n\taddedIndexes: string[][];\n\t/** Removed composite `indexes` entries → DROP INDEX (additive). */\n\tremovedIndexes: string[][];\n}\n\n/** Column identity minus the index flags: what actually shapes stored data. */\nfunction columnDataShape(col: unknown): string {\n\tconst { indexed, search, ...rest } = (col ?? {}) as Record<string, unknown>;\n\treturn JSON.stringify(rest, Object.keys(rest).sort());\n}\n\n/** Diff two `string[][]` lists (uniqueKeys / indexes) by column-list value. */\nfunction diffKeyLists(\n\texisting: readonly (readonly string[])[] | undefined,\n\tincoming: readonly (readonly string[])[] | undefined,\n): { added: string[][]; removed: string[][] } {\n\tconst key = (cols: readonly string[]) => JSON.stringify(cols);\n\tconst existingSet = new Set((existing ?? []).map(key));\n\tconst incomingSet = new Set((incoming ?? []).map(key));\n\treturn {\n\t\tadded: (incoming ?? [])\n\t\t\t.filter((cols) => !existingSet.has(key(cols)))\n\t\t\t.map((cols) => [...cols]),\n\t\tremoved: (existing ?? [])\n\t\t\t.filter((cols) => !incomingSet.has(key(cols)))\n\t\t\t.map((cols) => [...cols]),\n\t};\n}\n\n/**\n * Compare two multi-table subgraph schemas and return differences.\n *\n * Index-only changes (`indexed`/`search` flags, composite `indexes`) are\n * reported separately from data-shape changes: an index never requires a\n * rebuild, so it must never land in `changed`/breaking — flipping\n * `indexed: true` on a populated column used to cost a full reindex.\n */\nexport function diffSchema(\n\texisting: SubgraphSchema,\n\tincoming: SubgraphSchema,\n): TableDiff {\n\tconst existingTables = new Set(Object.keys(existing));\n\tconst incomingTables = new Set(Object.keys(incoming));\n\n\tconst addedTables = [...incomingTables].filter((t) => !existingTables.has(t));\n\tconst removedTables = [...existingTables].filter(\n\t\t(t) => !incomingTables.has(t),\n\t);\n\n\tconst tables: Record<string, ColumnDiff> = {};\n\tconst constraints: Record<string, ConstraintDiff> = {};\n\tfor (const tableName of incomingTables) {\n\t\tif (!existingTables.has(tableName)) continue;\n\t\tconst existingTable = existing[tableName];\n\t\tconst incomingTable = incoming[tableName];\n\t\tconst existingCols = existingTable?.columns;\n\t\tconst incomingCols = incomingTable?.columns;\n\n\t\tconst existingKeys = new Set(Object.keys(existingCols));\n\t\tconst incomingKeys = new Set(Object.keys(incomingCols));\n\t\tconst common = [...incomingKeys].filter((k) => existingKeys.has(k));\n\n\t\tconst sortedStringify = (o: unknown) =>\n\t\t\tJSON.stringify(o, Object.keys(o as object).sort());\n\n\t\ttables[tableName] = {\n\t\t\tadded: [...incomingKeys].filter((k) => !existingKeys.has(k)),\n\t\t\tremoved: [...existingKeys].filter((k) => !incomingKeys.has(k)),\n\t\t\tchanged: common.filter(\n\t\t\t\t(k) =>\n\t\t\t\t\tcolumnDataShape(existingCols[k]) !== columnDataShape(incomingCols[k]),\n\t\t\t),\n\t\t\tindexChanged: common.filter(\n\t\t\t\t(k) =>\n\t\t\t\t\tcolumnDataShape(existingCols[k]) ===\n\t\t\t\t\t\tcolumnDataShape(incomingCols[k]) &&\n\t\t\t\t\tsortedStringify(existingCols[k]) !== sortedStringify(incomingCols[k]),\n\t\t\t),\n\t\t};\n\n\t\tconst uq = diffKeyLists(\n\t\t\texistingTable?.uniqueKeys,\n\t\t\tincomingTable?.uniqueKeys,\n\t\t);\n\t\tconst ix = diffKeyLists(existingTable?.indexes, incomingTable?.indexes);\n\t\tconstraints[tableName] = {\n\t\t\taddedUniqueKeys: uq.added,\n\t\t\tremovedUniqueKeys: uq.removed,\n\t\t\taddedIndexes: ix.added,\n\t\t\tremovedIndexes: ix.removed,\n\t\t};\n\t}\n\n\treturn { addedTables, removedTables, tables, constraints };\n}\n\n/**\n * Returns true if the diff contains any breaking changes\n * (removed tables, removed columns, changed column types, or removed\n * uniqueKeys — handler upserts `ON CONFLICT` against those).\n * Index-flag and composite-index changes are never breaking.\n */\nexport function hasBreakingChanges(diff: TableDiff): {\n\tbreaking: boolean;\n\treasons: string[];\n} {\n\tconst reasons: string[] = [];\n\tif (diff.removedTables.length > 0) {\n\t\treasons.push(`removed tables: [${diff.removedTables.join(\", \")}]`);\n\t}\n\tfor (const [table, colDiff] of Object.entries(diff.tables)) {\n\t\tif (colDiff.removed.length > 0) {\n\t\t\treasons.push(`${table}: removed columns [${colDiff.removed.join(\", \")}]`);\n\t\t}\n\t\tif (colDiff.changed.length > 0) {\n\t\t\treasons.push(`${table}: changed columns [${colDiff.changed.join(\", \")}]`);\n\t\t}\n\t}\n\tfor (const [table, conDiff] of Object.entries(diff.constraints ?? {})) {\n\t\tif (conDiff.removedUniqueKeys.length > 0) {\n\t\t\treasons.push(\n\t\t\t\t`${table}: removed uniqueKeys [${conDiff.removedUniqueKeys\n\t\t\t\t\t.map((cols) => `(${cols.join(\", \")})`)\n\t\t\t\t\t.join(\", \")}]`,\n\t\t\t);\n\t\t}\n\t}\n\treturn { breaking: reasons.length > 0, reasons };\n}\n\n/** Increment the patch segment of a semver string. \"1.0.2\" → \"1.0.3\" */\nfunction bumpPatch(version: string): string {\n\tconst parts = version.split(\".\");\n\tif (parts.length !== 3) return \"1.0.1\";\n\tconst patch = Number.parseInt(parts[2] ?? \"0\", 10);\n\treturn `${parts[0]}.${parts[1]}.${Number.isNaN(patch) ? 1 : patch + 1}`;\n}\n\nexport interface DeployDiff {\n\taddedTables: string[];\n\tremovedTables: string[];\n\taddedColumns: Record<string, string[]>;\n\tbreakingChanges: string[];\n\t/** Columns whose only change was the `indexed`/`search` flag (index DDL applied in place). */\n\tindexChanges?: Record<string, string[]>;\n\t/** uniqueKeys added in place via ALTER TABLE … ADD CONSTRAINT. */\n\taddedUniqueKeys?: Record<string, string[][]>;\n}\n\n/**\n * Map a raw `TableDiff` (+ breaking reasons) into the wire `DeployDiff`. `null`\n * diff (e.g. same-hash force reindex, where no schema diff exists) → empty\n * added/removed/columns with reasons preserved. Single source for both the\n * non-refuse \"reindexed\" result and the refuse-path error payload.\n */\nfunction toDeployDiff(diff: TableDiff | null, reasons: string[]): DeployDiff {\n\treturn {\n\t\taddedTables: diff?.addedTables ?? [],\n\t\tremovedTables: diff?.removedTables ?? [],\n\t\taddedColumns: diff\n\t\t\t? Object.fromEntries(\n\t\t\t\t\tObject.entries(diff.tables)\n\t\t\t\t\t\t.filter(([, c]) => c.added.length > 0)\n\t\t\t\t\t\t.map(([t, c]) => [t, c.added]),\n\t\t\t\t)\n\t\t\t: {},\n\t\tbreakingChanges: reasons,\n\t};\n}\n\nexport interface DeployPlan {\n\tschemaName: string;\n\t/** `DROP SCHEMA … CASCADE` a destructive rebuild would run first. */\n\tdropStatement: string;\n\t/** DDL the deploy will run. */\n\tstatements: string[];\n}\n\n/**\n * Render the DDL a deploy would run, without executing.\n * Powers `--dry-run`: the user reviews exactly what a deploy does first.\n */\nexport function renderDeployPlan(\n\tdef: SubgraphDefinition,\n\tschemaName?: string,\n): DeployPlan {\n\tvalidateSubgraphDefinition(def);\n\tconst { statements } = generateSubgraphSQL(def, schemaName);\n\tconst schema = schemaName ?? pgSchemaName(def.name);\n\tconst dropStatement = `DROP SCHEMA IF EXISTS \"${schema}\" CASCADE;`;\n\treturn { schemaName: schema, dropStatement, statements };\n}\n\n/**\n * Deploy a subgraph schema to the database.\n * - New subgraph → CREATE SCHEMA + tables + register\n * - Same hash → no-op (handler path updated)\n * - Additive change → ALTER TABLE ADD COLUMN / CREATE TABLE for new tables\n * - Breaking change → auto-reindex (drop + recreate)\n */\nexport async function deploySchema(\n\tdb: AnyDb,\n\tdef: SubgraphDefinition,\n\thandlerPath: string,\n\topts?: {\n\t\tforceReindex?: boolean;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<{\n\taction: \"created\" | \"unchanged\" | \"handler_updated\" | \"updated\" | \"reindexed\";\n\tsubgraphId: string;\n\tversion: string;\n\tdiff?: DeployDiff;\n\t/** Non-fatal caveats the caller should surface (e.g. handler grafts at tip). */\n\twarnings?: string[];\n}> {\n\tvalidateSubgraphDefinition(def);\n\n\tconst { statements, hash } = generateSubgraphSQL(def, opts?.schemaName);\n\tconst { getSubgraph, registerSubgraph } = await import(\n\t\t\"@secondlayer/shared/db/queries/subgraphs\"\n\t);\n\n\tconst ddlDb = db;\n\n\tconst existing = await getSubgraph(db, def.name, opts?.accountId);\n\n\tconst schemaName = opts?.schemaName ?? pgSchemaName(def.name);\n\n\t// Server owns versioning: bump patch from existing, or start at 1.0.0\n\tconst newVersion = existing ? bumpPatch(existing.version) : \"1.0.0\";\n\n\tconst regData = {\n\t\tname: def.name,\n\t\tversion: newVersion,\n\t\tdefinition: toJsonSafe({\n\t\t\tname: def.name,\n\t\t\tdescription: def.description,\n\t\t\tstartBlock: def.startBlock,\n\t\t\tsources: def.sources,\n\t\t\tschema: def.schema,\n\t\t}) as Record<string, unknown>,\n\t\tschemaHash: hash,\n\t\thandlerPath,\n\t\tapiKeyId: opts?.apiKeyId,\n\t\taccountId: opts?.accountId,\n\t\thandlerCode: opts?.handlerCode,\n\t\tsourceCode: opts?.sourceCode,\n\t\tschemaName,\n\t\tstartBlock: def.startBlock,\n\t};\n\n\tif (existing) {\n\t\t// Guard against zombie rows: registry entry exists but PG schema was dropped\n\t\t// (e.g. partial delete or manual cleanup). Treat as a new subgraph.\n\t\tconst schemaExists = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS (\n\t\t\t\tSELECT 1 FROM information_schema.schemata\n\t\t\t\tWHERE schema_name = ${schemaName}\n\t\t\t) AS \"exists\"\n\t\t`\n\t\t\t.execute(ddlDb)\n\t\t\t.then((r) => r.rows[0]?.exists ?? false);\n\n\t\tif (!schemaExists) {\n\t\t\tfor (const stmt of statements) {\n\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t}\n\t\t\tconst sg = await registerSubgraph(db, regData);\n\t\t\treturn { action: \"reindexed\", subgraphId: sg.id, version: newVersion };\n\t\t}\n\n\t\tif (existing.schema_hash === hash && !opts?.forceReindex) {\n\t\t\t// Update handler path and code in case file moved or handler changed.\n\t\t\tconst handlerChanged =\n\t\t\t\topts?.handlerCode != null && opts.handlerCode !== existing.handler_code;\n\t\t\tconst { updateSubgraphHandlerPath } = await import(\n\t\t\t\t\"@secondlayer/shared/db/queries/subgraphs\"\n\t\t\t);\n\t\t\tawait updateSubgraphHandlerPath(db, def.name, handlerPath, {\n\t\t\t\thandlerCode: opts?.handlerCode,\n\t\t\t\tsourceCode: opts?.sourceCode,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\taction: handlerChanged ? \"handler_updated\" : \"unchanged\",\n\t\t\t\tsubgraphId: existing.id,\n\t\t\t\tversion: existing.version,\n\t\t\t\t// A handler-only change takes effect from the CURRENT tip: rows\n\t\t\t\t// already indexed keep the old handler's output. Silent until now —\n\t\t\t\t// say it, and name the fix.\n\t\t\t\t...(handlerChanged\n\t\t\t\t\t? {\n\t\t\t\t\t\t\twarnings: [\n\t\t\t\t\t\t\t\t\"handler changed but schema did not: new logic applies from the current tip only. \" +\n\t\t\t\t\t\t\t\t\t\"Rows already indexed were computed by the previous handler. \" +\n\t\t\t\t\t\t\t\t\t\"To recompute history, redeploy with --reindex (or backfill a range).\",\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\n\t\tif (existing.schema_hash === hash && opts?.forceReindex) {\n\t\t\t// Same schema but force reindex requested — drop and recreate.\n\t\t\tawait sql\n\t\t\t\t.raw(`DROP SCHEMA IF EXISTS \"${schemaName}\" CASCADE`)\n\t\t\t\t.execute(ddlDb);\n\t\t\tfor (const stmt of statements) {\n\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t}\n\t\t\tconst sg = await registerSubgraph(db, regData);\n\t\t\treturn { action: \"reindexed\", subgraphId: sg.id, version: newVersion };\n\t\t}\n\n\t\tif (existing.definition.schema) {\n\t\t\tconst diff = diffSchema(\n\t\t\t\texisting.definition.schema as SubgraphSchema,\n\t\t\t\tdef.schema,\n\t\t\t);\n\t\t\tconst { breaking, reasons } = hasBreakingChanges(diff);\n\n\t\t\tif (breaking || opts?.forceReindex) {\n\t\t\t\t// Breaking change or forced: drop schema, recreate, register\n\t\t\t\tawait sql\n\t\t\t\t\t.raw(`DROP SCHEMA IF EXISTS \"${schemaName}\" CASCADE`)\n\t\t\t\t\t.execute(ddlDb);\n\t\t\t\tfor (const stmt of statements) {\n\t\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t\t}\n\t\t\t\tconst sg = await registerSubgraph(db, regData);\n\t\t\t\tconst deployDiff = toDeployDiff(diff, reasons);\n\t\t\t\treturn {\n\t\t\t\t\taction: \"reindexed\",\n\t\t\t\t\tsubgraphId: sg.id,\n\t\t\t\t\tversion: newVersion,\n\t\t\t\t\tdiff: deployDiff,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Create new tables using the SAME per-table emitter as the full\n\t\t\t// generator, so an additively-created table gets its UNIQUE constraints,\n\t\t\t// composite indexes, column defaults, and FKs — not just the bare columns.\n\t\t\t// (A missing UNIQUE here previously made a handler upsert ON CONFLICT fail\n\t\t\t// at runtime on additively-added tables.)\n\t\t\tconst addedDefs = diff.addedTables\n\t\t\t\t.map((tableName) => ({ tableName, tableDef: def.schema[tableName] }))\n\t\t\t\t.filter(\n\t\t\t\t\t(t): t is { tableName: string; tableDef: SubgraphTable } =>\n\t\t\t\t\t\tt.tableDef !== undefined,\n\t\t\t\t);\n\n\t\t\t// pg_trgm must exist before any search-column GIN index on the new tables.\n\t\t\tif (addedDefs.some(({ tableDef }) => tableNeedsTrgm(tableDef))) {\n\t\t\t\tawait sql.raw(\"CREATE EXTENSION IF NOT EXISTS pg_trgm\").execute(ddlDb);\n\t\t\t}\n\t\t\tfor (const { tableName, tableDef } of addedDefs) {\n\t\t\t\tfor (const stmt of emitTableDDL(schemaName, tableName, tableDef)) {\n\t\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Add columns to existing tables\n\t\t\tfor (const [tableName, colDiff] of Object.entries(diff.tables)) {\n\t\t\t\tif (colDiff.added.length === 0) continue;\n\t\t\t\tconst qualifiedName = `${schemaName}.${tableName}`;\n\t\t\t\tconst tableDef = def.schema[tableName];\n\t\t\t\tif (!tableDef) continue;\n\t\t\t\tfor (const colName of colDiff.added) {\n\t\t\t\t\tconst col = tableDef.columns[colName];\n\t\t\t\t\tif (!col) continue;\n\t\t\t\t\tconst sqlType = TYPE_MAP[col.type];\n\t\t\t\t\tif (!sqlType) continue;\n\t\t\t\t\tconst nullable = col.nullable\n\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t: ` NOT NULL DEFAULT ${getDefault(col.type)}`;\n\t\t\t\t\tawait sql\n\t\t\t\t\t\t.raw(\n\t\t\t\t\t\t\t`ALTER TABLE ${qualifiedName} ADD COLUMN ${colName} ${sqlType}${nullable}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t\tif (col.indexed) {\n\t\t\t\t\t\tfor (const stmt of emitIndexedColumnIndexDDL(\n\t\t\t\t\t\t\tschemaName,\n\t\t\t\t\t\t\ttableName,\n\t\t\t\t\t\t\tcolName,\n\t\t\t\t\t\t).create) {\n\t\t\t\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (col.search) {\n\t\t\t\t\t\tawait sql\n\t\t\t\t\t\t\t.raw(\n\t\t\t\t\t\t\t\t`CREATE INDEX IF NOT EXISTS idx_${schemaName}_${tableName}_${colName}_trgm ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Index-flag flips on EXISTING (populated) columns: pure index DDL,\n\t\t\t// applied in place. CONCURRENTLY because the table has data and this\n\t\t\t// runs outside a transaction (autocommit per statement) — a plain\n\t\t\t// CREATE INDEX would take a write lock for the whole build.\n\t\t\tconst existingSchema = existing.definition.schema as SubgraphSchema;\n\t\t\tconst flagFlips: Record<string, string[]> = {};\n\t\t\tconst needsTrgmForFlips = Object.entries(diff.tables).some(\n\t\t\t\t([tableName, colDiff]) =>\n\t\t\t\t\tcolDiff.indexChanged.some(\n\t\t\t\t\t\t(colName) =>\n\t\t\t\t\t\t\tdef.schema[tableName]?.columns[colName]?.search &&\n\t\t\t\t\t\t\t!existingSchema[tableName]?.columns[colName]?.search,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tif (needsTrgmForFlips) {\n\t\t\t\tawait sql.raw(\"CREATE EXTENSION IF NOT EXISTS pg_trgm\").execute(ddlDb);\n\t\t\t}\n\t\t\tfor (const [tableName, colDiff] of Object.entries(diff.tables)) {\n\t\t\t\tif (colDiff.indexChanged.length === 0) continue;\n\t\t\t\tflagFlips[tableName] = colDiff.indexChanged;\n\t\t\t\tconst qualifiedName = `${schemaName}.${tableName}`;\n\t\t\t\tfor (const colName of colDiff.indexChanged) {\n\t\t\t\t\tconst was = existingSchema[tableName]?.columns[colName];\n\t\t\t\t\tconst now = def.schema[tableName]?.columns[colName];\n\t\t\t\t\tif (!now) continue;\n\t\t\t\t\tconst trgmIdx = `idx_${schemaName}_${tableName}_${colName}_trgm`;\n\t\t\t\t\tconst indexedIdx = emitIndexedColumnIndexDDL(\n\t\t\t\t\t\tschemaName,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolName,\n\t\t\t\t\t\t{ concurrently: true },\n\t\t\t\t\t);\n\t\t\t\t\tif (now.indexed && !was?.indexed) {\n\t\t\t\t\t\tfor (const stmt of indexedIdx.create) {\n\t\t\t\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (!now.indexed && was?.indexed) {\n\t\t\t\t\t\tfor (const stmt of indexedIdx.drop) {\n\t\t\t\t\t\t\tawait sql.raw(stmt).execute(ddlDb);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (now.search && !was?.search) {\n\t\t\t\t\t\tawait sql\n\t\t\t\t\t\t\t.raw(\n\t\t\t\t\t\t\t\t`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${trgmIdx} ON ${qualifiedName} USING gin (${colName} gin_trgm_ops)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t\t} else if (!now.search && was?.search) {\n\t\t\t\t\t\tawait sql\n\t\t\t\t\t\t\t.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${trgmIdx}`)\n\t\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// uniqueKeys additions: ADD CONSTRAINT in place (idempotent via\n\t\t\t// pg_constraint check — Postgres has no ADD CONSTRAINT IF NOT EXISTS).\n\t\t\t// Removals never reach here: hasBreakingChanges classifies them\n\t\t\t// breaking, which lands in the reindex branch above.\n\t\t\tconst addedUq: Record<string, string[][]> = {};\n\t\t\tfor (const [tableName, conDiff] of Object.entries(diff.constraints)) {\n\t\t\t\tconst qualifiedName = `${schemaName}.${tableName}`;\n\t\t\t\tfor (const cols of conDiff.addedUniqueKeys) {\n\t\t\t\t\tconst constraintName = `uq_${schemaName}_${tableName}_${cols.join(\"_\")}`;\n\t\t\t\t\tconst exists = await sql<{ exists: boolean }>`\n\t\t\t\t\t\tSELECT EXISTS (\n\t\t\t\t\t\t\tSELECT 1 FROM pg_constraint\n\t\t\t\t\t\t\tWHERE conname = ${constraintName}\n\t\t\t\t\t\t) AS \"exists\"\n\t\t\t\t\t`\n\t\t\t\t\t\t.execute(ddlDb)\n\t\t\t\t\t\t.then((r) => r.rows[0]?.exists ?? false);\n\t\t\t\t\tif (!exists) {\n\t\t\t\t\t\tawait sql\n\t\t\t\t\t\t\t.raw(\n\t\t\t\t\t\t\t\t`ALTER TABLE ${qualifiedName} ADD CONSTRAINT ${constraintName} UNIQUE (${cols.join(\", \")})`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t\t}\n\t\t\t\t\taddedUq[tableName] = [...(addedUq[tableName] ?? []), cols];\n\t\t\t\t}\n\t\t\t\t// Composite indexes: additive both ways. Names are positional in the\n\t\t\t\t// incoming schema; a reordered (unchanged-value) entry keeps its old\n\t\t\t\t// positionally-derived name, which is harmless.\n\t\t\t\tfor (const cols of conDiff.addedIndexes) {\n\t\t\t\t\tconst i = (def.schema[tableName]?.indexes ?? []).findIndex(\n\t\t\t\t\t\t(entry) => JSON.stringify(entry) === JSON.stringify(cols),\n\t\t\t\t\t);\n\t\t\t\t\tconst idxName = `idx_${schemaName}_${tableName}_composite_${i}`;\n\t\t\t\t\tawait sql\n\t\t\t\t\t\t.raw(\n\t\t\t\t\t\t\t`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${idxName} ON ${qualifiedName} (${cols.join(\", \")})`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t}\n\t\t\t\tfor (const cols of conDiff.removedIndexes) {\n\t\t\t\t\tconst i = (existingSchema[tableName]?.indexes ?? []).findIndex(\n\t\t\t\t\t\t(entry) => JSON.stringify(entry) === JSON.stringify(cols),\n\t\t\t\t\t);\n\t\t\t\t\tif (i < 0) continue;\n\t\t\t\t\tconst idxName = `idx_${schemaName}_${tableName}_composite_${i}`;\n\t\t\t\t\tawait sql\n\t\t\t\t\t\t.raw(`DROP INDEX CONCURRENTLY IF EXISTS ${schemaName}.${idxName}`)\n\t\t\t\t\t\t.execute(ddlDb);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst sg = await registerSubgraph(db, regData);\n\t\t\tconst addedCols: Record<string, string[]> = {};\n\t\t\tfor (const [t, colDiff] of Object.entries(diff.tables)) {\n\t\t\t\tif ((colDiff as ColumnDiff).added.length > 0)\n\t\t\t\t\taddedCols[t] = (colDiff as ColumnDiff).added;\n\t\t\t}\n\t\t\tconst deployDiff: DeployDiff = {\n\t\t\t\taddedTables: diff.addedTables,\n\t\t\t\tremovedTables: [],\n\t\t\t\taddedColumns: addedCols,\n\t\t\t\tbreakingChanges: [],\n\t\t\t\t...(Object.keys(flagFlips).length > 0\n\t\t\t\t\t? { indexChanges: flagFlips }\n\t\t\t\t\t: {}),\n\t\t\t\t...(Object.keys(addedUq).length > 0\n\t\t\t\t\t? { addedUniqueKeys: addedUq }\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t\treturn {\n\t\t\t\taction: \"updated\",\n\t\t\t\tsubgraphId: sg.id,\n\t\t\t\tversion: newVersion,\n\t\t\t\tdiff: deployDiff,\n\t\t\t};\n\t\t}\n\t}\n\n\t// New subgraph — execute all DDL\n\tfor (const stmt of statements) {\n\t\tawait sql.raw(stmt).execute(ddlDb);\n\t}\n\n\tconst sg = await registerSubgraph(db, regData);\n\treturn { action: \"created\", subgraphId: sg.id, version: newVersion };\n}\n\nfunction getDefault(type: string): string {\n\tswitch (type) {\n\t\tcase \"text\":\n\t\tcase \"principal\":\n\t\t\treturn \"''\";\n\t\tcase \"uint\":\n\t\tcase \"int\":\n\t\t\treturn \"0\";\n\t\tcase \"boolean\":\n\t\t\treturn \"false\";\n\t\tcase \"timestamp\":\n\t\t\treturn \"NOW()\";\n\t\tcase \"jsonb\":\n\t\t\treturn \"'{}'\";\n\t\tdefault:\n\t\t\treturn \"''\";\n\t}\n}\n",
|
|
8
|
+
"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"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "054E6A0FD91586DA64756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AbiContract as
|
|
2
|
-
import { AssetIdentifier } from "@secondlayer/stacks/filters";
|
|
1
|
+
import { AbiContract as AbiContract3, ExtractFunctionArgs as ExtractFunctionArgs2, ExtractFunctionNames } from "@secondlayer/stacks/clarity";
|
|
3
2
|
/**
|
|
4
3
|
* How long a read stays valid.
|
|
5
4
|
*
|
|
@@ -28,6 +27,8 @@ interface ErasedChainReadClient {
|
|
|
28
27
|
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>
|
|
29
28
|
};
|
|
30
29
|
}
|
|
30
|
+
import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
|
|
31
|
+
import { AssetIdentifier } from "@secondlayer/stacks/filters";
|
|
31
32
|
/** Supported column types for subgraph schemas */
|
|
32
33
|
type ColumnType = "text" | "uint" | "int" | "principal" | "boolean" | "timestamp" | "jsonb";
|
|
33
34
|
/** Column definition in a subgraph table */
|
|
@@ -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>;
|
|
@@ -234,9 +217,8 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
|
|
|
234
217
|
/**
|
|
235
218
|
* One contract id, or a SET of them (max 20) — the standard DeFi shape is
|
|
236
219
|
* a router plus N pools, which used to cost N near-identical sources and
|
|
237
|
-
* handlers
|
|
238
|
-
*
|
|
239
|
-
* `event.contractId` disambiguates.
|
|
220
|
+
* handlers. Payload types are identical per `type`, so one handler serves
|
|
221
|
+
* the set and `event.contractId` disambiguates.
|
|
240
222
|
*
|
|
241
223
|
* Supports `*` wildcards (e.g. `"SP1ABC….pool-*"`). Mutually exclusive
|
|
242
224
|
* with `trait`, which resolves its own set per block.
|
|
@@ -250,8 +232,11 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
|
|
|
250
232
|
* definition and used at runtime to decode args by name. Omit to keep
|
|
251
233
|
* `event.args` as a positional `unknown[]`.
|
|
252
234
|
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
235
|
+
* Required whenever `functionName` is set. `secondlayer subgraphs deploy`
|
|
236
|
+
* fills it in from the deployed contract for a single concrete
|
|
237
|
+
* `contractId`; pass it yourself for wildcard, multi-contract or trait
|
|
238
|
+
* sources, or a local deploy (`normalizeAbi()` from
|
|
239
|
+
* `@secondlayer/stacks/clarity`).
|
|
255
240
|
*/
|
|
256
241
|
abi?: AbiContract2;
|
|
257
242
|
}
|
|
@@ -308,29 +293,9 @@ type PrintField = ColumnType | {
|
|
|
308
293
|
* is skipped and logged rather than written as nulls.
|
|
309
294
|
*/
|
|
310
295
|
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
296
|
type PrintEventFields = FactoryScope & {
|
|
330
297
|
type: "print_event"
|
|
331
298
|
topic?: string
|
|
332
|
-
/** Identity map: insert without a handler function. XOR with handlers[name]. */
|
|
333
|
-
materialize?: MaterializeSpec
|
|
334
299
|
};
|
|
335
300
|
/**
|
|
336
301
|
* Pinned to one or more contract ids with no trait — `prints` is required so
|
|
@@ -374,65 +339,6 @@ interface TxMeta {
|
|
|
374
339
|
contractId?: string | null;
|
|
375
340
|
functionName?: string | null;
|
|
376
341
|
}
|
|
377
|
-
/** Scalar types that can appear as row values */
|
|
378
|
-
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
|
-
interface MatchedTx {
|
|
382
|
-
tx: TxRecord;
|
|
383
|
-
events: EventRecord[];
|
|
384
|
-
/** Source object key — used for handler dispatch */
|
|
385
|
-
sourceName: string;
|
|
386
|
-
}
|
|
387
|
-
type TxRecord = {
|
|
388
|
-
tx_id: string
|
|
389
|
-
type: string
|
|
390
|
-
sender: string
|
|
391
|
-
status: string
|
|
392
|
-
/** Position within the block — the runner sorts dispatch into chain order. */
|
|
393
|
-
tx_index?: number
|
|
394
|
-
contract_id?: string | null
|
|
395
|
-
function_name?: string | null
|
|
396
|
-
function_args?: unknown | null
|
|
397
|
-
raw_result?: string | null
|
|
398
|
-
};
|
|
399
|
-
type EventRecord = {
|
|
400
|
-
id: string
|
|
401
|
-
tx_id: string
|
|
402
|
-
type: string
|
|
403
|
-
/** Classic `event_index`, or `ordinal` when `clock === "vm"`. */
|
|
404
|
-
event_index: number
|
|
405
|
-
data: unknown
|
|
406
|
-
/** Set on opt-in `vm_events` rows. Two clocks never sort or dedupe together. */
|
|
407
|
-
clock?: "vm"
|
|
408
|
-
};
|
|
409
|
-
interface BlockMeta {
|
|
410
|
-
height: number;
|
|
411
|
-
hash: string;
|
|
412
|
-
timestamp: number;
|
|
413
|
-
burnBlockHeight: number;
|
|
414
|
-
/**
|
|
415
|
-
* Nakamoto StacksBlockId — the identifier `?tip=` accepts, and the only way
|
|
416
|
-
* to pin a read-only call to THIS block. Null on rows ingested before it
|
|
417
|
-
* was persisted; `ctx.client.readOnly` refuses to run rather than silently
|
|
418
|
-
* reading at the node's tip.
|
|
419
|
-
*/
|
|
420
|
-
indexBlockHash?: string | null;
|
|
421
|
-
}
|
|
422
|
-
interface TxMeta2 {
|
|
423
|
-
txId: string;
|
|
424
|
-
sender: string;
|
|
425
|
-
type: string;
|
|
426
|
-
status: string;
|
|
427
|
-
contractId?: string | null;
|
|
428
|
-
functionName?: string | null;
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Build a typed event payload based on the source filter type.
|
|
432
|
-
* Returns the payload the handler will receive.
|
|
433
|
-
*/
|
|
434
|
-
declare function buildEventPayload(filter: SubgraphFilter, tx: MatchedTx["tx"], event: MatchedTx["events"][0] | null): Record<string, unknown>;
|
|
435
|
-
import { AbiContract as AbiContract3, ExtractFunctionArgs as ExtractFunctionArgs2, ExtractFunctionNames } from "@secondlayer/stacks/clarity";
|
|
436
342
|
/** Maps a ColumnType string literal to its TypeScript equivalent */
|
|
437
343
|
type ColumnToTS<T extends string> = T extends "uint" | "int" ? bigint : T extends "text" | "principal" | "timestamp" ? string : T extends "boolean" ? boolean : T extends "jsonb" ? Record<string, unknown> : unknown;
|
|
438
344
|
/** Infer TS type for a single column definition, respecting nullable */
|
|
@@ -481,8 +387,6 @@ type WriteColumnType<C extends SubgraphColumn> = C["type"] extends "uint" | "int
|
|
|
481
387
|
* defaulted columns are optional; all others required.
|
|
482
388
|
*/
|
|
483
389
|
type WriteRow<T extends SubgraphTable> = { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? never : K] : WriteColumnType<T["columns"][K]> } & { [K in keyof T["columns"] as IsOptionalColumn<T["columns"][K]> extends true ? K : never]? : WriteColumnType<T["columns"][K]> };
|
|
484
|
-
/** Computed-or-value row for `patchOrInsert` — each field may be a function of the existing row. */
|
|
485
|
-
type PatchRow<T extends SubgraphTable> = { [K in keyof WriteRow<T>]? : WriteRow<T>[K] | ((existing: InferTableRow<T> | null) => unknown) };
|
|
486
390
|
type TableName<S extends SubgraphSchema> = keyof S & string;
|
|
487
391
|
type ColumnName<
|
|
488
392
|
S extends SubgraphSchema,
|
|
@@ -522,8 +426,6 @@ interface TypedSubgraphContext<S extends SubgraphSchema> {
|
|
|
522
426
|
K extends Partial<WriteRow<S[T]>>
|
|
523
427
|
>(table: T, key: K, row: Omit<WriteRow<S[T]>, keyof K> & Partial<WriteRow<S[T]>>): void;
|
|
524
428
|
delete<T extends TableName<S>>(table: T, where: RowWhere<S, T>): void;
|
|
525
|
-
patch<T extends TableName<S>>(table: T, where: RowWhere<S, T>, set: Partial<WriteRow<S[T]>>): void;
|
|
526
|
-
patchOrInsert<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, row: PatchRow<S[T]> & Record<string, ComputedValue>): Promise<void>;
|
|
527
429
|
/**
|
|
528
430
|
* Atomic accumulator — `INSERT … ON CONFLICT (key) DO UPDATE SET col =
|
|
529
431
|
* COALESCE(col,0) + delta`. Deltas commute, so it's the reorg-safe primitive
|
|
@@ -533,12 +435,6 @@ interface TypedSubgraphContext<S extends SubgraphSchema> {
|
|
|
533
435
|
increment<T extends TableName<S>>(table: T, key: Partial<WriteRow<S[T]>>, deltas: Partial<Record<ColumnName<S, T>, bigint | number>>): void;
|
|
534
436
|
findOne<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]> | null>;
|
|
535
437
|
findMany<T extends TableName<S>>(table: T, where: RowWhere<S, T>): Promise<InferTableRow<S[T]>[]>;
|
|
536
|
-
formatUnits(value: bigint, decimals: number): string;
|
|
537
|
-
count<T extends TableName<S>>(table: T, where?: RowWhere<S, T>): Promise<number>;
|
|
538
|
-
sum<T extends TableName<S>>(table: T, column: ColumnName<S, T>, where?: RowWhere<S, T>): Promise<bigint>;
|
|
539
|
-
min<T extends TableName<S>>(table: T, column: ColumnName<S, T>, where?: RowWhere<S, T>): Promise<bigint | null>;
|
|
540
|
-
max<T extends TableName<S>>(table: T, column: ColumnName<S, T>, where?: RowWhere<S, T>): Promise<bigint | null>;
|
|
541
|
-
countDistinct<T extends TableName<S>>(table: T, column: ColumnName<S, T>, where?: RowWhere<S, T>): Promise<number>;
|
|
542
438
|
}
|
|
543
439
|
interface FtTransferPayload {
|
|
544
440
|
sender: string;
|
|
@@ -734,6 +630,60 @@ type EventForFilter<F extends SubgraphFilter> = F extends {
|
|
|
734
630
|
} ? VarSetPayload : F extends {
|
|
735
631
|
type: infer T extends "map_set" | "map_insert" | "map_delete"
|
|
736
632
|
} ? T extends "map_delete" ? MapDeletePayload : MapWritePayload : never;
|
|
633
|
+
interface BlockMeta {
|
|
634
|
+
height: number;
|
|
635
|
+
hash: string;
|
|
636
|
+
timestamp: number;
|
|
637
|
+
burnBlockHeight: number;
|
|
638
|
+
/**
|
|
639
|
+
* Nakamoto StacksBlockId — the identifier `?tip=` accepts, and the only way
|
|
640
|
+
* to pin a read-only call to THIS block. Null on rows ingested before it
|
|
641
|
+
* was persisted; `ctx.client.readOnly` refuses to run rather than silently
|
|
642
|
+
* reading at the node's tip.
|
|
643
|
+
*/
|
|
644
|
+
indexBlockHash?: string | null;
|
|
645
|
+
}
|
|
646
|
+
interface TxMeta2 {
|
|
647
|
+
txId: string;
|
|
648
|
+
sender: string;
|
|
649
|
+
type: string;
|
|
650
|
+
status: string;
|
|
651
|
+
contractId?: string | null;
|
|
652
|
+
functionName?: string | null;
|
|
653
|
+
}
|
|
654
|
+
interface MatchedTx {
|
|
655
|
+
tx: TxRecord;
|
|
656
|
+
events: EventRecord[];
|
|
657
|
+
/** Source object key — used for handler dispatch */
|
|
658
|
+
sourceName: string;
|
|
659
|
+
}
|
|
660
|
+
type TxRecord = {
|
|
661
|
+
tx_id: string
|
|
662
|
+
type: string
|
|
663
|
+
sender: string
|
|
664
|
+
status: string
|
|
665
|
+
/** Position within the block — the runner sorts dispatch into chain order. */
|
|
666
|
+
tx_index?: number
|
|
667
|
+
contract_id?: string | null
|
|
668
|
+
function_name?: string | null
|
|
669
|
+
function_args?: unknown | null
|
|
670
|
+
raw_result?: string | null
|
|
671
|
+
};
|
|
672
|
+
type EventRecord = {
|
|
673
|
+
id: string
|
|
674
|
+
tx_id: string
|
|
675
|
+
type: string
|
|
676
|
+
/** Classic `event_index`, or `ordinal` when `clock === "vm"`. */
|
|
677
|
+
event_index: number
|
|
678
|
+
data: unknown
|
|
679
|
+
/** Set on opt-in `vm_events` rows. Two clocks never sort or dedupe together. */
|
|
680
|
+
clock?: "vm"
|
|
681
|
+
};
|
|
682
|
+
/**
|
|
683
|
+
* Build a typed event payload based on the source filter type.
|
|
684
|
+
* Returns the payload the handler will receive.
|
|
685
|
+
*/
|
|
686
|
+
declare function buildEventPayload(filter: SubgraphFilter, tx: MatchedTx["tx"], event: MatchedTx["events"][0] | null): Record<string, unknown>;
|
|
737
687
|
/** An in-memory subgraph context for tests. */
|
|
738
688
|
interface TestSubgraphContext<S extends SubgraphSchema> extends Omit<TypedSubgraphContext<S>, never> {
|
|
739
689
|
/**
|
|
@@ -901,4 +851,4 @@ declare function probeHandlers(def: ProbeHandlersDef, samples: Array<{
|
|
|
901
851
|
source: string
|
|
902
852
|
event: Record<string, unknown>
|
|
903
853
|
}>): Promise<ProbeHandlersResult>;
|
|
904
|
-
export {
|
|
854
|
+
export { BlockMeta, EventTrace, IndexContractCallRow, IndexEventRow, IndexTestRow, ProbeHandlersDef, ProbeHandlersResult, RunSubgraphTestInput, SubgraphTestResult, SubgraphTestSource, TestSubgraphContext, TxMeta2 as TxMeta, buildEvent, buildEventPayload, createTestContext, probeHandlers, runSubgraphTest, toContractCallPayload, toHandlerPayload };
|