@latticexyz/store-indexer 2.2.18-9fa07c8489f1fbf167d0db01cd9aaa645a29c8e2 → 2.2.18-c44207f620a38653497b78db0b71f5de7bc1a940
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/postgres-decoded-indexer.js +1 -92
- package/dist/bin/postgres-decoded-indexer.js.map +1 -1
- package/dist/bin/postgres-frontend.js +5 -258
- package/dist/bin/postgres-frontend.js.map +1 -1
- package/dist/bin/postgres-indexer.js +1 -106
- package/dist/bin/postgres-indexer.js.map +1 -1
- package/dist/bin/sqlite-indexer.js +1 -243
- package/dist/bin/sqlite-indexer.js.map +1 -1
- package/dist/chunk-7O2ZWWUX.js +2 -0
- package/dist/{chunk-SJLOWI5M.js.map → chunk-7O2ZWWUX.js.map} +1 -1
- package/dist/chunk-AYPBOJNL.js +2 -0
- package/dist/{chunk-GDNGJPVT.js.map → chunk-AYPBOJNL.js.map} +1 -1
- package/dist/chunk-ED45N3IT.js +2 -0
- package/dist/{chunk-O4XAWAXU.js.map → chunk-ED45N3IT.js.map} +1 -1
- package/dist/chunk-JDWVOODJ.js +2 -0
- package/dist/{chunk-R7UQFYRA.js.map → chunk-JDWVOODJ.js.map} +1 -1
- package/dist/chunk-O2SDU7EQ.js +7 -0
- package/dist/{chunk-L5CWEDU6.js.map → chunk-O2SDU7EQ.js.map} +1 -1
- package/dist/chunk-R7HX5BT2.js +2 -0
- package/dist/{chunk-66BWQNF7.js.map → chunk-R7HX5BT2.js.map} +1 -1
- package/dist/chunk-YQ7E5W26.js +2 -0
- package/dist/{chunk-CGE4ONKA.js.map → chunk-YQ7E5W26.js.map} +1 -1
- package/dist/healthcheck-57YETUEX.js +2 -0
- package/dist/helloWorld-4VT4FZ7F.js +2 -0
- package/dist/metrics-4BMCDEZZ.js +2 -0
- package/package.json +9 -17
- package/dist/bin/postgres-decoded-indexer.cjs +0 -322
- package/dist/bin/postgres-decoded-indexer.cjs.map +0 -1
- package/dist/bin/postgres-decoded-indexer.d.cts +0 -1
- package/dist/bin/postgres-frontend.cjs +0 -567
- package/dist/bin/postgres-frontend.cjs.map +0 -1
- package/dist/bin/postgres-frontend.d.cts +0 -1
- package/dist/bin/postgres-indexer.cjs +0 -368
- package/dist/bin/postgres-indexer.cjs.map +0 -1
- package/dist/bin/postgres-indexer.d.cts +0 -1
- package/dist/bin/sqlite-indexer.cjs +0 -567
- package/dist/bin/sqlite-indexer.cjs.map +0 -1
- package/dist/bin/sqlite-indexer.d.cts +0 -1
- package/dist/chunk-66BWQNF7.js +0 -38
- package/dist/chunk-CGE4ONKA.js +0 -44
- package/dist/chunk-GDNGJPVT.js +0 -16
- package/dist/chunk-L5CWEDU6.js +0 -53
- package/dist/chunk-O4XAWAXU.js +0 -72
- package/dist/chunk-R7UQFYRA.js +0 -99
- package/dist/chunk-SJLOWI5M.js +0 -31
- package/dist/healthcheck-2DQWYXPX.js +0 -7
- package/dist/helloWorld-6IXGINV6.js +0 -7
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +0 -2
- package/dist/metrics-HO5SO4EX.js +0 -7
- package/dist/metrics-HO5SO4EX.js.map +0 -1
- /package/dist/{healthcheck-2DQWYXPX.js.map → healthcheck-57YETUEX.js.map} +0 -0
- /package/dist/{helloWorld-6IXGINV6.js.map → helloWorld-4VT4FZ7F.js.map} +0 -0
- /package/dist/{index.cjs.map → metrics-4BMCDEZZ.js.map} +0 -0
@@ -1,567 +0,0 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
"use strict";
|
3
|
-
var __create = Object.create;
|
4
|
-
var __defProp = Object.defineProperty;
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
11
|
-
for (let key of __getOwnPropNames(from))
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
14
|
-
}
|
15
|
-
return to;
|
16
|
-
};
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
23
|
-
mod
|
24
|
-
));
|
25
|
-
|
26
|
-
// src/bin/postgres-frontend.ts
|
27
|
-
var import_config = require("dotenv/config");
|
28
|
-
var import_zod2 = require("zod");
|
29
|
-
var import_koa = __toESM(require("koa"), 1);
|
30
|
-
var import_cors = __toESM(require("@koa/cors"), 1);
|
31
|
-
var import_trpc_koa_adapter = require("trpc-koa-adapter");
|
32
|
-
var import_trpc_indexer = require("@latticexyz/store-sync/trpc-indexer");
|
33
|
-
var import_postgres_js = require("drizzle-orm/postgres-js");
|
34
|
-
var import_postgres3 = __toESM(require("postgres"), 1);
|
35
|
-
|
36
|
-
// src/bin/parseEnv.ts
|
37
|
-
var import_viem = require("viem");
|
38
|
-
var import_zod = require("zod");
|
39
|
-
var frontendEnvSchema = import_zod.z.object({
|
40
|
-
HOST: import_zod.z.string().default("0.0.0.0"),
|
41
|
-
PORT: import_zod.z.coerce.number().positive().default(3001)
|
42
|
-
});
|
43
|
-
var indexerEnvSchema = import_zod.z.intersection(
|
44
|
-
import_zod.z.object({
|
45
|
-
FOLLOW_BLOCK_TAG: import_zod.z.enum(["latest", "safe", "finalized"]).default("safe"),
|
46
|
-
START_BLOCK: import_zod.z.coerce.bigint().nonnegative().default(0n),
|
47
|
-
MAX_BLOCK_RANGE: import_zod.z.coerce.bigint().positive().default(1000n),
|
48
|
-
POLLING_INTERVAL: import_zod.z.coerce.number().positive().default(1e3),
|
49
|
-
STORE_ADDRESS: import_zod.z.string().optional().transform((input2) => input2 === "" ? void 0 : input2).refine(isHexOrUndefined),
|
50
|
-
INTERNAL__VALIDATE_BLOCK_RANGE: import_zod.z.string().optional().transform((input2) => input2 === "true" || input2 === "1")
|
51
|
-
}),
|
52
|
-
import_zod.z.union([
|
53
|
-
import_zod.z.object({
|
54
|
-
RPC_HTTP_URL: import_zod.z.string(),
|
55
|
-
RPC_WS_URL: import_zod.z.string().optional()
|
56
|
-
}),
|
57
|
-
import_zod.z.object({
|
58
|
-
RPC_HTTP_URL: import_zod.z.string().optional(),
|
59
|
-
RPC_WS_URL: import_zod.z.string()
|
60
|
-
})
|
61
|
-
])
|
62
|
-
);
|
63
|
-
function parseEnv(envSchema) {
|
64
|
-
try {
|
65
|
-
return envSchema.parse(process.env);
|
66
|
-
} catch (error2) {
|
67
|
-
if (error2 instanceof import_zod.ZodError) {
|
68
|
-
const { ...invalidEnvVars } = error2.format();
|
69
|
-
console.error(`
|
70
|
-
Missing or invalid environment variables:
|
71
|
-
|
72
|
-
${Object.keys(invalidEnvVars).join("\n ")}
|
73
|
-
`);
|
74
|
-
process.exit(1);
|
75
|
-
}
|
76
|
-
throw error2;
|
77
|
-
}
|
78
|
-
}
|
79
|
-
function isHexOrUndefined(input2) {
|
80
|
-
return input2 === void 0 || (0, import_viem.isHex)(input2);
|
81
|
-
}
|
82
|
-
|
83
|
-
// src/postgres/deprecated/createQueryAdapter.ts
|
84
|
-
var import_viem2 = require("viem");
|
85
|
-
var import_store_sync = require("@latticexyz/store-sync");
|
86
|
-
var import_internal2 = require("@latticexyz/protocol-parser/internal");
|
87
|
-
|
88
|
-
// src/debug.ts
|
89
|
-
var import_debug = __toESM(require("debug"), 1);
|
90
|
-
var debug = (0, import_debug.default)("mud:store-indexer");
|
91
|
-
var error = (0, import_debug.default)("mud:store-indexer");
|
92
|
-
debug.log = console.debug.bind(console);
|
93
|
-
error.log = console.error.bind(console);
|
94
|
-
|
95
|
-
// src/postgres/deprecated/getLogs.ts
|
96
|
-
var import_postgres = require("@latticexyz/store-sync/postgres");
|
97
|
-
var import_drizzle_orm = require("drizzle-orm");
|
98
|
-
var import_utils = require("@latticexyz/common/utils");
|
99
|
-
|
100
|
-
// src/postgres/recordToLog.ts
|
101
|
-
var import_internal = require("@latticexyz/protocol-parser/internal");
|
102
|
-
function recordToLog(record) {
|
103
|
-
return {
|
104
|
-
address: record.address,
|
105
|
-
eventName: "Store_SetRecord",
|
106
|
-
args: {
|
107
|
-
tableId: record.tableId,
|
108
|
-
keyTuple: (0, import_internal.decodeDynamicField)("bytes32[]", record.keyBytes),
|
109
|
-
staticData: record.staticData ?? "0x",
|
110
|
-
encodedLengths: record.encodedLengths ?? "0x",
|
111
|
-
dynamicData: record.dynamicData ?? "0x"
|
112
|
-
}
|
113
|
-
};
|
114
|
-
}
|
115
|
-
|
116
|
-
// src/postgres/deprecated/getLogs.ts
|
117
|
-
var import_common = require("@latticexyz/common");
|
118
|
-
async function getLogs(database, {
|
119
|
-
chainId,
|
120
|
-
address,
|
121
|
-
filters = []
|
122
|
-
}) {
|
123
|
-
const benchmark = (0, import_common.createBenchmark)("drizzleGetLogs");
|
124
|
-
const conditions = filters.length ? filters.map(
|
125
|
-
(filter) => (0, import_drizzle_orm.and)(
|
126
|
-
address != null ? (0, import_drizzle_orm.eq)(import_postgres.tables.recordsTable.address, address) : void 0,
|
127
|
-
(0, import_drizzle_orm.eq)(import_postgres.tables.recordsTable.tableId, filter.tableId),
|
128
|
-
filter.key0 != null ? (0, import_drizzle_orm.eq)(import_postgres.tables.recordsTable.key0, filter.key0) : void 0,
|
129
|
-
filter.key1 != null ? (0, import_drizzle_orm.eq)(import_postgres.tables.recordsTable.key1, filter.key1) : void 0
|
130
|
-
)
|
131
|
-
) : address != null ? [(0, import_drizzle_orm.eq)(import_postgres.tables.recordsTable.address, address)] : [];
|
132
|
-
benchmark("parse config");
|
133
|
-
const chainState = await database.select().from(import_postgres.tables.configTable).where((0, import_drizzle_orm.eq)(import_postgres.tables.configTable.chainId, chainId)).limit(1).execute().then((rows) => rows.find(() => true));
|
134
|
-
const indexerBlockNumber = chainState?.blockNumber ?? 0n;
|
135
|
-
benchmark("query chainState");
|
136
|
-
const records = await database.select().from(import_postgres.tables.recordsTable).where((0, import_drizzle_orm.or)(...conditions)).orderBy(
|
137
|
-
(0, import_drizzle_orm.asc)(import_postgres.tables.recordsTable.blockNumber)
|
138
|
-
// TODO: add logIndex (https://github.com/latticexyz/mud/issues/1979)
|
139
|
-
);
|
140
|
-
benchmark("query records");
|
141
|
-
const blockNumber = records.reduce((max, record) => (0, import_utils.bigIntMax)(max, record.blockNumber ?? 0n), indexerBlockNumber);
|
142
|
-
benchmark("find block number");
|
143
|
-
const logs = records.filter((record) => !record.isDeleted).map(recordToLog);
|
144
|
-
benchmark("map records to logs");
|
145
|
-
return { blockNumber, logs };
|
146
|
-
}
|
147
|
-
|
148
|
-
// src/postgres/deprecated/createQueryAdapter.ts
|
149
|
-
var import_utils2 = require("@latticexyz/common/utils");
|
150
|
-
async function createQueryAdapter(database) {
|
151
|
-
const adapter = {
|
152
|
-
async getLogs(opts) {
|
153
|
-
return getLogs(database, opts);
|
154
|
-
},
|
155
|
-
async findAll(opts) {
|
156
|
-
const filters = opts.filters ?? [];
|
157
|
-
const { blockNumber, logs } = await getLogs(database, {
|
158
|
-
...opts,
|
159
|
-
// make sure we're always retrieving `store.Tables` table, so we can decode table values
|
160
|
-
filters: filters.length > 0 ? [...filters, { tableId: import_store_sync.schemasTable.tableId }] : []
|
161
|
-
});
|
162
|
-
const tables2 = logs.filter(import_store_sync.isTableRegistrationLog).map(import_store_sync.logToTable);
|
163
|
-
const logsByTable = (0, import_utils2.groupBy)(logs, (log) => `${(0, import_viem2.getAddress)(log.address)}:${log.args.tableId}`);
|
164
|
-
const tablesWithRecords = tables2.map((table) => {
|
165
|
-
const tableLogs = logsByTable.get(`${(0, import_viem2.getAddress)(table.address)}:${table.tableId}`) ?? [];
|
166
|
-
const records = tableLogs.map((log) => {
|
167
|
-
const key = (0, import_internal2.decodeKey)(table.keySchema, log.args.keyTuple);
|
168
|
-
const value = (0, import_internal2.decodeValueArgs)(table.valueSchema, log.args);
|
169
|
-
return { key, value, fields: { ...key, ...value } };
|
170
|
-
});
|
171
|
-
return {
|
172
|
-
...table,
|
173
|
-
records
|
174
|
-
};
|
175
|
-
});
|
176
|
-
debug("findAll: decoded %d logs across %d tables", logs.length, tables2.length);
|
177
|
-
return {
|
178
|
-
blockNumber,
|
179
|
-
tables: tablesWithRecords
|
180
|
-
};
|
181
|
-
}
|
182
|
-
};
|
183
|
-
return adapter;
|
184
|
-
}
|
185
|
-
|
186
|
-
// src/postgres/apiRoutes.ts
|
187
|
-
var import_router = __toESM(require("@koa/router"), 1);
|
188
|
-
var import_koa_compose = __toESM(require("koa-compose"), 1);
|
189
|
-
var import_indexer_client = require("@latticexyz/store-sync/indexer-client");
|
190
|
-
var import_store_sync2 = require("@latticexyz/store-sync");
|
191
|
-
|
192
|
-
// src/postgres/queryLogs.ts
|
193
|
-
var import_utils3 = require("@latticexyz/common/utils");
|
194
|
-
var import_viem3 = require("viem");
|
195
|
-
var import_postgres2 = require("@latticexyz/store-sync/postgres");
|
196
|
-
var schemaName = (0, import_postgres2.transformSchemaName)("mud");
|
197
|
-
function and2(sql, conditions) {
|
198
|
-
return sql`(${conditions.reduce((query, condition) => sql`${query} AND ${condition}`)})`;
|
199
|
-
}
|
200
|
-
function or2(sql, conditions) {
|
201
|
-
return sql`(${conditions.reduce((query, condition) => sql`${query} OR ${condition}`)})`;
|
202
|
-
}
|
203
|
-
function queryLogs(sql, opts) {
|
204
|
-
const conditions = opts.filters.length ? opts.filters.map(
|
205
|
-
(filter) => and2(
|
206
|
-
sql,
|
207
|
-
[
|
208
|
-
opts.address != null ? sql`address = ${(0, import_viem3.hexToBytes)(opts.address)}` : null,
|
209
|
-
sql`table_id = ${(0, import_viem3.hexToBytes)(filter.tableId)}`,
|
210
|
-
filter.key0 != null ? sql`key0 = ${(0, import_viem3.hexToBytes)(filter.key0)}` : null,
|
211
|
-
filter.key1 != null ? sql`key1 = ${(0, import_viem3.hexToBytes)(filter.key1)}` : null
|
212
|
-
].filter(import_utils3.isNotNull)
|
213
|
-
)
|
214
|
-
) : opts.address != null ? [sql`address = ${(0, import_viem3.hexToBytes)(opts.address)}`] : [];
|
215
|
-
const where = sql`WHERE ${and2(
|
216
|
-
sql,
|
217
|
-
[sql`is_deleted != true`, conditions.length ? or2(sql, conditions) : null].filter(import_utils3.isNotNull)
|
218
|
-
)}`;
|
219
|
-
return sql`
|
220
|
-
WITH
|
221
|
-
config AS (
|
222
|
-
SELECT
|
223
|
-
version AS "indexerVersion",
|
224
|
-
chain_id AS "chainId",
|
225
|
-
block_number AS "chainBlockNumber"
|
226
|
-
FROM ${sql(`${schemaName}.config`)}
|
227
|
-
LIMIT 1
|
228
|
-
),
|
229
|
-
records AS (
|
230
|
-
SELECT
|
231
|
-
'0x' || encode(address, 'hex') AS address,
|
232
|
-
'0x' || encode(table_id, 'hex') AS "tableId",
|
233
|
-
'0x' || encode(key_bytes, 'hex') AS "keyBytes",
|
234
|
-
'0x' || encode(static_data, 'hex') AS "staticData",
|
235
|
-
'0x' || encode(encoded_lengths, 'hex') AS "encodedLengths",
|
236
|
-
'0x' || encode(dynamic_data, 'hex') AS "dynamicData",
|
237
|
-
block_number AS "recordBlockNumber",
|
238
|
-
log_index AS "logIndex"
|
239
|
-
FROM ${sql(`${schemaName}.records`)}
|
240
|
-
${where}
|
241
|
-
ORDER BY block_number, log_index ASC
|
242
|
-
)
|
243
|
-
SELECT
|
244
|
-
(SELECT COUNT(*) FROM records) AS "totalRows",
|
245
|
-
*
|
246
|
-
FROM config, records
|
247
|
-
`;
|
248
|
-
}
|
249
|
-
|
250
|
-
// src/postgres/apiRoutes.ts
|
251
|
-
var import_common2 = require("@latticexyz/common");
|
252
|
-
|
253
|
-
// src/koa-middleware/compress.ts
|
254
|
-
var import_node_stream = require("stream");
|
255
|
-
var import_accepts = __toESM(require("accepts"), 1);
|
256
|
-
var import_node_zlib = require("zlib");
|
257
|
-
var import_utils4 = require("@latticexyz/common/utils");
|
258
|
-
var encodings = {
|
259
|
-
br: import_node_zlib.createBrotliCompress,
|
260
|
-
gzip: import_node_zlib.createGzip,
|
261
|
-
deflate: import_node_zlib.createDeflate
|
262
|
-
};
|
263
|
-
var encodingNames = Object.keys(encodings);
|
264
|
-
function flushEvery(stream, bytesThreshold) {
|
265
|
-
let bytesSinceFlush = 0;
|
266
|
-
stream.on("data", (data) => {
|
267
|
-
bytesSinceFlush += data.length;
|
268
|
-
if (bytesSinceFlush > bytesThreshold) {
|
269
|
-
bytesSinceFlush = 0;
|
270
|
-
stream.flush();
|
271
|
-
}
|
272
|
-
});
|
273
|
-
return stream;
|
274
|
-
}
|
275
|
-
function compress({ flushThreshold = 1024 * 4 } = {}) {
|
276
|
-
return async function compressMiddleware(ctx, next) {
|
277
|
-
ctx.vary("Accept-Encoding");
|
278
|
-
await next();
|
279
|
-
const encoding = (0, import_accepts.default)(ctx.req).encoding(encodingNames);
|
280
|
-
if (!(0, import_utils4.includes)(encodingNames, encoding)) return;
|
281
|
-
const compressed = flushEvery(encodings[encoding](), flushThreshold);
|
282
|
-
ctx.set("Content-Encoding", encoding);
|
283
|
-
ctx.body = ctx.body instanceof import_node_stream.Stream ? ctx.body.pipe(compressed) : compressed.end(ctx.body);
|
284
|
-
};
|
285
|
-
}
|
286
|
-
|
287
|
-
// src/postgres/apiRoutes.ts
|
288
|
-
function apiRoutes(database) {
|
289
|
-
const router = new import_router.default();
|
290
|
-
router.get("/api/logs", compress(), async (ctx) => {
|
291
|
-
const benchmark = (0, import_common2.createBenchmark)("postgres:logs");
|
292
|
-
let options;
|
293
|
-
try {
|
294
|
-
options = import_indexer_client.input.parse(typeof ctx.query.input === "string" ? JSON.parse(ctx.query.input) : {});
|
295
|
-
} catch (e) {
|
296
|
-
ctx.status = 400;
|
297
|
-
ctx.set("Content-Type", "application/json");
|
298
|
-
ctx.body = JSON.stringify(e);
|
299
|
-
debug(e);
|
300
|
-
return;
|
301
|
-
}
|
302
|
-
try {
|
303
|
-
options.filters = options.filters.length > 0 ? [...options.filters, { tableId: import_store_sync2.schemasTable.tableId }] : [];
|
304
|
-
const records = await queryLogs(database, options ?? {}).execute();
|
305
|
-
benchmark("query records");
|
306
|
-
const logs = records.map(recordToLog);
|
307
|
-
benchmark("map records to logs");
|
308
|
-
if (records.length === 0) {
|
309
|
-
ctx.status = 404;
|
310
|
-
ctx.body = "no logs found";
|
311
|
-
error(
|
312
|
-
`no logs found for chainId ${options.chainId}, address ${options.address}, filters ${JSON.stringify(
|
313
|
-
options.filters
|
314
|
-
)}`
|
315
|
-
);
|
316
|
-
return;
|
317
|
-
}
|
318
|
-
const blockNumber = records[0].chainBlockNumber;
|
319
|
-
ctx.status = 200;
|
320
|
-
const maxAgeSeconds = 60 * 5;
|
321
|
-
const staleWhileRevalidateSeconds = 4e3 * 2;
|
322
|
-
ctx.set(
|
323
|
-
"Cache-Control",
|
324
|
-
`public, max-age=${maxAgeSeconds}, stale-while-revalidate=${staleWhileRevalidateSeconds}`
|
325
|
-
);
|
326
|
-
ctx.set("Content-Type", "application/json");
|
327
|
-
ctx.body = JSON.stringify({ blockNumber, logs });
|
328
|
-
} catch (e) {
|
329
|
-
ctx.status = 500;
|
330
|
-
ctx.set("Content-Type", "application/json");
|
331
|
-
ctx.body = JSON.stringify(e);
|
332
|
-
error(e);
|
333
|
-
}
|
334
|
-
});
|
335
|
-
return (0, import_koa_compose.default)([router.routes(), router.allowedMethods()]);
|
336
|
-
}
|
337
|
-
|
338
|
-
// src/koa-middleware/sentry.ts
|
339
|
-
var Sentry = __toESM(require("@sentry/node"), 1);
|
340
|
-
var import_profiling_node = require("@sentry/profiling-node");
|
341
|
-
var import_utils5 = require("@sentry/utils");
|
342
|
-
var import_koa_compose2 = __toESM(require("koa-compose"), 1);
|
343
|
-
function errorHandler() {
|
344
|
-
return async function errorHandlerMiddleware(ctx, next) {
|
345
|
-
try {
|
346
|
-
await next();
|
347
|
-
} catch (err) {
|
348
|
-
Sentry.withScope((scope) => {
|
349
|
-
scope.addEventProcessor((event) => {
|
350
|
-
return Sentry.addRequestDataToEvent(event, ctx.request);
|
351
|
-
});
|
352
|
-
Sentry.captureException(err);
|
353
|
-
});
|
354
|
-
throw err;
|
355
|
-
}
|
356
|
-
};
|
357
|
-
}
|
358
|
-
function requestHandler() {
|
359
|
-
return async function requestHandlerMiddleware(ctx, next) {
|
360
|
-
await Sentry.runWithAsyncContext(async () => {
|
361
|
-
const hub = Sentry.getCurrentHub();
|
362
|
-
hub.configureScope(
|
363
|
-
(scope) => scope.addEventProcessor(
|
364
|
-
(event) => Sentry.addRequestDataToEvent(event, ctx.request, {
|
365
|
-
include: {
|
366
|
-
user: false
|
367
|
-
}
|
368
|
-
})
|
369
|
-
)
|
370
|
-
);
|
371
|
-
await next();
|
372
|
-
});
|
373
|
-
};
|
374
|
-
}
|
375
|
-
function tracing() {
|
376
|
-
return async function tracingMiddleware(ctx, next) {
|
377
|
-
const reqMethod = (ctx.method || "").toUpperCase();
|
378
|
-
const reqUrl = ctx.url && (0, import_utils5.stripUrlQueryAndFragment)(ctx.url);
|
379
|
-
let traceparentData;
|
380
|
-
if (ctx.request.get("sentry-trace")) {
|
381
|
-
traceparentData = Sentry.extractTraceparentData(ctx.request.get("sentry-trace"));
|
382
|
-
}
|
383
|
-
const transaction = Sentry.startTransaction({
|
384
|
-
name: `${reqMethod} ${reqUrl}`,
|
385
|
-
op: "http.server",
|
386
|
-
...traceparentData
|
387
|
-
});
|
388
|
-
ctx.__sentry_transaction = transaction;
|
389
|
-
Sentry.getCurrentHub().configureScope((scope) => {
|
390
|
-
scope.setSpan(transaction);
|
391
|
-
});
|
392
|
-
ctx.res.on("finish", () => {
|
393
|
-
setImmediate(() => {
|
394
|
-
if (ctx._matchedRoute) {
|
395
|
-
const mountPath = ctx.mountPath || "";
|
396
|
-
transaction.setName(`${reqMethod} ${mountPath}${ctx._matchedRoute}`);
|
397
|
-
}
|
398
|
-
transaction.setHttpStatus(ctx.status);
|
399
|
-
transaction.finish();
|
400
|
-
});
|
401
|
-
});
|
402
|
-
await next();
|
403
|
-
};
|
404
|
-
}
|
405
|
-
function sentry(dsn) {
|
406
|
-
debug("Initializing Sentry");
|
407
|
-
Sentry.init({
|
408
|
-
dsn,
|
409
|
-
integrations: [
|
410
|
-
// Automatically instrument Node.js libraries and frameworks
|
411
|
-
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
|
412
|
-
new import_profiling_node.ProfilingIntegration()
|
413
|
-
],
|
414
|
-
// Performance Monitoring
|
415
|
-
tracesSampleRate: 1,
|
416
|
-
// Set sampling rate for profiling - this is relative to tracesSampleRate
|
417
|
-
profilesSampleRate: 1
|
418
|
-
});
|
419
|
-
return (0, import_koa_compose2.default)([errorHandler(), requestHandler(), tracing()]);
|
420
|
-
}
|
421
|
-
|
422
|
-
// src/koa-middleware/healthcheck.ts
|
423
|
-
function healthcheck({ isHealthy, isReady } = {}) {
|
424
|
-
return async function healthcheckMiddleware(ctx, next) {
|
425
|
-
if (ctx.path === "/healthz") {
|
426
|
-
if (isHealthy == null || isHealthy()) {
|
427
|
-
ctx.status = 200;
|
428
|
-
ctx.body = "healthy";
|
429
|
-
} else {
|
430
|
-
ctx.status = 503;
|
431
|
-
ctx.body = "not healthy";
|
432
|
-
}
|
433
|
-
return;
|
434
|
-
}
|
435
|
-
if (ctx.path === "/readyz") {
|
436
|
-
if (isReady == null || isReady()) {
|
437
|
-
ctx.status = 200;
|
438
|
-
ctx.body = "ready";
|
439
|
-
} else {
|
440
|
-
ctx.status = 503;
|
441
|
-
ctx.body = "not ready";
|
442
|
-
}
|
443
|
-
return;
|
444
|
-
}
|
445
|
-
await next();
|
446
|
-
};
|
447
|
-
}
|
448
|
-
|
449
|
-
// src/koa-middleware/helloWorld.ts
|
450
|
-
function helloWorld() {
|
451
|
-
return async function helloWorldMiddleware(ctx, next) {
|
452
|
-
if (ctx.path === "/") {
|
453
|
-
ctx.status = 200;
|
454
|
-
ctx.body = "emit HelloWorld();";
|
455
|
-
return;
|
456
|
-
}
|
457
|
-
await next();
|
458
|
-
};
|
459
|
-
}
|
460
|
-
|
461
|
-
// src/koa-middleware/metrics.ts
|
462
|
-
var import_prom_client = __toESM(require("prom-client"), 1);
|
463
|
-
function metrics({
|
464
|
-
isHealthy,
|
465
|
-
isReady,
|
466
|
-
getLatestStoredBlockNumber,
|
467
|
-
getDistanceFromFollowBlock,
|
468
|
-
followBlockTag
|
469
|
-
} = {}) {
|
470
|
-
import_prom_client.default.collectDefaultMetrics();
|
471
|
-
if (isHealthy != null) {
|
472
|
-
new import_prom_client.default.Gauge({
|
473
|
-
name: "health_status",
|
474
|
-
help: "Health status (0 = unhealthy, 1 = healthy)",
|
475
|
-
collect() {
|
476
|
-
this.set(Number(isHealthy()));
|
477
|
-
}
|
478
|
-
});
|
479
|
-
}
|
480
|
-
if (isReady != null) {
|
481
|
-
new import_prom_client.default.Gauge({
|
482
|
-
name: "readiness_status",
|
483
|
-
help: "Readiness status (whether the service is ready to receive requests, 0 = not ready, 1 = ready)",
|
484
|
-
collect() {
|
485
|
-
this.set(Number(isReady()));
|
486
|
-
}
|
487
|
-
});
|
488
|
-
}
|
489
|
-
if (getLatestStoredBlockNumber != null) {
|
490
|
-
new import_prom_client.default.Gauge({
|
491
|
-
name: "latest_stored_block_number",
|
492
|
-
help: "Latest block number stored in the database",
|
493
|
-
async collect() {
|
494
|
-
this.set(Number(await getLatestStoredBlockNumber()));
|
495
|
-
}
|
496
|
-
});
|
497
|
-
}
|
498
|
-
if (followBlockTag != null) {
|
499
|
-
const blockTagGauge = new import_prom_client.default.Gauge({
|
500
|
-
name: "follow_block_tag",
|
501
|
-
help: "Block tag the indexer is following (0 = finalized, 1 = safe, 2 = latest)"
|
502
|
-
});
|
503
|
-
const blockTagToValue = {
|
504
|
-
finalized: 0,
|
505
|
-
safe: 1,
|
506
|
-
latest: 2
|
507
|
-
};
|
508
|
-
blockTagGauge.set(blockTagToValue[followBlockTag]);
|
509
|
-
}
|
510
|
-
if (getDistanceFromFollowBlock != null) {
|
511
|
-
new import_prom_client.default.Gauge({
|
512
|
-
name: "distance_from_follow_block",
|
513
|
-
help: "Block distance from the block tag this the indexer is following",
|
514
|
-
async collect() {
|
515
|
-
this.set(Number(await getDistanceFromFollowBlock()));
|
516
|
-
}
|
517
|
-
});
|
518
|
-
}
|
519
|
-
return async function metricsMiddleware(ctx, next) {
|
520
|
-
if (ctx.path === "/metrics") {
|
521
|
-
ctx.status = 200;
|
522
|
-
ctx.body = await import_prom_client.default.register.metrics();
|
523
|
-
return;
|
524
|
-
}
|
525
|
-
await next();
|
526
|
-
};
|
527
|
-
}
|
528
|
-
|
529
|
-
// src/bin/postgres-frontend.ts
|
530
|
-
(async () => {
|
531
|
-
const env = parseEnv(
|
532
|
-
import_zod2.z.intersection(
|
533
|
-
frontendEnvSchema,
|
534
|
-
import_zod2.z.object({
|
535
|
-
DATABASE_URL: import_zod2.z.string(),
|
536
|
-
SENTRY_DSN: import_zod2.z.string().optional()
|
537
|
-
})
|
538
|
-
)
|
539
|
-
);
|
540
|
-
const database = (0, import_postgres3.default)(env.DATABASE_URL, { prepare: false });
|
541
|
-
const server = new import_koa.default();
|
542
|
-
if (env.SENTRY_DSN) {
|
543
|
-
server.use(sentry(env.SENTRY_DSN));
|
544
|
-
}
|
545
|
-
server.use((0, import_cors.default)());
|
546
|
-
server.use(healthcheck());
|
547
|
-
server.use(
|
548
|
-
metrics({
|
549
|
-
isHealthy: () => true,
|
550
|
-
isReady: () => true
|
551
|
-
})
|
552
|
-
);
|
553
|
-
server.use(helloWorld());
|
554
|
-
server.use(apiRoutes(database));
|
555
|
-
server.use(
|
556
|
-
(0, import_trpc_koa_adapter.createKoaMiddleware)({
|
557
|
-
prefix: "/trpc",
|
558
|
-
router: (0, import_trpc_indexer.createAppRouter)(),
|
559
|
-
createContext: async () => ({
|
560
|
-
queryAdapter: await createQueryAdapter((0, import_postgres_js.drizzle)(database))
|
561
|
-
})
|
562
|
-
})
|
563
|
-
);
|
564
|
-
server.listen({ host: env.HOST, port: env.PORT });
|
565
|
-
console.log(`postgres indexer frontend listening on http://${env.HOST}:${env.PORT}`);
|
566
|
-
})();
|
567
|
-
//# sourceMappingURL=postgres-frontend.cjs.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":["../../src/bin/postgres-frontend.ts","../../src/bin/parseEnv.ts","../../src/postgres/deprecated/createQueryAdapter.ts","../../src/debug.ts","../../src/postgres/deprecated/getLogs.ts","../../src/postgres/recordToLog.ts","../../src/postgres/apiRoutes.ts","../../src/postgres/queryLogs.ts","../../src/koa-middleware/compress.ts","../../src/koa-middleware/sentry.ts","../../src/koa-middleware/healthcheck.ts","../../src/koa-middleware/helloWorld.ts","../../src/koa-middleware/metrics.ts"],"sourcesContent":["#!/usr/bin/env node\nimport \"dotenv/config\";\nimport { z } from \"zod\";\nimport Koa from \"koa\";\nimport cors from \"@koa/cors\";\nimport { createKoaMiddleware } from \"trpc-koa-adapter\";\nimport { createAppRouter } from \"@latticexyz/store-sync/trpc-indexer\";\nimport { drizzle } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport { frontendEnvSchema, parseEnv } from \"./parseEnv\";\nimport { createQueryAdapter } from \"../postgres/deprecated/createQueryAdapter\";\nimport { apiRoutes } from \"../postgres/apiRoutes\";\nimport { sentry } from \"../koa-middleware/sentry\";\nimport { healthcheck } from \"../koa-middleware/healthcheck\";\nimport { helloWorld } from \"../koa-middleware/helloWorld\";\nimport { metrics } from \"../koa-middleware/metrics\";\n\n// Workaround for:\n// Top-level await is currently not supported with the \"cjs\" output format\n(async (): Promise<void> => {\n const env = parseEnv(\n z.intersection(\n frontendEnvSchema,\n z.object({\n DATABASE_URL: z.string(),\n SENTRY_DSN: z.string().optional(),\n }),\n ),\n );\n\n const database = postgres(env.DATABASE_URL, { prepare: false });\n\n const server = new Koa();\n\n if (env.SENTRY_DSN) {\n server.use(sentry(env.SENTRY_DSN));\n }\n\n server.use(cors());\n server.use(healthcheck());\n server.use(\n metrics({\n isHealthy: () => true,\n isReady: () => true,\n }),\n );\n server.use(helloWorld());\n server.use(apiRoutes(database));\n\n server.use(\n createKoaMiddleware({\n prefix: \"/trpc\",\n router: createAppRouter(),\n createContext: async () => ({\n queryAdapter: await createQueryAdapter(drizzle(database)),\n }),\n }),\n );\n\n server.listen({ host: env.HOST, port: env.PORT });\n console.log(`postgres indexer frontend listening on http://${env.HOST}:${env.PORT}`);\n})();\n","import { Hex, isHex } from \"viem\";\nimport { z, ZodError, ZodTypeAny } from \"zod\";\n\nexport const frontendEnvSchema = z.object({\n HOST: z.string().default(\"0.0.0.0\"),\n PORT: z.coerce.number().positive().default(3001),\n});\n\nexport const indexerEnvSchema = z.intersection(\n z.object({\n FOLLOW_BLOCK_TAG: z.enum([\"latest\", \"safe\", \"finalized\"]).default(\"safe\"),\n START_BLOCK: z.coerce.bigint().nonnegative().default(0n),\n MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n),\n POLLING_INTERVAL: z.coerce.number().positive().default(1000),\n STORE_ADDRESS: z\n .string()\n .optional()\n .transform((input) => (input === \"\" ? undefined : input))\n .refine(isHexOrUndefined),\n INTERNAL__VALIDATE_BLOCK_RANGE: z\n .string()\n .optional()\n .transform((input) => input === \"true\" || input === \"1\"),\n }),\n z.union([\n z.object({\n RPC_HTTP_URL: z.string(),\n RPC_WS_URL: z.string().optional(),\n }),\n z.object({\n RPC_HTTP_URL: z.string().optional(),\n RPC_WS_URL: z.string(),\n }),\n ]),\n);\n\nexport function parseEnv<TSchema extends ZodTypeAny>(envSchema: TSchema): z.infer<TSchema> {\n try {\n return envSchema.parse(process.env);\n } catch (error) {\n if (error instanceof ZodError) {\n const { ...invalidEnvVars } = error.format();\n console.error(`\\nMissing or invalid environment variables:\\n\\n ${Object.keys(invalidEnvVars).join(\"\\n \")}\\n`);\n process.exit(1);\n }\n throw error;\n }\n}\n\nfunction isHexOrUndefined(input: unknown): input is Hex | undefined {\n return input === undefined || isHex(input);\n}\n","import { getAddress } from \"viem\";\nimport { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { TableWithRecords, isTableRegistrationLog, logToTable, schemasTable } from \"@latticexyz/store-sync\";\nimport { KeySchema, decodeKey, decodeValueArgs } from \"@latticexyz/protocol-parser/internal\";\nimport { QueryAdapter } from \"@latticexyz/store-sync/trpc-indexer\";\nimport { debug } from \"../../debug\";\nimport { getLogs } from \"./getLogs\";\nimport { groupBy } from \"@latticexyz/common/utils\";\n\n/**\n * Creates a query adapter for the tRPC server/client to query data from Postgres.\n *\n * @param {PgDatabase<any>} database Postgres database object from Drizzle\n * @returns {Promise<QueryAdapter>} A set of methods used by tRPC endpoints.\n * @deprecated\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function createQueryAdapter(database: PgDatabase<any>): Promise<QueryAdapter> {\n const adapter: QueryAdapter = {\n async getLogs(opts) {\n return getLogs(database, opts);\n },\n async findAll(opts) {\n const filters = opts.filters ?? [];\n const { blockNumber, logs } = await getLogs(database, {\n ...opts,\n // make sure we're always retrieving `store.Tables` table, so we can decode table values\n filters: filters.length > 0 ? [...filters, { tableId: schemasTable.tableId }] : [],\n });\n\n const tables = logs.filter(isTableRegistrationLog).map(logToTable);\n\n const logsByTable = groupBy(logs, (log) => `${getAddress(log.address)}:${log.args.tableId}`);\n\n const tablesWithRecords: readonly TableWithRecords[] = tables.map((table) => {\n const tableLogs = logsByTable.get(`${getAddress(table.address)}:${table.tableId}`) ?? [];\n const records = tableLogs.map((log) => {\n const key = decodeKey(table.keySchema as KeySchema, log.args.keyTuple);\n const value = decodeValueArgs(table.valueSchema, log.args);\n return { key, value, fields: { ...key, ...value } };\n });\n\n return {\n ...table,\n records,\n };\n });\n\n debug(\"findAll: decoded %d logs across %d tables\", logs.length, tables.length);\n\n return {\n blockNumber,\n tables: tablesWithRecords,\n };\n },\n };\n return adapter;\n}\n","import createDebug from \"debug\";\n\nexport const debug = createDebug(\"mud:store-indexer\");\nexport const error = createDebug(\"mud:store-indexer\");\n\n// Pipe debug output to stdout instead of stderr\ndebug.log = console.debug.bind(console);\n\n// Pipe error output to stderr\nerror.log = console.error.bind(console);\n","import { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { Hex } from \"viem\";\nimport { StorageAdapterLog, SyncFilter } from \"@latticexyz/store-sync\";\nimport { tables } from \"@latticexyz/store-sync/postgres\";\nimport { and, asc, eq, or } from \"drizzle-orm\";\nimport { bigIntMax } from \"@latticexyz/common/utils\";\nimport { recordToLog } from \"../recordToLog\";\nimport { createBenchmark } from \"@latticexyz/common\";\n\n/**\n * @deprecated\n */\nexport async function getLogs(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n database: PgDatabase<any>,\n {\n chainId,\n address,\n filters = [],\n }: {\n readonly chainId: number;\n readonly address?: Hex;\n readonly filters?: readonly SyncFilter[];\n },\n): Promise<{ blockNumber: bigint; logs: Extract<StorageAdapterLog, { eventName: \"Store_SetRecord\" }>[] }> {\n const benchmark = createBenchmark(\"drizzleGetLogs\");\n\n const conditions = filters.length\n ? filters.map((filter) =>\n and(\n address != null ? eq(tables.recordsTable.address, address) : undefined,\n eq(tables.recordsTable.tableId, filter.tableId),\n filter.key0 != null ? eq(tables.recordsTable.key0, filter.key0) : undefined,\n filter.key1 != null ? eq(tables.recordsTable.key1, filter.key1) : undefined,\n ),\n )\n : address != null\n ? [eq(tables.recordsTable.address, address)]\n : [];\n benchmark(\"parse config\");\n\n // Query for the block number that the indexer (i.e. chain) is at, in case the\n // indexer is further along in the chain than a given store/table's last updated\n // block number. We'll then take the highest block number between the indexer's\n // chain state and all the records in the query (in case the records updated\n // between these queries). Using just the highest block number from the queries\n // could potentially signal to the client an older-than-necessary block number,\n // for stores/tables that haven't seen recent activity.\n // TODO: move the block number query into the records query for atomicity so we don't have to merge them here\n const chainState = await database\n .select()\n .from(tables.configTable)\n .where(eq(tables.configTable.chainId, chainId))\n .limit(1)\n .execute()\n // Get the first record in a way that returns a possible `undefined`\n // TODO: move this to `.findFirst` after upgrading drizzle or `rows[0]` after enabling `noUncheckedIndexedAccess: true`\n .then((rows) => rows.find(() => true));\n const indexerBlockNumber = chainState?.blockNumber ?? 0n;\n benchmark(\"query chainState\");\n\n const records = await database\n .select()\n .from(tables.recordsTable)\n .where(or(...conditions))\n .orderBy(\n asc(tables.recordsTable.blockNumber),\n // TODO: add logIndex (https://github.com/latticexyz/mud/issues/1979)\n );\n benchmark(\"query records\");\n\n const blockNumber = records.reduce((max, record) => bigIntMax(max, record.blockNumber ?? 0n), indexerBlockNumber);\n benchmark(\"find block number\");\n\n const logs = records\n // TODO: add this to the query, assuming we can optimize with an index\n .filter((record) => !record.isDeleted)\n .map(recordToLog);\n benchmark(\"map records to logs\");\n\n return { blockNumber, logs };\n}\n","import { StorageAdapterLog } from \"@latticexyz/store-sync\";\nimport { decodeDynamicField } from \"@latticexyz/protocol-parser/internal\";\nimport { RecordData } from \"./common\";\n\nexport function recordToLog(\n record: Omit<RecordData, \"recordBlockNumber\">,\n): Extract<StorageAdapterLog, { eventName: \"Store_SetRecord\" }> {\n return {\n address: record.address,\n eventName: \"Store_SetRecord\",\n args: {\n tableId: record.tableId,\n keyTuple: decodeDynamicField(\"bytes32[]\", record.keyBytes),\n staticData: record.staticData ?? \"0x\",\n encodedLengths: record.encodedLengths ?? \"0x\",\n dynamicData: record.dynamicData ?? \"0x\",\n },\n } as const;\n}\n","import { Sql } from \"postgres\";\nimport { Middleware } from \"koa\";\nimport Router from \"@koa/router\";\nimport compose from \"koa-compose\";\nimport { input } from \"@latticexyz/store-sync/indexer-client\";\nimport { schemasTable } from \"@latticexyz/store-sync\";\nimport { queryLogs } from \"./queryLogs\";\nimport { recordToLog } from \"./recordToLog\";\nimport { debug, error } from \"../debug\";\nimport { createBenchmark } from \"@latticexyz/common\";\nimport { compress } from \"../koa-middleware/compress\";\n\nexport function apiRoutes(database: Sql): Middleware {\n const router = new Router();\n\n router.get(\"/api/logs\", compress(), async (ctx) => {\n const benchmark = createBenchmark(\"postgres:logs\");\n let options: ReturnType<typeof input.parse>;\n\n try {\n options = input.parse(typeof ctx.query.input === \"string\" ? JSON.parse(ctx.query.input) : {});\n } catch (e) {\n ctx.status = 400;\n ctx.set(\"Content-Type\", \"application/json\");\n ctx.body = JSON.stringify(e);\n debug(e);\n return;\n }\n\n try {\n options.filters = options.filters.length > 0 ? [...options.filters, { tableId: schemasTable.tableId }] : [];\n const records = await queryLogs(database, options ?? {}).execute();\n benchmark(\"query records\");\n const logs = records.map(recordToLog);\n benchmark(\"map records to logs\");\n\n // Ideally we would immediately return an error if the request is for a Store that the indexer\n // is not configured to index. Since we don't have easy access to this information here,\n // we return an error if there are no logs found for a given Store, since that would never\n // be the case for a Store that is being indexed (since there would at least be records for the\n // Tables table with tables created during Store initialization).\n if (records.length === 0) {\n ctx.status = 404;\n ctx.body = \"no logs found\";\n error(\n `no logs found for chainId ${options.chainId}, address ${options.address}, filters ${JSON.stringify(\n options.filters,\n )}`,\n );\n return;\n }\n\n const blockNumber = records[0].chainBlockNumber;\n ctx.status = 200;\n\n // max age is set to several multiples of the uncached response time (currently ~10s, but using 60s for wiggle room) to ensure only ~one origin request at a time\n // and stale-while-revalidate below means that the cache is refreshed under the hood while still responding fast (cached)\n const maxAgeSeconds = 60 * 5;\n // we set stale-while-revalidate to the time elapsed by the number of blocks we can fetch from the RPC in the same amount of time as an uncached response\n // meaning it would take ~the same about of time to get an uncached response from the origin as it would to catch up from the currently cached response\n // if an uncached response takes ~10 seconds, we have ~10s to catch up, so let's say we can do enough RPC calls to fetch 4000 blocks\n // with a block per 2 seconds, that means we can serve a stale/cached response for 8000 seconds before we should require the response be returned by the origin\n const staleWhileRevalidateSeconds = 4000 * 2;\n\n ctx.set(\n \"Cache-Control\",\n `public, max-age=${maxAgeSeconds}, stale-while-revalidate=${staleWhileRevalidateSeconds}`,\n );\n\n ctx.set(\"Content-Type\", \"application/json\");\n ctx.body = JSON.stringify({ blockNumber, logs });\n } catch (e) {\n ctx.status = 500;\n ctx.set(\"Content-Type\", \"application/json\");\n ctx.body = JSON.stringify(e);\n error(e);\n }\n });\n\n return compose([router.routes(), router.allowedMethods()]) as Middleware;\n}\n","import { isNotNull } from \"@latticexyz/common/utils\";\nimport { PendingQuery, Row, Sql } from \"postgres\";\nimport { hexToBytes } from \"viem\";\nimport { z } from \"zod\";\nimport { input } from \"@latticexyz/store-sync/indexer-client\";\nimport { transformSchemaName } from \"@latticexyz/store-sync/postgres\";\nimport { Record } from \"./common\";\n\nconst schemaName = transformSchemaName(\"mud\");\n\nfunction and(sql: Sql, conditions: PendingQuery<Row[]>[]): PendingQuery<Row[]> {\n return sql`(${conditions.reduce((query, condition) => sql`${query} AND ${condition}`)})`;\n}\n\nfunction or(sql: Sql, conditions: PendingQuery<Row[]>[]): PendingQuery<Row[]> {\n return sql`(${conditions.reduce((query, condition) => sql`${query} OR ${condition}`)})`;\n}\n\nexport function queryLogs(sql: Sql, opts: z.infer<typeof input>): PendingQuery<Record[]> {\n const conditions = opts.filters.length\n ? opts.filters.map((filter) =>\n and(\n sql,\n [\n opts.address != null ? sql`address = ${hexToBytes(opts.address)}` : null,\n sql`table_id = ${hexToBytes(filter.tableId)}`,\n filter.key0 != null ? sql`key0 = ${hexToBytes(filter.key0)}` : null,\n filter.key1 != null ? sql`key1 = ${hexToBytes(filter.key1)}` : null,\n ].filter(isNotNull),\n ),\n )\n : opts.address != null\n ? [sql`address = ${hexToBytes(opts.address)}`]\n : [];\n\n const where = sql`WHERE ${and(\n sql,\n [sql`is_deleted != true`, conditions.length ? or(sql, conditions) : null].filter(isNotNull),\n )}`;\n\n // TODO: implement bytea <> hex columns via custom types: https://github.com/porsager/postgres#custom-types\n return sql<Record[]>`\n WITH\n config AS (\n SELECT\n version AS \"indexerVersion\",\n chain_id AS \"chainId\",\n block_number AS \"chainBlockNumber\"\n FROM ${sql(`${schemaName}.config`)}\n LIMIT 1\n ),\n records AS (\n SELECT\n '0x' || encode(address, 'hex') AS address,\n '0x' || encode(table_id, 'hex') AS \"tableId\",\n '0x' || encode(key_bytes, 'hex') AS \"keyBytes\",\n '0x' || encode(static_data, 'hex') AS \"staticData\",\n '0x' || encode(encoded_lengths, 'hex') AS \"encodedLengths\",\n '0x' || encode(dynamic_data, 'hex') AS \"dynamicData\",\n block_number AS \"recordBlockNumber\",\n log_index AS \"logIndex\"\n FROM ${sql(`${schemaName}.records`)}\n ${where}\n ORDER BY block_number, log_index ASC\n )\n SELECT\n (SELECT COUNT(*) FROM records) AS \"totalRows\",\n *\n FROM config, records\n `;\n}\n","import { Middleware } from \"koa\";\nimport { Readable, Stream } from \"node:stream\";\nimport accepts from \"accepts\";\nimport { Zlib, createBrotliCompress, createDeflate, createGzip } from \"node:zlib\";\nimport { includes } from \"@latticexyz/common/utils\";\n\n// Loosely based on https://github.com/holic/koa-compress/blob/master/lib/index.js\n// with better handling of streams better with occasional flushing\n\nconst encodings = {\n br: createBrotliCompress,\n gzip: createGzip,\n deflate: createDeflate,\n} as const;\n\nconst encodingNames = Object.keys(encodings) as (keyof typeof encodings)[];\n\nfunction flushEvery<stream extends Zlib & Readable>(stream: stream, bytesThreshold: number): stream {\n let bytesSinceFlush = 0;\n stream.on(\"data\", (data) => {\n bytesSinceFlush += data.length;\n if (bytesSinceFlush > bytesThreshold) {\n bytesSinceFlush = 0;\n stream.flush();\n }\n });\n return stream;\n}\n\ntype CompressOptions = {\n flushThreshold?: number;\n};\n\nexport function compress({ flushThreshold = 1024 * 4 }: CompressOptions = {}): Middleware {\n return async function compressMiddleware(ctx, next) {\n ctx.vary(\"Accept-Encoding\");\n\n await next();\n\n const encoding = accepts(ctx.req).encoding(encodingNames);\n if (!includes(encodingNames, encoding)) return;\n\n const compressed = flushEvery(encodings[encoding](), flushThreshold);\n\n ctx.set(\"Content-Encoding\", encoding);\n ctx.body = ctx.body instanceof Stream ? ctx.body.pipe(compressed) : compressed.end(ctx.body);\n };\n}\n","import * as Sentry from \"@sentry/node\";\nimport { ProfilingIntegration } from \"@sentry/profiling-node\";\nimport { stripUrlQueryAndFragment } from \"@sentry/utils\";\nimport { debug } from \"../debug\";\nimport Koa from \"koa\";\nimport compose from \"koa-compose\";\n\nexport function errorHandler(): Koa.Middleware {\n return async function errorHandlerMiddleware(ctx, next) {\n try {\n await next();\n } catch (err) {\n Sentry.withScope((scope) => {\n scope.addEventProcessor((event) => {\n return Sentry.addRequestDataToEvent(event, ctx.request);\n });\n Sentry.captureException(err);\n });\n throw err;\n }\n };\n}\n\nexport function requestHandler(): Koa.Middleware {\n return async function requestHandlerMiddleware(ctx, next) {\n await Sentry.runWithAsyncContext(async () => {\n const hub = Sentry.getCurrentHub();\n hub.configureScope((scope) =>\n scope.addEventProcessor((event) =>\n Sentry.addRequestDataToEvent(event, ctx.request, {\n include: {\n user: false,\n },\n }),\n ),\n );\n await next();\n });\n };\n}\n\nexport function tracing(): Koa.Middleware {\n // creates a Sentry transaction per request\n return async function tracingMiddleware(ctx, next) {\n const reqMethod = (ctx.method || \"\").toUpperCase();\n const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url);\n\n // Connect to trace of upstream app\n let traceparentData;\n if (ctx.request.get(\"sentry-trace\")) {\n traceparentData = Sentry.extractTraceparentData(ctx.request.get(\"sentry-trace\"));\n }\n\n const transaction = Sentry.startTransaction({\n name: `${reqMethod} ${reqUrl}`,\n op: \"http.server\",\n ...traceparentData,\n });\n\n ctx.__sentry_transaction = transaction;\n\n // We put the transaction on the scope so users can attach children to it\n Sentry.getCurrentHub().configureScope((scope) => {\n scope.setSpan(transaction);\n });\n\n ctx.res.on(\"finish\", () => {\n // Push `transaction.finish` to the next event loop so open spans have a chance to finish before the transaction closes\n setImmediate(() => {\n // If you're using koa router, set the matched route as transaction name\n if (ctx._matchedRoute) {\n const mountPath = ctx.mountPath || \"\";\n transaction.setName(`${reqMethod} ${mountPath}${ctx._matchedRoute}`);\n }\n\n transaction.setHttpStatus(ctx.status);\n transaction.finish();\n });\n });\n\n await next();\n };\n}\n\nexport function sentry(dsn: string): Koa.Middleware {\n debug(\"Initializing Sentry\");\n Sentry.init({\n dsn,\n integrations: [\n // Automatically instrument Node.js libraries and frameworks\n ...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),\n new ProfilingIntegration(),\n ],\n // Performance Monitoring\n tracesSampleRate: 1.0,\n // Set sampling rate for profiling - this is relative to tracesSampleRate\n profilesSampleRate: 1.0,\n });\n\n return compose([errorHandler(), requestHandler(), tracing()]);\n}\n","import { Middleware } from \"koa\";\n\ntype HealthcheckOptions = {\n isHealthy?: () => boolean;\n isReady?: () => boolean;\n};\n\n/**\n * Middleware to add Kubernetes healthcheck endpoints\n */\nexport function healthcheck({ isHealthy, isReady }: HealthcheckOptions = {}): Middleware {\n return async function healthcheckMiddleware(ctx, next): Promise<void> {\n if (ctx.path === \"/healthz\") {\n if (isHealthy == null || isHealthy()) {\n ctx.status = 200;\n ctx.body = \"healthy\";\n } else {\n ctx.status = 503;\n ctx.body = \"not healthy\";\n }\n return;\n }\n\n if (ctx.path === \"/readyz\") {\n if (isReady == null || isReady()) {\n ctx.status = 200;\n ctx.body = \"ready\";\n } else {\n ctx.status = 503;\n ctx.body = \"not ready\";\n }\n return;\n }\n\n await next();\n };\n}\n","import { Middleware } from \"koa\";\n\nexport function helloWorld(): Middleware {\n return async function helloWorldMiddleware(ctx, next): Promise<void> {\n if (ctx.path === \"/\") {\n ctx.status = 200;\n ctx.body = \"emit HelloWorld();\";\n return;\n }\n await next();\n };\n}\n","import { Middleware } from \"koa\";\nimport promClient from \"prom-client\";\n\ntype MetricsOptions = {\n isHealthy?: () => boolean;\n isReady?: () => boolean;\n getLatestStoredBlockNumber?: () => Promise<bigint | undefined>;\n getDistanceFromFollowBlock?: () => Promise<bigint>;\n followBlockTag?: \"latest\" | \"safe\" | \"finalized\";\n};\n\n/**\n * Middleware to add Prometheus metrics endpoints\n */\nexport function metrics({\n isHealthy,\n isReady,\n getLatestStoredBlockNumber,\n getDistanceFromFollowBlock,\n followBlockTag,\n}: MetricsOptions = {}): Middleware {\n promClient.collectDefaultMetrics();\n if (isHealthy != null) {\n new promClient.Gauge({\n name: \"health_status\",\n help: \"Health status (0 = unhealthy, 1 = healthy)\",\n collect(): void {\n this.set(Number(isHealthy()));\n },\n });\n }\n\n if (isReady != null) {\n new promClient.Gauge({\n name: \"readiness_status\",\n help: \"Readiness status (whether the service is ready to receive requests, 0 = not ready, 1 = ready)\",\n collect(): void {\n this.set(Number(isReady()));\n },\n });\n }\n\n if (getLatestStoredBlockNumber != null) {\n new promClient.Gauge({\n name: \"latest_stored_block_number\",\n help: \"Latest block number stored in the database\",\n async collect(): Promise<void> {\n this.set(Number(await getLatestStoredBlockNumber()));\n },\n });\n }\n\n if (followBlockTag != null) {\n const blockTagGauge = new promClient.Gauge({\n name: \"follow_block_tag\",\n help: \"Block tag the indexer is following (0 = finalized, 1 = safe, 2 = latest)\",\n });\n const blockTagToValue = {\n finalized: 0,\n safe: 1,\n latest: 2,\n };\n blockTagGauge.set(blockTagToValue[followBlockTag]);\n }\n\n if (getDistanceFromFollowBlock != null) {\n new promClient.Gauge({\n name: \"distance_from_follow_block\",\n help: \"Block distance from the block tag this the indexer is following\",\n async collect(): Promise<void> {\n this.set(Number(await getDistanceFromFollowBlock()));\n },\n });\n }\n\n return async function metricsMiddleware(ctx, next): Promise<void> {\n if (ctx.path === \"/metrics\") {\n ctx.status = 200;\n ctx.body = await promClient.register.metrics();\n return;\n }\n\n await next();\n };\n}\n"],"mappings":"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","names":["import_zod","import_postgres","input","error","import_viem","import_internal","createDebug","import_utils","tables","import_store_sync","import_utils","import_viem","import_postgres","and","or","import_common","import_utils","accepts","Router","compose","import_utils","import_koa_compose","compose","promClient","postgres","Koa","cors"]}
|
@@ -1 +0,0 @@
|
|
1
|
-
#!/usr/bin/env node
|