@secondlayer/subgraphs 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -0
- package/dist/src/index.d.ts +71 -9
- package/dist/src/index.js +461 -54
- package/dist/src/index.js.map +11 -9
- package/dist/src/runtime/block-processor.d.ts +37 -9
- package/dist/src/runtime/block-processor.js +127 -37
- package/dist/src/runtime/block-processor.js.map +5 -5
- package/dist/src/runtime/catchup.d.ts +34 -8
- package/dist/src/runtime/catchup.js +125 -36
- package/dist/src/runtime/catchup.js.map +5 -5
- package/dist/src/runtime/context.d.ts +27 -1
- package/dist/src/runtime/context.js +13 -2
- package/dist/src/runtime/context.js.map +3 -3
- package/dist/src/runtime/processor.js +143 -39
- package/dist/src/runtime/processor.js.map +8 -8
- package/dist/src/runtime/reindex.d.ts +34 -8
- package/dist/src/runtime/reindex.js +131 -36
- package/dist/src/runtime/reindex.js.map +6 -6
- package/dist/src/runtime/reorg.d.ts +34 -8
- package/dist/src/runtime/reorg.js +131 -39
- package/dist/src/runtime/reorg.js.map +6 -6
- package/dist/src/runtime/runner.d.ts +43 -9
- package/dist/src/runtime/source-matcher.d.ts +19 -10
- package/dist/src/runtime/source-matcher.js +26 -6
- package/dist/src/runtime/source-matcher.js.map +3 -3
- package/dist/src/schema/index.d.ts +42 -8
- package/dist/src/schema/index.js +57 -19
- package/dist/src/schema/index.js.map +5 -5
- package/dist/src/service.js +143 -39
- package/dist/src/service.js.map +8 -8
- package/dist/src/triggers/index.d.ts +16 -8
- package/dist/src/types.d.ts +35 -9
- package/dist/src/validate.d.ts +34 -8
- package/dist/src/validate.js +10 -3
- package/dist/src/validate.js.map +3 -3
- package/package.json +3 -3
|
@@ -9,6 +9,22 @@ interface SubgraphColumn {
|
|
|
9
9
|
search?: boolean;
|
|
10
10
|
default?: string | number | boolean;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* A foreign-key relation to another table in the same subgraph. Drives DDL FK
|
|
14
|
+
* constraints and ORM codegen (`@relation` in Prisma, `relations()` in Drizzle)
|
|
15
|
+
* so generated clients get typed joins. The referenced columns must form a
|
|
16
|
+
* `uniqueKeys` entry on the target table.
|
|
17
|
+
*/
|
|
18
|
+
interface SubgraphRelation {
|
|
19
|
+
/** Relation field name on this table's generated model (e.g. "pool"). */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Target table name in this subgraph. */
|
|
22
|
+
references: string;
|
|
23
|
+
/** Local column(s) holding the foreign key. */
|
|
24
|
+
fields: string[];
|
|
25
|
+
/** Target column(s) the fields point at (a uniqueKeys entry on the target). */
|
|
26
|
+
referencedColumns: string[];
|
|
27
|
+
}
|
|
12
28
|
/** Table definition within a subgraph schema */
|
|
13
29
|
interface SubgraphTable {
|
|
14
30
|
columns: Record<string, SubgraphColumn>;
|
|
@@ -16,6 +32,8 @@ interface SubgraphTable {
|
|
|
16
32
|
indexes?: string[][];
|
|
17
33
|
/** Unique key constraints (each entry is an array of column names). Required for upsert. */
|
|
18
34
|
uniqueKeys?: string[][];
|
|
35
|
+
/** Foreign-key relations to other tables (for typed ORM joins). */
|
|
36
|
+
relations?: SubgraphRelation[];
|
|
19
37
|
}
|
|
20
38
|
/** Subgraph schema — maps table names to table definitions */
|
|
21
39
|
type SubgraphSchema = Record<string, SubgraphTable>;
|
|
@@ -42,45 +60,53 @@ interface StxLockFilter {
|
|
|
42
60
|
lockedAddress?: string;
|
|
43
61
|
minAmount?: bigint;
|
|
44
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Restrict a source to contracts conforming to a trait/standard (e.g. "sip-010")
|
|
65
|
+
* instead of a fixed contract — resolved from the contract registry at match time,
|
|
66
|
+
* as-of each processed block. Lets a source index "all SIP-010 tokens" etc.
|
|
67
|
+
*/
|
|
68
|
+
type TraitScope = {
|
|
69
|
+
trait?: string
|
|
70
|
+
};
|
|
45
71
|
/** FT event filters */
|
|
46
|
-
interface FtTransferFilter {
|
|
72
|
+
interface FtTransferFilter extends TraitScope {
|
|
47
73
|
type: "ft_transfer";
|
|
48
74
|
assetIdentifier?: string;
|
|
49
75
|
sender?: string;
|
|
50
76
|
recipient?: string;
|
|
51
77
|
minAmount?: bigint;
|
|
52
78
|
}
|
|
53
|
-
interface FtMintFilter {
|
|
79
|
+
interface FtMintFilter extends TraitScope {
|
|
54
80
|
type: "ft_mint";
|
|
55
81
|
assetIdentifier?: string;
|
|
56
82
|
recipient?: string;
|
|
57
83
|
minAmount?: bigint;
|
|
58
84
|
}
|
|
59
|
-
interface FtBurnFilter {
|
|
85
|
+
interface FtBurnFilter extends TraitScope {
|
|
60
86
|
type: "ft_burn";
|
|
61
87
|
assetIdentifier?: string;
|
|
62
88
|
sender?: string;
|
|
63
89
|
minAmount?: bigint;
|
|
64
90
|
}
|
|
65
91
|
/** NFT event filters */
|
|
66
|
-
interface NftTransferFilter {
|
|
92
|
+
interface NftTransferFilter extends TraitScope {
|
|
67
93
|
type: "nft_transfer";
|
|
68
94
|
assetIdentifier?: string;
|
|
69
95
|
sender?: string;
|
|
70
96
|
recipient?: string;
|
|
71
97
|
}
|
|
72
|
-
interface NftMintFilter {
|
|
98
|
+
interface NftMintFilter extends TraitScope {
|
|
73
99
|
type: "nft_mint";
|
|
74
100
|
assetIdentifier?: string;
|
|
75
101
|
recipient?: string;
|
|
76
102
|
}
|
|
77
|
-
interface NftBurnFilter {
|
|
103
|
+
interface NftBurnFilter extends TraitScope {
|
|
78
104
|
type: "nft_burn";
|
|
79
105
|
assetIdentifier?: string;
|
|
80
106
|
sender?: string;
|
|
81
107
|
}
|
|
82
108
|
/** Contract event filters */
|
|
83
|
-
interface ContractCallFilter {
|
|
109
|
+
interface ContractCallFilter extends TraitScope {
|
|
84
110
|
type: "contract_call";
|
|
85
111
|
contractId?: string;
|
|
86
112
|
functionName?: string;
|
|
@@ -98,7 +124,7 @@ interface ContractDeployFilter {
|
|
|
98
124
|
deployer?: string;
|
|
99
125
|
contractName?: string;
|
|
100
126
|
}
|
|
101
|
-
interface PrintEventFilter {
|
|
127
|
+
interface PrintEventFilter extends TraitScope {
|
|
102
128
|
type: "print_event";
|
|
103
129
|
contractId?: string;
|
|
104
130
|
topic?: string;
|
|
@@ -18,12 +18,14 @@ class SubgraphContext {
|
|
|
18
18
|
pgSchemaName;
|
|
19
19
|
subgraphSchema;
|
|
20
20
|
ops = [];
|
|
21
|
-
|
|
21
|
+
byo;
|
|
22
|
+
constructor(db, pgSchemaName, subgraphSchema, block, tx, byo = false) {
|
|
22
23
|
this.db = db;
|
|
23
24
|
this.pgSchemaName = pgSchemaName;
|
|
24
25
|
this.subgraphSchema = subgraphSchema;
|
|
25
26
|
this.block = block;
|
|
26
27
|
this._tx = tx;
|
|
28
|
+
this.byo = byo;
|
|
27
29
|
}
|
|
28
30
|
get tx() {
|
|
29
31
|
return this._tx;
|
|
@@ -218,6 +220,15 @@ class SubgraphContext {
|
|
|
218
220
|
}
|
|
219
221
|
buildStatements(ops) {
|
|
220
222
|
const statements = [];
|
|
223
|
+
if (this.byo) {
|
|
224
|
+
const insertTables = new Set;
|
|
225
|
+
for (const op of ops)
|
|
226
|
+
if (op.kind === "insert")
|
|
227
|
+
insertTables.add(op.table);
|
|
228
|
+
for (const table of insertTables) {
|
|
229
|
+
statements.push(`DELETE FROM "${this.pgSchemaName}"."${table}" WHERE "_block_height" = ${this.block.height}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
221
232
|
let currentBatch = null;
|
|
222
233
|
let currentBatchKey = "";
|
|
223
234
|
const flushInsertBatch = () => {
|
|
@@ -711,7 +722,19 @@ function matchPattern(value, pattern) {
|
|
|
711
722
|
}
|
|
712
723
|
return re.test(value);
|
|
713
724
|
}
|
|
714
|
-
|
|
725
|
+
var EMPTY_SET = new Set;
|
|
726
|
+
function traitAllows(filter, contractId, traitContracts) {
|
|
727
|
+
const trait = filter.trait;
|
|
728
|
+
if (!trait)
|
|
729
|
+
return true;
|
|
730
|
+
if (!contractId)
|
|
731
|
+
return false;
|
|
732
|
+
return (traitContracts.get(trait) ?? EMPTY_SET).has(contractId);
|
|
733
|
+
}
|
|
734
|
+
function assetContract(assetId) {
|
|
735
|
+
return assetId?.split("::")[0];
|
|
736
|
+
}
|
|
737
|
+
function matchFilter(filter, transactions, eventsByTx, traitContracts) {
|
|
715
738
|
const results = [];
|
|
716
739
|
switch (filter.type) {
|
|
717
740
|
case "stx_transfer":
|
|
@@ -775,6 +798,8 @@ function matchFilter(filter, transactions, eventsByTx) {
|
|
|
775
798
|
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
776
799
|
return false;
|
|
777
800
|
}
|
|
801
|
+
if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
|
|
802
|
+
return false;
|
|
778
803
|
if ("sender" in filter && filter.sender) {
|
|
779
804
|
if (!matchPattern(data.sender, filter.sender))
|
|
780
805
|
return false;
|
|
@@ -813,6 +838,8 @@ function matchFilter(filter, transactions, eventsByTx) {
|
|
|
813
838
|
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
814
839
|
return false;
|
|
815
840
|
}
|
|
841
|
+
if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
|
|
842
|
+
return false;
|
|
816
843
|
if ("sender" in filter && filter.sender) {
|
|
817
844
|
if (!matchPattern(data.sender, filter.sender))
|
|
818
845
|
return false;
|
|
@@ -845,6 +872,8 @@ function matchFilter(filter, transactions, eventsByTx) {
|
|
|
845
872
|
if (!matchPattern(tx.sender, filter.caller))
|
|
846
873
|
continue;
|
|
847
874
|
}
|
|
875
|
+
if (!traitAllows(filter, tx.contract_id, traitContracts))
|
|
876
|
+
continue;
|
|
848
877
|
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
849
878
|
results.push({ tx, events: txEvents });
|
|
850
879
|
}
|
|
@@ -879,11 +908,13 @@ function matchFilter(filter, transactions, eventsByTx) {
|
|
|
879
908
|
return false;
|
|
880
909
|
if (data.topic !== "print")
|
|
881
910
|
return false;
|
|
911
|
+
const printContractId = data.contract_identifier ?? data.contract_id;
|
|
882
912
|
if (filter.contractId) {
|
|
883
|
-
|
|
884
|
-
if (!contractId || !matchPattern(contractId, filter.contractId))
|
|
913
|
+
if (!printContractId || !matchPattern(printContractId, filter.contractId))
|
|
885
914
|
return false;
|
|
886
915
|
}
|
|
916
|
+
if (!traitAllows(filter, printContractId, traitContracts))
|
|
917
|
+
return false;
|
|
887
918
|
return true;
|
|
888
919
|
});
|
|
889
920
|
if (matched.length > 0) {
|
|
@@ -895,7 +926,7 @@ function matchFilter(filter, transactions, eventsByTx) {
|
|
|
895
926
|
}
|
|
896
927
|
return results;
|
|
897
928
|
}
|
|
898
|
-
function matchSources(sources, transactions, events) {
|
|
929
|
+
function matchSources(sources, transactions, events, traitContracts = new Map) {
|
|
899
930
|
const eventsByTx = new Map;
|
|
900
931
|
for (const event of events) {
|
|
901
932
|
const list = eventsByTx.get(event.tx_id) ?? [];
|
|
@@ -905,7 +936,7 @@ function matchSources(sources, transactions, events) {
|
|
|
905
936
|
const seen = new Set;
|
|
906
937
|
const results = [];
|
|
907
938
|
for (const [sourceName, filter] of Object.entries(sources)) {
|
|
908
|
-
const matches = matchFilter(filter, transactions, eventsByTx);
|
|
939
|
+
const matches = matchFilter(filter, transactions, eventsByTx, traitContracts);
|
|
909
940
|
for (const match of matches) {
|
|
910
941
|
const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
|
|
911
942
|
if (!seen.has(dedupeKey)) {
|
|
@@ -922,8 +953,11 @@ import {
|
|
|
922
953
|
getSourceDb,
|
|
923
954
|
getTargetDb
|
|
924
955
|
} from "@secondlayer/shared/db";
|
|
956
|
+
import { resolveTraitContractIds } from "@secondlayer/shared/db/queries/contracts";
|
|
925
957
|
import {
|
|
958
|
+
isByoSubgraph,
|
|
926
959
|
recordSubgraphProcessed,
|
|
960
|
+
resolveSubgraphDb,
|
|
927
961
|
updateSubgraphStatus
|
|
928
962
|
} from "@secondlayer/shared/db/queries/subgraphs";
|
|
929
963
|
import { logger as logger4 } from "@secondlayer/shared/logger";
|
|
@@ -1161,7 +1195,38 @@ async function refreshMatcher(db) {
|
|
|
1161
1195
|
}
|
|
1162
1196
|
|
|
1163
1197
|
// src/runtime/block-processor.ts
|
|
1164
|
-
var
|
|
1198
|
+
var routeCache = new Map;
|
|
1199
|
+
async function resolveRoute(subgraphName, targetDb) {
|
|
1200
|
+
const cached = routeCache.get(subgraphName);
|
|
1201
|
+
if (cached)
|
|
1202
|
+
return cached;
|
|
1203
|
+
const row = await targetDb.selectFrom("subgraphs").selectAll().where("name", "=", subgraphName).executeTakeFirst();
|
|
1204
|
+
const byo = row ? isByoSubgraph(row) : false;
|
|
1205
|
+
const route = {
|
|
1206
|
+
schemaName: row?.schema_name ?? pgSchemaName(subgraphName),
|
|
1207
|
+
dataDb: row && byo ? resolveSubgraphDb(row) : targetDb,
|
|
1208
|
+
byo
|
|
1209
|
+
};
|
|
1210
|
+
routeCache.set(subgraphName, route);
|
|
1211
|
+
return route;
|
|
1212
|
+
}
|
|
1213
|
+
function invalidateSubgraphRoute(subgraphName) {
|
|
1214
|
+
routeCache.delete(subgraphName);
|
|
1215
|
+
}
|
|
1216
|
+
async function resolveTraitContracts(subgraph, blockHeight, db) {
|
|
1217
|
+
const traits = new Set;
|
|
1218
|
+
for (const source of Object.values(subgraph.sources)) {
|
|
1219
|
+
const trait = source.trait;
|
|
1220
|
+
if (trait)
|
|
1221
|
+
traits.add(trait);
|
|
1222
|
+
}
|
|
1223
|
+
const resolved = new Map;
|
|
1224
|
+
for (const trait of traits) {
|
|
1225
|
+
const ids = await resolveTraitContractIds(db, trait, blockHeight);
|
|
1226
|
+
resolved.set(trait, new Set(ids));
|
|
1227
|
+
}
|
|
1228
|
+
return resolved;
|
|
1229
|
+
}
|
|
1165
1230
|
async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
1166
1231
|
const sourceDb = getSourceDb();
|
|
1167
1232
|
const targetDb = getTargetDb();
|
|
@@ -1201,7 +1266,8 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
1201
1266
|
txs = await sourceDb.selectFrom("transactions").selectAll().where("block_height", "=", blockHeight).execute();
|
|
1202
1267
|
evts = await sourceDb.selectFrom("events").selectAll().where("block_height", "=", blockHeight).execute();
|
|
1203
1268
|
}
|
|
1204
|
-
const
|
|
1269
|
+
const traitContracts = await resolveTraitContracts(subgraph, blockHeight, targetDb);
|
|
1270
|
+
const matched = matchSources(subgraph.sources, txs, evts, traitContracts);
|
|
1205
1271
|
result.matched = matched.length;
|
|
1206
1272
|
if (matched.length === 0) {
|
|
1207
1273
|
if (!opts?.skipProgressUpdate) {
|
|
@@ -1209,12 +1275,8 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
1209
1275
|
}
|
|
1210
1276
|
return result;
|
|
1211
1277
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
const subgraphRecord = await targetDb.selectFrom("subgraphs").select("schema_name").where("name", "=", subgraphName).executeTakeFirst();
|
|
1215
|
-
schemaName = subgraphRecord?.schema_name ?? pgSchemaName(subgraphName);
|
|
1216
|
-
schemaNameCache.set(subgraphName, schemaName);
|
|
1217
|
-
}
|
|
1278
|
+
const route = await resolveRoute(subgraphName, targetDb);
|
|
1279
|
+
const schemaName = route.schemaName;
|
|
1218
1280
|
const blockMeta = {
|
|
1219
1281
|
height: block.height,
|
|
1220
1282
|
hash: block.hash,
|
|
@@ -1229,30 +1291,57 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
1229
1291
|
};
|
|
1230
1292
|
let handlerMs = 0;
|
|
1231
1293
|
let flushMs = 0;
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1294
|
+
const applyProgress = async (tx, rr) => {
|
|
1295
|
+
if (opts?.skipProgressUpdate)
|
|
1296
|
+
return;
|
|
1297
|
+
const status = rr.errors > 0 && rr.processed === 0 ? "error" : "active";
|
|
1298
|
+
await updateSubgraphStatus(tx, subgraphName, status, blockHeight);
|
|
1299
|
+
if (rr.processed > 0 || rr.errors > 0) {
|
|
1300
|
+
const lastError = rr.errors > 0 ? `${rr.errors} error(s) at block ${blockHeight}` : undefined;
|
|
1301
|
+
await recordSubgraphProcessed(tx, subgraphName, rr.processed, rr.errors, lastError);
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
if (route.byo) {
|
|
1305
|
+
let runResult = { processed: 0, errors: 0 };
|
|
1306
|
+
let manifest;
|
|
1307
|
+
await route.dataDb.transaction().execute(async (tx) => {
|
|
1308
|
+
const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx, true);
|
|
1309
|
+
const handlerStart = performance.now();
|
|
1310
|
+
runResult = await runHandlers(subgraph, matched, ctx);
|
|
1311
|
+
handlerMs = performance.now() - handlerStart;
|
|
1312
|
+
if (ctx.pendingOps > 0) {
|
|
1313
|
+
const flushStart = performance.now();
|
|
1314
|
+
manifest = await ctx.flush();
|
|
1315
|
+
flushMs = performance.now() - flushStart;
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1237
1318
|
result.processed = runResult.processed;
|
|
1238
1319
|
result.errors = runResult.errors;
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const manifest = await ctx.flush();
|
|
1242
|
-
if (manifest.count > 0) {
|
|
1320
|
+
await targetDb.transaction().execute(async (tx) => {
|
|
1321
|
+
if (manifest && manifest.count > 0) {
|
|
1243
1322
|
await emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block.height);
|
|
1244
1323
|
}
|
|
1245
|
-
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1324
|
+
await applyProgress(tx, runResult);
|
|
1325
|
+
});
|
|
1326
|
+
} else {
|
|
1327
|
+
await targetDb.transaction().execute(async (tx) => {
|
|
1328
|
+
const ctx = new SubgraphContext(tx, schemaName, subgraph.schema, blockMeta, initialTx);
|
|
1329
|
+
const handlerStart = performance.now();
|
|
1330
|
+
const runResult = await runHandlers(subgraph, matched, ctx);
|
|
1331
|
+
handlerMs = performance.now() - handlerStart;
|
|
1332
|
+
result.processed = runResult.processed;
|
|
1333
|
+
result.errors = runResult.errors;
|
|
1334
|
+
if (ctx.pendingOps > 0) {
|
|
1335
|
+
const flushStart = performance.now();
|
|
1336
|
+
const manifest = await ctx.flush();
|
|
1337
|
+
if (manifest.count > 0) {
|
|
1338
|
+
await emitSubscriptionOutbox(tx, subgraphName, manifest, matcher, block.height);
|
|
1339
|
+
}
|
|
1340
|
+
flushMs = performance.now() - flushStart;
|
|
1341
|
+
}
|
|
1342
|
+
await applyProgress(tx, runResult);
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1256
1345
|
const totalMs = performance.now() - blockStart;
|
|
1257
1346
|
result.timing = {
|
|
1258
1347
|
totalMs: Math.round(totalMs),
|
|
@@ -1263,7 +1352,7 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
|
|
|
1263
1352
|
try {
|
|
1264
1353
|
const tables = Object.keys(subgraph.schema);
|
|
1265
1354
|
for (const table of tables) {
|
|
1266
|
-
const { rows } = await sql3.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(
|
|
1355
|
+
const { rows } = await sql3.raw(`SELECT n_live_tup AS count FROM pg_stat_user_tables WHERE schemaname = '${schemaName}' AND relname = '${table}'`).execute(route.dataDb);
|
|
1267
1356
|
const count = Number(rows[0]?.count ?? 0);
|
|
1268
1357
|
if (count >= 1e7) {
|
|
1269
1358
|
logger4.warn("Subgraph table exceeds 10M rows (estimate)", {
|
|
@@ -1435,6 +1524,12 @@ function generateSubgraphSQL(def, schemaNameOverride) {
|
|
|
1435
1524
|
}
|
|
1436
1525
|
}
|
|
1437
1526
|
}
|
|
1527
|
+
for (const [tableName, tableDef] of Object.entries(def.schema)) {
|
|
1528
|
+
for (const rel of tableDef.relations ?? []) {
|
|
1529
|
+
const constraintName = `fk_${schemaName}_${tableName}_${rel.name}`;
|
|
1530
|
+
statements.push(`ALTER TABLE ${schemaName}.${tableName} ADD CONSTRAINT ${constraintName} ` + `FOREIGN KEY (${rel.fields.join(", ")}) ` + `REFERENCES ${schemaName}.${rel.references} (${rel.referencedColumns.join(", ")})`);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1438
1533
|
const hashInput = JSON.stringify({
|
|
1439
1534
|
name: def.name,
|
|
1440
1535
|
schema: def.schema,
|
|
@@ -1903,5 +1998,5 @@ export {
|
|
|
1903
1998
|
backfillSubgraph
|
|
1904
1999
|
};
|
|
1905
2000
|
|
|
1906
|
-
//# debugId=
|
|
2001
|
+
//# debugId=C6A12A80FA03F24E64756E2164756E21
|
|
1907
2002
|
//# sourceMappingURL=reindex.js.map
|