@secondlayer/shared 0.7.0 → 0.8.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/dist/src/crypto/hmac.js +2 -2
- package/dist/src/crypto/hmac.js.map +3 -3
- package/dist/src/db/index.d.ts +18 -3
- package/dist/src/db/index.js +6 -2
- package/dist/src/db/index.js.map +4 -4
- package/dist/src/db/jsonb.js.map +2 -2
- package/dist/src/db/queries/accounts.d.ts +16 -3
- package/dist/src/db/queries/accounts.js +6 -3
- package/dist/src/db/queries/accounts.js.map +3 -3
- package/dist/src/db/queries/integrity.d.ts +15 -2
- package/dist/src/db/queries/integrity.js.map +2 -2
- package/dist/src/db/queries/metrics.d.ts +15 -2
- package/dist/src/db/queries/metrics.js.map +2 -2
- package/dist/src/db/queries/subgraph-gaps.d.ts +305 -0
- package/dist/src/db/queries/subgraph-gaps.js +103 -0
- package/dist/src/db/queries/subgraph-gaps.js.map +10 -0
- package/dist/src/db/queries/subgraphs.d.ts +15 -2
- package/dist/src/db/queries/subgraphs.js +2 -2
- package/dist/src/db/queries/subgraphs.js.map +4 -4
- package/dist/src/db/queries/usage.d.ts +23 -3
- package/dist/src/db/queries/usage.js +35 -3
- package/dist/src/db/queries/usage.js.map +4 -4
- package/dist/src/db/schema.d.ts +18 -3
- package/dist/src/env.js.map +2 -2
- package/dist/src/errors.d.ts +17 -4
- package/dist/src/errors.js +14 -2
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +78 -6
- package/dist/src/index.js +26 -8
- package/dist/src/index.js.map +12 -12
- package/dist/src/lib/plans.js.map +2 -2
- package/dist/src/logger.js.map +3 -3
- package/dist/src/node/archive-client.js +22 -6
- package/dist/src/node/archive-client.js.map +5 -5
- package/dist/src/node/client.js.map +2 -2
- package/dist/src/node/hiro-client.js +47 -11
- package/dist/src/node/hiro-client.js.map +5 -5
- package/dist/src/node/hiro-pg-client.js +131 -26
- package/dist/src/node/hiro-pg-client.js.map +3 -3
- package/dist/src/node/local-client.d.ts +15 -2
- package/dist/src/node/local-client.js.map +2 -2
- package/dist/src/queue/index.js +8 -4
- package/dist/src/queue/index.js.map +5 -5
- package/dist/src/queue/listener.js.map +2 -2
- package/dist/src/queue/recovery.js +6 -2
- package/dist/src/queue/recovery.js.map +5 -5
- package/dist/src/schemas/filters.js +2 -2
- package/dist/src/schemas/filters.js.map +3 -3
- package/dist/src/schemas/index.d.ts +45 -1
- package/dist/src/schemas/index.js +5 -3
- package/dist/src/schemas/index.js.map +5 -5
- package/dist/src/schemas/subgraphs.d.ts +45 -1
- package/dist/src/schemas/subgraphs.js.map +2 -2
- package/dist/src/types.d.ts +1 -1
- package/migrations/0001_initial.ts +295 -159
- package/migrations/0002_api_keys.ts +44 -28
- package/migrations/0003_tenant_isolation.ts +116 -107
- package/migrations/0004_accounts_and_usage.ts +81 -75
- package/migrations/0005_sessions.ts +33 -33
- package/migrations/0006_tx_index.ts +6 -2
- package/migrations/0007_contracts.ts +38 -24
- package/migrations/0008_drop_contracts.ts +33 -19
- package/migrations/0009_waitlist.ts +12 -12
- package/migrations/0010_waitlist_status.ts +5 -5
- package/migrations/0011_account_insights.ts +52 -52
- package/migrations/0012_view_health_snapshots.ts +21 -21
- package/migrations/0013_view_processing_stats.ts +32 -32
- package/migrations/0014_view_table_snapshots.ts +24 -24
- package/migrations/0015_rename_views_to_subgraphs.ts +137 -75
- package/migrations/0016_rename_webhook_to_endpoint.ts +12 -4
- package/migrations/0017_security_hardening.ts +32 -0
- package/migrations/0018_subgraph_gaps.ts +39 -0
- package/package.json +147 -143
|
@@ -34,13 +34,23 @@ function getPlanLimits(plan) {
|
|
|
34
34
|
import { sql } from "kysely";
|
|
35
35
|
async function incrementApiRequests(db, accountId) {
|
|
36
36
|
const today = new Date().toISOString().slice(0, 10);
|
|
37
|
-
await db.insertInto("usage_daily").values({
|
|
37
|
+
await db.insertInto("usage_daily").values({
|
|
38
|
+
account_id: accountId,
|
|
39
|
+
date: today,
|
|
40
|
+
api_requests: 1,
|
|
41
|
+
deliveries: 0
|
|
42
|
+
}).onConflict((oc) => oc.columns(["account_id", "date"]).doUpdateSet({
|
|
38
43
|
api_requests: sql`usage_daily.api_requests + 1`
|
|
39
44
|
})).execute();
|
|
40
45
|
}
|
|
41
46
|
async function incrementDeliveries(db, accountId, count = 1) {
|
|
42
47
|
const today = new Date().toISOString().slice(0, 10);
|
|
43
|
-
await db.insertInto("usage_daily").values({
|
|
48
|
+
await db.insertInto("usage_daily").values({
|
|
49
|
+
account_id: accountId,
|
|
50
|
+
date: today,
|
|
51
|
+
api_requests: 0,
|
|
52
|
+
deliveries: count
|
|
53
|
+
}).onConflict((oc) => oc.columns(["account_id", "date"]).doUpdateSet({
|
|
44
54
|
deliveries: sql`usage_daily.deliveries + ${count}`
|
|
45
55
|
})).execute();
|
|
46
56
|
}
|
|
@@ -56,6 +66,27 @@ async function getUsage(db, accountId) {
|
|
|
56
66
|
storageBytes: Number(storageRow?.storage_bytes ?? 0)
|
|
57
67
|
};
|
|
58
68
|
}
|
|
69
|
+
async function getDailyUsage(db, accountId) {
|
|
70
|
+
const rows = await db.selectFrom("usage_daily").select(["date", "api_requests", "deliveries"]).where("account_id", "=", accountId).where("date", ">=", sql`NOW()::date - 6`).orderBy("date", "asc").execute();
|
|
71
|
+
const byDate = new Map(rows.map((r) => {
|
|
72
|
+
const d = r.date;
|
|
73
|
+
const key = d instanceof Date ? d.toISOString().slice(0, 10) : String(d).slice(0, 10);
|
|
74
|
+
return [key, r];
|
|
75
|
+
}));
|
|
76
|
+
const result = [];
|
|
77
|
+
for (let i = 6;i >= 0; i--) {
|
|
78
|
+
const d = new Date;
|
|
79
|
+
d.setDate(d.getDate() - i);
|
|
80
|
+
const dateStr = d.toISOString().slice(0, 10);
|
|
81
|
+
const row = byDate.get(dateStr);
|
|
82
|
+
result.push({
|
|
83
|
+
date: dateStr,
|
|
84
|
+
apiRequests: row?.api_requests ?? 0,
|
|
85
|
+
deliveries: row?.deliveries ?? 0
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
59
90
|
async function checkLimits(db, accountId, plan) {
|
|
60
91
|
const limits = getPlanLimits(plan);
|
|
61
92
|
const usage = await getUsage(db, accountId);
|
|
@@ -114,8 +145,9 @@ export {
|
|
|
114
145
|
incrementDeliveries,
|
|
115
146
|
incrementApiRequests,
|
|
116
147
|
getUsage,
|
|
148
|
+
getDailyUsage,
|
|
117
149
|
checkLimits
|
|
118
150
|
};
|
|
119
151
|
|
|
120
|
-
//# debugId=
|
|
152
|
+
//# debugId=C9AA7973D9E596F264756E2164756E21
|
|
121
153
|
//# sourceMappingURL=usage.js.map
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/lib/plans.ts", "../src/db/queries/usage.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export interface PlanLimits {\n
|
|
6
|
-
"import {
|
|
5
|
+
"export interface PlanLimits {\n\tstreams: number;\n\tsubgraphs: number;\n\tapiRequestsPerDay: number;\n\tdeliveriesPerMonth: number;\n\tstorageBytes: number;\n}\n\nexport const FREE_PLAN: PlanLimits = {\n\tstreams: 3,\n\tsubgraphs: 2,\n\tapiRequestsPerDay: 1_000,\n\tdeliveriesPerMonth: 5_000,\n\tstorageBytes: 100 * 1024 * 1024, // 100MB\n};\n\nexport function getPlanLimits(plan: string): PlanLimits {\n\tswitch (plan) {\n\t\tcase \"free\":\n\t\tdefault:\n\t\t\treturn FREE_PLAN;\n\t}\n}\n",
|
|
6
|
+
"import { type Kysely, sql } from \"kysely\";\nimport { getPlanLimits } from \"../../lib/plans.ts\";\nimport type { Database } from \"../types.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait db\n\t\t.insertInto(\"usage_daily\")\n\t\t.values({\n\t\t\taccount_id: accountId,\n\t\t\tdate: today,\n\t\t\tapi_requests: 1,\n\t\t\tdeliveries: 0,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"account_id\", \"date\"]).doUpdateSet({\n\t\t\t\tapi_requests: sql`usage_daily.api_requests + 1`,\n\t\t\t}),\n\t\t)\n\t\t.execute();\n}\n\n/** Increment delivery counter for today. */\nexport async function incrementDeliveries(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tcount = 1,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait db\n\t\t.insertInto(\"usage_daily\")\n\t\t.values({\n\t\t\taccount_id: accountId,\n\t\t\tdate: today,\n\t\t\tapi_requests: 0,\n\t\t\tdeliveries: count,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"account_id\", \"date\"]).doUpdateSet({\n\t\t\t\tdeliveries: sql`usage_daily.deliveries + ${count}`,\n\t\t\t}),\n\t\t)\n\t\t.execute();\n}\n\nexport interface UsageSummary {\n\tapiRequestsToday: number;\n\tdeliveriesThisMonth: number;\n\tstorageBytes: number;\n}\n\n/** Get current usage for an account. */\nexport async function getUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<UsageSummary> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tconst monthStart = today.slice(0, 7) + \"-01\"; // YYYY-MM-01\n\n\t// Today's API requests\n\tconst dailyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(\"api_requests\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \"=\", today)\n\t\t.executeTakeFirst();\n\n\t// This month's deliveries\n\tconst monthlyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(deliveries), 0)`.as(\"total\"))\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", monthStart)\n\t\t.executeTakeFirst();\n\n\t// Latest storage snapshot\n\tconst storageRow = await db\n\t\t.selectFrom(\"usage_snapshots\")\n\t\t.select(\"storage_bytes\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"measured_at\", \"desc\")\n\t\t.limit(1)\n\t\t.executeTakeFirst();\n\n\treturn {\n\t\tapiRequestsToday: dailyRow?.api_requests ?? 0,\n\t\tdeliveriesThisMonth: Number(monthlyRow?.total ?? 0),\n\t\tstorageBytes: Number(storageRow?.storage_bytes ?? 0),\n\t};\n}\n\nexport interface DailyUsage {\n\tdate: string;\n\tapiRequests: number;\n\tdeliveries: number;\n}\n\n/** Get last 7 days of daily usage, filling missing days with 0. */\nexport async function getDailyUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<DailyUsage[]> {\n\tconst rows = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select([\"date\", \"api_requests\", \"deliveries\"])\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", sql<string>`NOW()::date - 6`)\n\t\t.orderBy(\"date\", \"asc\")\n\t\t.execute();\n\n\t// Fill missing days with 0 (normalize date to YYYY-MM-DD string)\n\tconst byDate = new Map(\n\t\trows.map((r) => {\n\t\t\tconst d = r.date as unknown;\n\t\t\tconst key =\n\t\t\t\td instanceof Date\n\t\t\t\t\t? d.toISOString().slice(0, 10)\n\t\t\t\t\t: String(d).slice(0, 10);\n\t\t\treturn [key, r];\n\t\t}),\n\t);\n\tconst result: DailyUsage[] = [];\n\tfor (let i = 6; i >= 0; i--) {\n\t\tconst d = new Date();\n\t\td.setDate(d.getDate() - i);\n\t\tconst dateStr = d.toISOString().slice(0, 10);\n\t\tconst row = byDate.get(dateStr);\n\t\tresult.push({\n\t\t\tdate: dateStr,\n\t\t\tapiRequests: row?.api_requests ?? 0,\n\t\t\tdeliveries: row?.deliveries ?? 0,\n\t\t});\n\t}\n\treturn result;\n}\n\nexport interface LimitCheck {\n\tallowed: boolean;\n\tlimits: ReturnType<typeof getPlanLimits>;\n\tcurrent: UsageSummary & { streams: number; subgraphs: number };\n\texceeded?: string;\n}\n\n/** Check if an account is within plan limits. */\nexport async function checkLimits(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tplan: string,\n): Promise<LimitCheck> {\n\tconst limits = getPlanLimits(plan);\n\tconst usage = await getUsage(db, accountId);\n\n\t// Count streams owned by this account's keys\n\tconst streamCount = await db\n\t\t.selectFrom(\"streams\")\n\t\t.innerJoin(\"api_keys\", \"streams.api_key_id\", \"api_keys.id\")\n\t\t.select(sql<number>`count(*)`.as(\"count\"))\n\t\t.where(\"api_keys.account_id\", \"=\", accountId)\n\t\t.executeTakeFirst();\n\n\tconst subgraphCount = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n\t\t.select(sql<number>`count(*)`.as(\"count\"))\n\t\t.where(\"api_keys.account_id\", \"=\", accountId)\n\t\t.executeTakeFirst();\n\n\tconst current = {\n\t\t...usage,\n\t\tstreams: Number(streamCount?.count ?? 0),\n\t\tsubgraphs: Number(subgraphCount?.count ?? 0),\n\t};\n\n\t// Check each limit\n\tif (current.streams >= limits.streams) {\n\t\treturn { allowed: false, limits, current, exceeded: \"streams\" };\n\t}\n\tif (current.subgraphs >= limits.subgraphs) {\n\t\treturn { allowed: false, limits, current, exceeded: \"subgraphs\" };\n\t}\n\tif (current.apiRequestsToday >= limits.apiRequestsPerDay) {\n\t\treturn { allowed: false, limits, current, exceeded: \"api_requests\" };\n\t}\n\tif (current.deliveriesThisMonth >= limits.deliveriesPerMonth) {\n\t\treturn { allowed: false, limits, current, exceeded: \"deliveries\" };\n\t}\n\tif (current.storageBytes >= limits.storageBytes) {\n\t\treturn { allowed: false, limits, current, exceeded: \"storage\" };\n\t}\n\n\treturn { allowed: true, limits, current };\n}\n\n/**\n * Measure storage for all accounts by querying pg_total_relation_size\n * for each tenant's subgraph schemas.\n */\nexport async function measureStorage(db: Kysely<Database>): Promise<void> {\n\t// Get all accounts with subgraphs\n\tconst accountSubgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n\t\t.select([\"api_keys.account_id\", \"subgraphs.schema_name\"])\n\t\t.where(\"subgraphs.schema_name\", \"is not\", null)\n\t\t.execute();\n\n\t// Group schemas by account\n\tconst byAccount = new Map<string, string[]>();\n\tfor (const row of accountSubgraphs) {\n\t\tconst schemas = byAccount.get(row.account_id) ?? [];\n\t\tif (row.schema_name) schemas.push(row.schema_name);\n\t\tbyAccount.set(row.account_id, schemas);\n\t}\n\n\tfor (const [accountId, schemas] of byAccount) {\n\t\tlet totalBytes = 0;\n\t\tfor (const schema of schemas) {\n\t\t\ttry {\n\t\t\t\tconst result = await sql<{ size: string }>`\n SELECT COALESCE(SUM(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename))), 0)::text as size\n FROM pg_tables WHERE schemaname = ${schema}\n `.execute(db);\n\t\t\t\ttotalBytes += Number((result.rows[0] as any)?.size ?? 0);\n\t\t\t} catch {\n\t\t\t\t// Schema may not exist\n\t\t\t}\n\t\t}\n\n\t\tawait db\n\t\t\t.insertInto(\"usage_snapshots\")\n\t\t\t.values({\n\t\t\t\taccount_id: accountId,\n\t\t\t\tstorage_bytes: totalBytes,\n\t\t\t})\n\t\t\t.execute();\n\t}\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAQO,IAAM,YAAwB;AAAA,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "C9AA7973D9E596F264756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/src/db/schema.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ interface StreamsTable {
|
|
|
37
37
|
options: Generated<unknown>;
|
|
38
38
|
endpoint_url: string;
|
|
39
39
|
signing_secret: string | null;
|
|
40
|
-
api_key_id: string
|
|
40
|
+
api_key_id: string;
|
|
41
41
|
created_at: Generated<Date>;
|
|
42
42
|
updated_at: Generated<Date>;
|
|
43
43
|
}
|
|
@@ -91,15 +91,26 @@ interface SubgraphsTable {
|
|
|
91
91
|
schema_hash: string;
|
|
92
92
|
handler_path: string;
|
|
93
93
|
schema_name: string | null;
|
|
94
|
+
start_block: Generated<number>;
|
|
94
95
|
last_processed_block: Generated<number>;
|
|
95
96
|
last_error: string | null;
|
|
96
97
|
last_error_at: Date | null;
|
|
97
98
|
total_processed: Generated<number>;
|
|
98
99
|
total_errors: Generated<number>;
|
|
99
|
-
api_key_id: string
|
|
100
|
+
api_key_id: string;
|
|
100
101
|
created_at: Generated<Date>;
|
|
101
102
|
updated_at: Generated<Date>;
|
|
102
103
|
}
|
|
104
|
+
interface SubgraphGapsTable {
|
|
105
|
+
id: Generated<string>;
|
|
106
|
+
subgraph_id: string;
|
|
107
|
+
subgraph_name: string;
|
|
108
|
+
gap_start: number;
|
|
109
|
+
gap_end: number;
|
|
110
|
+
reason: string;
|
|
111
|
+
detected_at: Generated<Date>;
|
|
112
|
+
resolved_at: Date | null;
|
|
113
|
+
}
|
|
103
114
|
interface ApiKeysTable {
|
|
104
115
|
id: Generated<string>;
|
|
105
116
|
key_hash: string;
|
|
@@ -136,6 +147,7 @@ interface MagicLinksTable {
|
|
|
136
147
|
token: string;
|
|
137
148
|
expires_at: Date;
|
|
138
149
|
used_at: Date | null;
|
|
150
|
+
failed_attempts: Generated<number>;
|
|
139
151
|
created_at: Generated<Date>;
|
|
140
152
|
}
|
|
141
153
|
interface UsageDailyTable {
|
|
@@ -237,6 +249,7 @@ interface Database {
|
|
|
237
249
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
238
250
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
239
251
|
subgraph_table_snapshots: SubgraphTableSnapshotsTable;
|
|
252
|
+
subgraph_gaps: SubgraphGapsTable;
|
|
240
253
|
}
|
|
241
254
|
type Block = Selectable<BlocksTable>;
|
|
242
255
|
type InsertBlock = Insertable<BlocksTable>;
|
|
@@ -282,4 +295,6 @@ type AccountAgentRun = Selectable<AccountAgentRunsTable>;
|
|
|
282
295
|
type InsertAccountAgentRun = Insertable<AccountAgentRunsTable>;
|
|
283
296
|
type SubgraphHealthSnapshot = Selectable<SubgraphHealthSnapshotsTable>;
|
|
284
297
|
type InsertSubgraphHealthSnapshot = Insertable<SubgraphHealthSnapshotsTable>;
|
|
285
|
-
|
|
298
|
+
type SubgraphGap = Selectable<SubgraphGapsTable>;
|
|
299
|
+
type InsertSubgraphGap = Insertable<SubgraphGapsTable>;
|
|
300
|
+
export { WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateSubgraph, UpdateStreamRow, UpdateStreamMetrics, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, SubgraphsTable, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, StreamsTable, StreamMetricsTable, StreamMetrics, Stream, SessionsTable, Session, MagicLinksTable, MagicLink, JobsTable, Job, InsertTransaction, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertStreamMetrics, InsertStream, InsertSession, InsertMagicLink, InsertJob, InsertIndexProgress, InsertEvent, InsertDelivery, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Delivery, DeliveriesTable, Database, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
|
package/dist/src/env.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/env.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { z } from \"zod/v4\";\n\n// Parse comma-separated networks\nconst networksSchema = z.string().transform((val) => {\n
|
|
5
|
+
"import { z } from \"zod/v4\";\n\n// Parse comma-separated networks\nconst networksSchema = z.string().transform((val) => {\n\tconst networks = val\n\t\t.split(\",\")\n\t\t.map((n) => n.trim())\n\t\t.filter(Boolean);\n\tconst valid = [\"mainnet\", \"testnet\"];\n\tfor (const n of networks) {\n\t\tif (!valid.includes(n)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid network: ${n}. Must be one of: ${valid.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn networks as (\"mainnet\" | \"testnet\")[];\n});\n\ninterface EnvSchemaOutput {\n\tDATABASE_URL?: string;\n\tNETWORK?: \"mainnet\" | \"testnet\";\n\tNETWORKS?: (\"mainnet\" | \"testnet\")[];\n\tLOG_LEVEL: \"debug\" | \"info\" | \"warn\" | \"error\";\n\tNODE_ENV: \"development\" | \"production\" | \"test\";\n}\n\n// Cast needed: z.preprocess / z.default create different _input vs _output types\n// that z.ZodType<T> can't represent without explicit input type param\nconst envSchema: z.ZodType<EnvSchemaOutput> = z.object({\n\tDATABASE_URL: z.preprocess(\n\t\t(val) => (typeof val === \"string\" && val.length === 0 ? undefined : val),\n\t\tz.string().url().optional(),\n\t),\n\tNETWORK: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\tNETWORKS: networksSchema.optional(),\n\tLOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n\tNODE_ENV: z\n\t\t.enum([\"development\", \"production\", \"test\"])\n\t\t.default(\"development\"),\n}) as unknown as z.ZodType<EnvSchemaOutput>;\n\nexport type Env = EnvSchemaOutput & {\n\tenabledNetworks: (\"mainnet\" | \"testnet\")[];\n};\n\nlet cachedEnv: Env | null = null;\n\nexport function getEnv(): Env {\n\tif (cachedEnv) {\n\t\treturn cachedEnv;\n\t}\n\n\tconst result = envSchema.safeParse(process.env);\n\n\tif (!result.success) {\n\t\tconsole.error(\"❌ Invalid environment configuration:\");\n\t\tconsole.error(z.treeifyError(result.error));\n\t\tthrow new Error(\"Invalid environment configuration\");\n\t}\n\n\t// Compute enabled networks from NETWORKS or NETWORK\n\tlet enabledNetworks: (\"mainnet\" | \"testnet\")[];\n\tif (result.data.NETWORKS && result.data.NETWORKS.length > 0) {\n\t\tenabledNetworks = result.data.NETWORKS;\n\t} else if (result.data.NETWORK) {\n\t\tenabledNetworks = [result.data.NETWORK];\n\t} else {\n\t\tenabledNetworks = [\"mainnet\"]; // Default\n\t}\n\n\tcachedEnv = { ...result.data, enabledNetworks };\n\treturn cachedEnv;\n}\n\n// Export for testing\nexport { envSchema };\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAGA,IAAM,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ;AAAA,
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAGA,IAAM,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ;AAAA,EACpD,MAAM,WAAW,IACf,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA,EAChB,MAAM,QAAQ,CAAC,WAAW,SAAS;AAAA,EACnC,WAAW,KAAK,UAAU;AAAA,IACzB,IAAI,CAAC,MAAM,SAAS,CAAC,GAAG;AAAA,MACvB,MAAM,IAAI,MACT,oBAAoB,sBAAsB,MAAM,KAAK,IAAI,GAC1D;AAAA,IACD;AAAA,EACD;AAAA,EACA,OAAO;AAAA,CACP;AAYD,IAAM,YAAwC,EAAE,OAAO;AAAA,EACtD,cAAc,EAAE,WACf,CAAC,QAAS,OAAO,QAAQ,YAAY,IAAI,WAAW,IAAI,YAAY,KACpE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAC3B;AAAA,EACA,SAAS,EAAE,KAAK,CAAC,WAAW,SAAS,CAAC,EAAE,SAAS;AAAA,EACjD,UAAU,eAAe,SAAS;AAAA,EAClC,WAAW,EAAE,KAAK,CAAC,SAAS,QAAQ,QAAQ,OAAO,CAAC,EAAE,QAAQ,MAAM;AAAA,EACpE,UAAU,EACR,KAAK,CAAC,eAAe,cAAc,MAAM,CAAC,EAC1C,QAAQ,aAAa;AACxB,CAAC;AAMD,IAAI,YAAwB;AAErB,SAAS,MAAM,GAAQ;AAAA,EAC7B,IAAI,WAAW;AAAA,IACd,OAAO;AAAA,EACR;AAAA,EAEA,MAAM,SAAS,UAAU,UAAU,QAAQ,GAAG;AAAA,EAE9C,IAAI,CAAC,OAAO,SAAS;AAAA,IACpB,QAAQ,MAAM,sCAAqC;AAAA,IACnD,QAAQ,MAAM,EAAE,aAAa,OAAO,KAAK,CAAC;AAAA,IAC1C,MAAM,IAAI,MAAM,mCAAmC;AAAA,EACpD;AAAA,EAGA,IAAI;AAAA,EACJ,IAAI,OAAO,KAAK,YAAY,OAAO,KAAK,SAAS,SAAS,GAAG;AAAA,IAC5D,kBAAkB,OAAO,KAAK;AAAA,EAC/B,EAAO,SAAI,OAAO,KAAK,SAAS;AAAA,IAC/B,kBAAkB,CAAC,OAAO,KAAK,OAAO;AAAA,EACvC,EAAO;AAAA,IACN,kBAAkB,CAAC,SAAS;AAAA;AAAA,EAG7B,YAAY,KAAK,OAAO,MAAM,gBAAgB;AAAA,EAC9C,OAAO;AAAA;",
|
|
8
8
|
"debugId": "F91178E691D405D264756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
declare const ErrorCodes: {
|
|
2
|
+
readonly STREAM_NOT_FOUND: "STREAM_NOT_FOUND"
|
|
3
|
+
readonly VALIDATION_ERROR: "VALIDATION_ERROR"
|
|
4
|
+
readonly DATABASE_ERROR: "DATABASE_ERROR"
|
|
5
|
+
readonly DELIVERY_ERROR: "DELIVERY_ERROR"
|
|
6
|
+
readonly FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR"
|
|
7
|
+
readonly AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR"
|
|
8
|
+
readonly AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR"
|
|
9
|
+
readonly RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR"
|
|
10
|
+
readonly FORBIDDEN: "FORBIDDEN"
|
|
11
|
+
};
|
|
12
|
+
type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
1
13
|
/**
|
|
2
14
|
* Base error class for all Stacks Streams errors
|
|
3
15
|
*/
|
|
4
16
|
declare class StreamsError extends Error {
|
|
5
|
-
code:
|
|
17
|
+
code: ErrorCode;
|
|
6
18
|
cause?: unknown;
|
|
7
|
-
constructor(code:
|
|
19
|
+
constructor(code: ErrorCode, message: string, cause?: unknown);
|
|
8
20
|
toJSON(): {
|
|
9
21
|
name: string
|
|
10
22
|
code: string
|
|
@@ -66,9 +78,10 @@ declare class ForbiddenError extends StreamsError {
|
|
|
66
78
|
}
|
|
67
79
|
/** Error code → HTTP status. Used by API middleware for code-based matching
|
|
68
80
|
* (avoids cross-bundle instanceof failures from bunup class duplication). */
|
|
69
|
-
|
|
81
|
+
type MappedCode = Extract<ErrorCode, "AUTHENTICATION_ERROR" | "AUTHORIZATION_ERROR" | "RATE_LIMIT_ERROR" | "FORBIDDEN" | "STREAM_NOT_FOUND" | "VALIDATION_ERROR">;
|
|
82
|
+
declare const CODE_TO_STATUS: Record<MappedCode, 400 | 401 | 403 | 404 | 429>;
|
|
70
83
|
/**
|
|
71
84
|
* Safely extract error message from unknown error value
|
|
72
85
|
*/
|
|
73
86
|
declare function getErrorMessage(err: unknown): string;
|
|
74
|
-
export { getErrorMessage, ValidationError, StreamsError, StreamNotFoundError, RateLimitError, ForbiddenError, FilterEvaluationError, DeliveryError, DatabaseError, CODE_TO_STATUS, AuthorizationError, AuthenticationError };
|
|
87
|
+
export { getErrorMessage, ValidationError, StreamsError, StreamNotFoundError, RateLimitError, ForbiddenError, FilterEvaluationError, ErrorCodes, ErrorCode, DeliveryError, DatabaseError, CODE_TO_STATUS, AuthorizationError, AuthenticationError };
|
package/dist/src/errors.js
CHANGED
|
@@ -15,6 +15,18 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/errors.ts
|
|
18
|
+
var ErrorCodes = {
|
|
19
|
+
STREAM_NOT_FOUND: "STREAM_NOT_FOUND",
|
|
20
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
21
|
+
DATABASE_ERROR: "DATABASE_ERROR",
|
|
22
|
+
DELIVERY_ERROR: "DELIVERY_ERROR",
|
|
23
|
+
FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR",
|
|
24
|
+
AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR",
|
|
25
|
+
AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR",
|
|
26
|
+
RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR",
|
|
27
|
+
FORBIDDEN: "FORBIDDEN"
|
|
28
|
+
};
|
|
29
|
+
|
|
18
30
|
class StreamsError extends Error {
|
|
19
31
|
code;
|
|
20
32
|
cause;
|
|
@@ -108,7 +120,6 @@ var CODE_TO_STATUS = {
|
|
|
108
120
|
RATE_LIMIT_ERROR: 429,
|
|
109
121
|
FORBIDDEN: 403,
|
|
110
122
|
STREAM_NOT_FOUND: 404,
|
|
111
|
-
VIEW_NOT_FOUND: 404,
|
|
112
123
|
VALIDATION_ERROR: 400
|
|
113
124
|
};
|
|
114
125
|
function getErrorMessage(err) {
|
|
@@ -122,6 +133,7 @@ export {
|
|
|
122
133
|
RateLimitError,
|
|
123
134
|
ForbiddenError,
|
|
124
135
|
FilterEvaluationError,
|
|
136
|
+
ErrorCodes,
|
|
125
137
|
DeliveryError,
|
|
126
138
|
DatabaseError,
|
|
127
139
|
CODE_TO_STATUS,
|
|
@@ -129,5 +141,5 @@ export {
|
|
|
129
141
|
AuthenticationError
|
|
130
142
|
};
|
|
131
143
|
|
|
132
|
-
//# debugId=
|
|
144
|
+
//# debugId=04C32356C753666D64756E2164756E21
|
|
133
145
|
//# sourceMappingURL=errors.js.map
|
package/dist/src/errors.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/errors.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Base error class for all Stacks Streams errors\n */\nexport class StreamsError extends Error {\n
|
|
5
|
+
"export const ErrorCodes = {\n\tSTREAM_NOT_FOUND: \"STREAM_NOT_FOUND\",\n\tVALIDATION_ERROR: \"VALIDATION_ERROR\",\n\tDATABASE_ERROR: \"DATABASE_ERROR\",\n\tDELIVERY_ERROR: \"DELIVERY_ERROR\",\n\tFILTER_EVALUATION_ERROR: \"FILTER_EVALUATION_ERROR\",\n\tAUTHENTICATION_ERROR: \"AUTHENTICATION_ERROR\",\n\tAUTHORIZATION_ERROR: \"AUTHORIZATION_ERROR\",\n\tRATE_LIMIT_ERROR: \"RATE_LIMIT_ERROR\",\n\tFORBIDDEN: \"FORBIDDEN\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n/**\n * Base error class for all Stacks Streams errors\n */\nexport class StreamsError extends Error {\n\tpublic code: ErrorCode;\n\tpublic override cause?: unknown;\n\n\tconstructor(code: ErrorCode, message: string, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.code = code;\n\t\tthis.cause = cause;\n\t\tthis.name = this.constructor.name;\n\t\tError.captureStackTrace?.(this, this.constructor);\n\t}\n\n\ttoJSON(): {\n\t\tname: string;\n\t\tcode: string;\n\t\tmessage: string;\n\t\tstack: string | undefined;\n\t\tcause: unknown;\n\t} {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tcode: this.code,\n\t\t\tmessage: this.message,\n\t\t\tstack: this.stack,\n\t\t\tcause: this.cause,\n\t\t};\n\t}\n}\n\n/**\n * Stream not found error\n */\nexport class StreamNotFoundError extends StreamsError {\n\tconstructor(streamId: string) {\n\t\tsuper(\"STREAM_NOT_FOUND\", `Stream not found: ${streamId}`);\n\t}\n}\n\n/**\n * Validation error for invalid input\n */\nexport class ValidationError extends StreamsError {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"VALIDATION_ERROR\", message, cause);\n\t}\n}\n\n/**\n * Database operation error\n */\nexport class DatabaseError extends StreamsError {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"DATABASE_ERROR\", message, cause);\n\t}\n}\n\n/**\n * Delivery error\n */\nexport class DeliveryError extends StreamsError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic statusCode?: number,\n\t\tcause?: unknown,\n\t) {\n\t\tsuper(\"DELIVERY_ERROR\", message, cause);\n\t}\n\n\toverride toJSON(): {\n\t\tname: string;\n\t\tcode: string;\n\t\tmessage: string;\n\t\tstack: string | undefined;\n\t\tcause: unknown;\n\t\tstatusCode: number | undefined;\n\t} {\n\t\tconst base = super.toJSON();\n\t\treturn {\n\t\t\tname: base.name,\n\t\t\tcode: base.code,\n\t\t\tmessage: base.message,\n\t\t\tstack: base.stack,\n\t\t\tcause: base.cause,\n\t\t\tstatusCode: this.statusCode,\n\t\t};\n\t}\n}\n\n/**\n * Filter evaluation error\n */\nexport class FilterEvaluationError extends StreamsError {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper(\"FILTER_EVALUATION_ERROR\", message, cause);\n\t}\n}\n\nexport class AuthenticationError extends StreamsError {\n\tconstructor(message: string) {\n\t\tsuper(\"AUTHENTICATION_ERROR\", message);\n\t}\n}\n\nexport class AuthorizationError extends StreamsError {\n\tconstructor(message: string) {\n\t\tsuper(\"AUTHORIZATION_ERROR\", message);\n\t}\n}\n\nexport class RateLimitError extends StreamsError {\n\tconstructor(message: string) {\n\t\tsuper(\"RATE_LIMIT_ERROR\", message);\n\t}\n}\n\nexport class ForbiddenError extends StreamsError {\n\tconstructor(message = \"Forbidden\") {\n\t\tsuper(\"FORBIDDEN\", message);\n\t}\n}\n\n/** Error code → HTTP status. Used by API middleware for code-based matching\n * (avoids cross-bundle instanceof failures from bunup class duplication). */\ntype MappedCode = Extract<\n\tErrorCode,\n\t| \"AUTHENTICATION_ERROR\"\n\t| \"AUTHORIZATION_ERROR\"\n\t| \"RATE_LIMIT_ERROR\"\n\t| \"FORBIDDEN\"\n\t| \"STREAM_NOT_FOUND\"\n\t| \"VALIDATION_ERROR\"\n>;\nexport const CODE_TO_STATUS: Record<MappedCode, 400 | 401 | 403 | 404 | 429> = {\n\tAUTHENTICATION_ERROR: 401,\n\tAUTHORIZATION_ERROR: 403,\n\tRATE_LIMIT_ERROR: 429,\n\tFORBIDDEN: 403,\n\tSTREAM_NOT_FOUND: 404,\n\tVALIDATION_ERROR: 400,\n} as const;\n\n/**\n * Safely extract error message from unknown error value\n */\nexport function getErrorMessage(err: unknown): string {\n\treturn err instanceof Error ? err.message : String(err);\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAO,IAAM,aAAa;AAAA,EACzB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,WAAW;AACZ;AAAA;AAOO,MAAM,qBAAqB,MAAM;AAAA,EAChC;AAAA,EACS;AAAA,EAEhB,WAAW,CAAC,MAAiB,SAAiB,OAAiB;AAAA,IAC9D,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,QAAQ;AAAA,IACb,KAAK,OAAO,KAAK,YAAY;AAAA,IAC7B,MAAM,oBAAoB,MAAM,KAAK,WAAW;AAAA;AAAA,EAGjD,MAAM,GAMJ;AAAA,IACD,OAAO;AAAA,MACN,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,IACb;AAAA;AAEF;AAAA;AAKO,MAAM,4BAA4B,aAAa;AAAA,EACrD,WAAW,CAAC,UAAkB;AAAA,IAC7B,MAAM,oBAAoB,qBAAqB,UAAU;AAAA;AAE3D;AAAA;AAKO,MAAM,wBAAwB,aAAa;AAAA,EACjD,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC7C,MAAM,oBAAoB,SAAS,KAAK;AAAA;AAE1C;AAAA;AAKO,MAAM,sBAAsB,aAAa;AAAA,EAC/C,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC7C,MAAM,kBAAkB,SAAS,KAAK;AAAA;AAExC;AAAA;AAKO,MAAM,sBAAsB,aAAa;AAAA,EAGvC;AAAA,EAFR,WAAW,CACV,SACO,YACP,OACC;AAAA,IACD,MAAM,kBAAkB,SAAS,KAAK;AAAA,IAH/B;AAAA;AAAA,EAMC,MAAM,GAOb;AAAA,IACD,MAAM,OAAO,MAAM,OAAO;AAAA,IAC1B,OAAO;AAAA,MACN,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,IAClB;AAAA;AAEF;AAAA;AAKO,MAAM,8BAA8B,aAAa;AAAA,EACvD,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC7C,MAAM,2BAA2B,SAAS,KAAK;AAAA;AAEjD;AAAA;AAEO,MAAM,4BAA4B,aAAa;AAAA,EACrD,WAAW,CAAC,SAAiB;AAAA,IAC5B,MAAM,wBAAwB,OAAO;AAAA;AAEvC;AAAA;AAEO,MAAM,2BAA2B,aAAa;AAAA,EACpD,WAAW,CAAC,SAAiB;AAAA,IAC5B,MAAM,uBAAuB,OAAO;AAAA;AAEtC;AAAA;AAEO,MAAM,uBAAuB,aAAa;AAAA,EAChD,WAAW,CAAC,SAAiB;AAAA,IAC5B,MAAM,oBAAoB,OAAO;AAAA;AAEnC;AAAA;AAEO,MAAM,uBAAuB,aAAa;AAAA,EAChD,WAAW,CAAC,UAAU,aAAa;AAAA,IAClC,MAAM,aAAa,OAAO;AAAA;AAE5B;AAaO,IAAM,iBAAkE;AAAA,EAC9E,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,kBAAkB;AACnB;AAKO,SAAS,eAAe,CAAC,KAAsB;AAAA,EACrD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA;",
|
|
8
|
+
"debugId": "04C32356C753666D64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ interface StreamsTable {
|
|
|
37
37
|
options: Generated<unknown>;
|
|
38
38
|
endpoint_url: string;
|
|
39
39
|
signing_secret: string | null;
|
|
40
|
-
api_key_id: string
|
|
40
|
+
api_key_id: string;
|
|
41
41
|
created_at: Generated<Date>;
|
|
42
42
|
updated_at: Generated<Date>;
|
|
43
43
|
}
|
|
@@ -91,15 +91,26 @@ interface SubgraphsTable {
|
|
|
91
91
|
schema_hash: string;
|
|
92
92
|
handler_path: string;
|
|
93
93
|
schema_name: string | null;
|
|
94
|
+
start_block: Generated<number>;
|
|
94
95
|
last_processed_block: Generated<number>;
|
|
95
96
|
last_error: string | null;
|
|
96
97
|
last_error_at: Date | null;
|
|
97
98
|
total_processed: Generated<number>;
|
|
98
99
|
total_errors: Generated<number>;
|
|
99
|
-
api_key_id: string
|
|
100
|
+
api_key_id: string;
|
|
100
101
|
created_at: Generated<Date>;
|
|
101
102
|
updated_at: Generated<Date>;
|
|
102
103
|
}
|
|
104
|
+
interface SubgraphGapsTable {
|
|
105
|
+
id: Generated<string>;
|
|
106
|
+
subgraph_id: string;
|
|
107
|
+
subgraph_name: string;
|
|
108
|
+
gap_start: number;
|
|
109
|
+
gap_end: number;
|
|
110
|
+
reason: string;
|
|
111
|
+
detected_at: Generated<Date>;
|
|
112
|
+
resolved_at: Date | null;
|
|
113
|
+
}
|
|
103
114
|
interface ApiKeysTable {
|
|
104
115
|
id: Generated<string>;
|
|
105
116
|
key_hash: string;
|
|
@@ -136,6 +147,7 @@ interface MagicLinksTable {
|
|
|
136
147
|
token: string;
|
|
137
148
|
expires_at: Date;
|
|
138
149
|
used_at: Date | null;
|
|
150
|
+
failed_attempts: Generated<number>;
|
|
139
151
|
created_at: Generated<Date>;
|
|
140
152
|
}
|
|
141
153
|
interface UsageDailyTable {
|
|
@@ -237,6 +249,7 @@ interface Database {
|
|
|
237
249
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
238
250
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
239
251
|
subgraph_table_snapshots: SubgraphTableSnapshotsTable;
|
|
252
|
+
subgraph_gaps: SubgraphGapsTable;
|
|
240
253
|
}
|
|
241
254
|
type Block = Selectable<BlocksTable>;
|
|
242
255
|
type InsertBlock = Insertable<BlocksTable>;
|
|
@@ -282,6 +295,8 @@ type AccountAgentRun = Selectable<AccountAgentRunsTable>;
|
|
|
282
295
|
type InsertAccountAgentRun = Insertable<AccountAgentRunsTable>;
|
|
283
296
|
type SubgraphHealthSnapshot = Selectable<SubgraphHealthSnapshotsTable>;
|
|
284
297
|
type InsertSubgraphHealthSnapshot = Insertable<SubgraphHealthSnapshotsTable>;
|
|
298
|
+
type SubgraphGap = Selectable<SubgraphGapsTable>;
|
|
299
|
+
type InsertSubgraphGap = Insertable<SubgraphGapsTable>;
|
|
285
300
|
interface EnvSchemaOutput {
|
|
286
301
|
DATABASE_URL?: string;
|
|
287
302
|
NETWORK?: "mainnet" | "testnet";
|
|
@@ -321,13 +336,25 @@ declare function getDb(connectionString?: string): Kysely<Database>;
|
|
|
321
336
|
declare function getRawClient(): ReturnType<typeof postgres>;
|
|
322
337
|
/** Close the DB connection pool. Call in CLI commands to allow process exit. */
|
|
323
338
|
declare function closeDb(): Promise<void>;
|
|
339
|
+
declare const ErrorCodes: {
|
|
340
|
+
readonly STREAM_NOT_FOUND: "STREAM_NOT_FOUND"
|
|
341
|
+
readonly VALIDATION_ERROR: "VALIDATION_ERROR"
|
|
342
|
+
readonly DATABASE_ERROR: "DATABASE_ERROR"
|
|
343
|
+
readonly DELIVERY_ERROR: "DELIVERY_ERROR"
|
|
344
|
+
readonly FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR"
|
|
345
|
+
readonly AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR"
|
|
346
|
+
readonly AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR"
|
|
347
|
+
readonly RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR"
|
|
348
|
+
readonly FORBIDDEN: "FORBIDDEN"
|
|
349
|
+
};
|
|
350
|
+
type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
324
351
|
/**
|
|
325
352
|
* Base error class for all Stacks Streams errors
|
|
326
353
|
*/
|
|
327
354
|
declare class StreamsError extends Error {
|
|
328
|
-
code:
|
|
355
|
+
code: ErrorCode;
|
|
329
356
|
cause?: unknown;
|
|
330
|
-
constructor(code:
|
|
357
|
+
constructor(code: ErrorCode, message: string, cause?: unknown);
|
|
331
358
|
toJSON(): {
|
|
332
359
|
name: string
|
|
333
360
|
code: string
|
|
@@ -389,7 +416,8 @@ declare class ForbiddenError extends StreamsError {
|
|
|
389
416
|
}
|
|
390
417
|
/** Error code → HTTP status. Used by API middleware for code-based matching
|
|
391
418
|
* (avoids cross-bundle instanceof failures from bunup class duplication). */
|
|
392
|
-
|
|
419
|
+
type MappedCode = Extract<ErrorCode, "AUTHENTICATION_ERROR" | "AUTHORIZATION_ERROR" | "RATE_LIMIT_ERROR" | "FORBIDDEN" | "STREAM_NOT_FOUND" | "VALIDATION_ERROR">;
|
|
420
|
+
declare const CODE_TO_STATUS: Record<MappedCode, 400 | 401 | 403 | 404 | 429>;
|
|
393
421
|
/**
|
|
394
422
|
* Safely extract error message from unknown error value
|
|
395
423
|
*/
|
|
@@ -560,9 +588,35 @@ interface SubgraphSummary {
|
|
|
560
588
|
version: string;
|
|
561
589
|
status: string;
|
|
562
590
|
lastProcessedBlock: number;
|
|
591
|
+
totalProcessed: number;
|
|
592
|
+
totalErrors: number;
|
|
563
593
|
tables: string[];
|
|
594
|
+
chainTip: number;
|
|
595
|
+
progress: number;
|
|
596
|
+
gapCount: number;
|
|
597
|
+
integrity: "complete" | "gaps_detected";
|
|
564
598
|
createdAt: string;
|
|
565
599
|
}
|
|
600
|
+
interface SubgraphGapRange {
|
|
601
|
+
start: number;
|
|
602
|
+
end: number;
|
|
603
|
+
size: number;
|
|
604
|
+
reason: string;
|
|
605
|
+
}
|
|
606
|
+
interface SubgraphSyncInfo {
|
|
607
|
+
status: "synced" | "catching_up" | "reindexing" | "error";
|
|
608
|
+
startBlock: number;
|
|
609
|
+
lastProcessedBlock: number;
|
|
610
|
+
chainTip: number;
|
|
611
|
+
blocksRemaining: number;
|
|
612
|
+
progress: number;
|
|
613
|
+
gaps: {
|
|
614
|
+
count: number
|
|
615
|
+
totalMissingBlocks: number
|
|
616
|
+
ranges: SubgraphGapRange[]
|
|
617
|
+
};
|
|
618
|
+
integrity: "complete" | "gaps_detected";
|
|
619
|
+
}
|
|
566
620
|
interface SubgraphDetail {
|
|
567
621
|
name: string;
|
|
568
622
|
version: string;
|
|
@@ -575,6 +629,7 @@ interface SubgraphDetail {
|
|
|
575
629
|
lastError: string | null
|
|
576
630
|
lastErrorAt: string | null
|
|
577
631
|
};
|
|
632
|
+
sync: SubgraphSyncInfo;
|
|
578
633
|
tables: Record<string, {
|
|
579
634
|
endpoint: string
|
|
580
635
|
columns: Record<string, {
|
|
@@ -587,6 +642,23 @@ interface SubgraphDetail {
|
|
|
587
642
|
createdAt: string;
|
|
588
643
|
updatedAt: string;
|
|
589
644
|
}
|
|
645
|
+
interface SubgraphGapEntry {
|
|
646
|
+
start: number;
|
|
647
|
+
end: number;
|
|
648
|
+
size: number;
|
|
649
|
+
reason: string;
|
|
650
|
+
detectedAt: string;
|
|
651
|
+
resolvedAt: string | null;
|
|
652
|
+
}
|
|
653
|
+
interface SubgraphGapsResponse {
|
|
654
|
+
data: SubgraphGapEntry[];
|
|
655
|
+
meta: {
|
|
656
|
+
total: number
|
|
657
|
+
totalMissingBlocks: number
|
|
658
|
+
limit: number
|
|
659
|
+
offset: number
|
|
660
|
+
};
|
|
661
|
+
}
|
|
590
662
|
interface ReindexResponse {
|
|
591
663
|
message: string;
|
|
592
664
|
fromBlock: number;
|
|
@@ -725,4 +797,4 @@ declare function createSignatureHeader(payload: string, secret: string, timestam
|
|
|
725
797
|
* Returns true if valid, false otherwise
|
|
726
798
|
*/
|
|
727
799
|
declare function verifySignatureHeader(payload: string, header: string, secret: string, toleranceSeconds?: number): boolean;
|
|
728
|
-
export { sql, exports_queue as queue, parseJsonb, logger, jsonb, getRawClient, getErrorMessage, getEnv, getDb, exports_hmac as crypto, closeDb, WaitlistTable, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateSubgraph, UpdateStreamSchema, UpdateStreamRow, UpdateStreamMetrics, UpdateStream, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, SubgraphsTable, SubgraphTableSnapshotsTable, SubgraphSummary, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphDetail, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, StreamsTable, StreamsError, StreamResponseSchema, StreamResponse, StreamOptionsSchema, StreamOptions, StreamNotFoundError, StreamMetricsTable, StreamMetricsSchema, StreamMetricsResponse, StreamMetrics, StreamFilterSchema, StreamFilter, Stream, SessionsTable, Session, ReindexResponse, RateLimitError, QueueStats, PrintEventFilterSchema, PrintEventFilter, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, ListStreamsResponse, JobsTable, Job, InsertTransaction, InsertSubgraphHealthSnapshot, InsertSubgraph, InsertStreamMetrics, InsertStream, InsertSession, InsertMagicLink, InsertJob, InsertIndexProgress, InsertEvent, InsertDelivery, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, FilterEvaluationError, EventsTable, Event, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryPayloadSchema, DeliveryPayload, DeliveryError, Delivery, DeliveriesTable, DatabaseError, Database, CreateStreamSchema, CreateStreamResponse, CreateStream, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, CODE_TO_STATUS, BulkResumeResponse, BulkPauseResponse, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
|
|
800
|
+
export { sql, exports_queue as queue, parseJsonb, logger, jsonb, getRawClient, getErrorMessage, getEnv, getDb, exports_hmac as crypto, closeDb, WaitlistTable, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateSubgraph, UpdateStreamSchema, UpdateStreamRow, UpdateStreamMetrics, UpdateStream, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, SubgraphsTable, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, StreamsTable, StreamsError, StreamResponseSchema, StreamResponse, StreamOptionsSchema, StreamOptions, StreamNotFoundError, StreamMetricsTable, StreamMetricsSchema, StreamMetricsResponse, StreamMetrics, StreamFilterSchema, StreamFilter, Stream, SessionsTable, Session, ReindexResponse, RateLimitError, QueueStats, PrintEventFilterSchema, PrintEventFilter, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, ListStreamsResponse, JobsTable, Job, InsertTransaction, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertStreamMetrics, InsertStream, InsertSession, InsertMagicLink, InsertJob, InsertIndexProgress, InsertEvent, InsertDelivery, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, FilterEvaluationError, EventsTable, Event, ErrorCodes, ErrorCode, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryPayloadSchema, DeliveryPayload, DeliveryError, Delivery, DeliveriesTable, DatabaseError, Database, CreateStreamSchema, CreateStreamResponse, CreateStream, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, CODE_TO_STATUS, BulkResumeResponse, BulkPauseResponse, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
|
package/dist/src/index.js
CHANGED
|
@@ -41,8 +41,12 @@ function getDb(connectionString) {
|
|
|
41
41
|
if (!db) {
|
|
42
42
|
const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/streams_dev";
|
|
43
43
|
const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || url.includes("@postgres:");
|
|
44
|
+
const poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
|
|
44
45
|
rawClient = postgres(url, {
|
|
45
|
-
|
|
46
|
+
max: poolMax,
|
|
47
|
+
ssl: isLocal ? undefined : {
|
|
48
|
+
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0"
|
|
49
|
+
}
|
|
46
50
|
});
|
|
47
51
|
db = new Kysely({
|
|
48
52
|
dialect: new PostgresJSDialect({ postgres: rawClient })
|
|
@@ -66,6 +70,18 @@ async function closeDb() {
|
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
// src/errors.ts
|
|
73
|
+
var ErrorCodes = {
|
|
74
|
+
STREAM_NOT_FOUND: "STREAM_NOT_FOUND",
|
|
75
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
76
|
+
DATABASE_ERROR: "DATABASE_ERROR",
|
|
77
|
+
DELIVERY_ERROR: "DELIVERY_ERROR",
|
|
78
|
+
FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR",
|
|
79
|
+
AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR",
|
|
80
|
+
AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR",
|
|
81
|
+
RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR",
|
|
82
|
+
FORBIDDEN: "FORBIDDEN"
|
|
83
|
+
};
|
|
84
|
+
|
|
69
85
|
class StreamsError extends Error {
|
|
70
86
|
code;
|
|
71
87
|
cause;
|
|
@@ -159,7 +175,6 @@ var CODE_TO_STATUS = {
|
|
|
159
175
|
RATE_LIMIT_ERROR: 429,
|
|
160
176
|
FORBIDDEN: 403,
|
|
161
177
|
STREAM_NOT_FOUND: 404,
|
|
162
|
-
VIEW_NOT_FOUND: 404,
|
|
163
178
|
VALIDATION_ERROR: 400
|
|
164
179
|
};
|
|
165
180
|
function getErrorMessage(err) {
|
|
@@ -290,8 +305,8 @@ __export(exports_queue, {
|
|
|
290
305
|
claim: () => claim,
|
|
291
306
|
WORKER_ID: () => WORKER_ID
|
|
292
307
|
});
|
|
293
|
-
import { sql as sql3 } from "kysely";
|
|
294
308
|
import { randomUUID } from "crypto";
|
|
309
|
+
import { sql as sql3 } from "kysely";
|
|
295
310
|
var WORKER_ID = `worker-${randomUUID().slice(0, 8)}`;
|
|
296
311
|
async function enqueue(streamId, blockHeight, backfill = false) {
|
|
297
312
|
const db2 = getDb();
|
|
@@ -366,7 +381,7 @@ async function stats() {
|
|
|
366
381
|
`.execute(getDb());
|
|
367
382
|
const counts = {};
|
|
368
383
|
for (const row of rows) {
|
|
369
|
-
counts[row.status] = parseInt(row.count, 10);
|
|
384
|
+
counts[row.status] = Number.parseInt(row.count, 10);
|
|
370
385
|
}
|
|
371
386
|
return {
|
|
372
387
|
pending: counts["pending"] || 0,
|
|
@@ -380,8 +395,8 @@ function getWorkerId() {
|
|
|
380
395
|
return WORKER_ID;
|
|
381
396
|
}
|
|
382
397
|
// src/schemas/filters.ts
|
|
383
|
-
import { z as z2 } from "zod/v4";
|
|
384
398
|
import { isValidAddress as _isValidAddress } from "@secondlayer/stacks";
|
|
399
|
+
import { z as z2 } from "zod/v4";
|
|
385
400
|
var isValidAddress = _isValidAddress;
|
|
386
401
|
var stacksPrincipal = z2.string().refine((val) => {
|
|
387
402
|
const parts = val.split(".");
|
|
@@ -518,7 +533,9 @@ var UpdateStreamSchema = z4.object({
|
|
|
518
533
|
endpointUrl: z4.string().url().optional(),
|
|
519
534
|
filters: z4.array(StreamFilterSchema).min(1).optional(),
|
|
520
535
|
options: streamOptionsShape.partial().optional()
|
|
521
|
-
}).refine((data) => Object.keys(data).length > 0, {
|
|
536
|
+
}).refine((data) => Object.keys(data).length > 0, {
|
|
537
|
+
message: "At least one field must be provided for update"
|
|
538
|
+
});
|
|
522
539
|
var DeliveryPayloadSchema = z4.object({
|
|
523
540
|
streamId: z4.string().uuid(),
|
|
524
541
|
streamName: z4.string(),
|
|
@@ -613,7 +630,7 @@ function verifySignatureHeader(payload, header, secret, toleranceSeconds = 300)
|
|
|
613
630
|
if (!timestamp || !signature) {
|
|
614
631
|
return false;
|
|
615
632
|
}
|
|
616
|
-
const ts = parseInt(timestamp, 10);
|
|
633
|
+
const ts = Number.parseInt(timestamp, 10);
|
|
617
634
|
if (isNaN(ts)) {
|
|
618
635
|
return false;
|
|
619
636
|
}
|
|
@@ -658,6 +675,7 @@ export {
|
|
|
658
675
|
FtBurnFilterSchema,
|
|
659
676
|
ForbiddenError,
|
|
660
677
|
FilterEvaluationError,
|
|
678
|
+
ErrorCodes,
|
|
661
679
|
DeploySubgraphRequestSchema,
|
|
662
680
|
DeliveryPayloadSchema,
|
|
663
681
|
DeliveryError,
|
|
@@ -670,5 +688,5 @@ export {
|
|
|
670
688
|
AuthenticationError
|
|
671
689
|
};
|
|
672
690
|
|
|
673
|
-
//# debugId=
|
|
691
|
+
//# debugId=FE31159620AFAA0264756E2164756E21
|
|
674
692
|
//# sourceMappingURL=index.js.map
|