@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.
Files changed (73) hide show
  1. package/dist/src/crypto/hmac.js +2 -2
  2. package/dist/src/crypto/hmac.js.map +3 -3
  3. package/dist/src/db/index.d.ts +18 -3
  4. package/dist/src/db/index.js +6 -2
  5. package/dist/src/db/index.js.map +4 -4
  6. package/dist/src/db/jsonb.js.map +2 -2
  7. package/dist/src/db/queries/accounts.d.ts +16 -3
  8. package/dist/src/db/queries/accounts.js +6 -3
  9. package/dist/src/db/queries/accounts.js.map +3 -3
  10. package/dist/src/db/queries/integrity.d.ts +15 -2
  11. package/dist/src/db/queries/integrity.js.map +2 -2
  12. package/dist/src/db/queries/metrics.d.ts +15 -2
  13. package/dist/src/db/queries/metrics.js.map +2 -2
  14. package/dist/src/db/queries/subgraph-gaps.d.ts +305 -0
  15. package/dist/src/db/queries/subgraph-gaps.js +103 -0
  16. package/dist/src/db/queries/subgraph-gaps.js.map +10 -0
  17. package/dist/src/db/queries/subgraphs.d.ts +15 -2
  18. package/dist/src/db/queries/subgraphs.js +2 -2
  19. package/dist/src/db/queries/subgraphs.js.map +4 -4
  20. package/dist/src/db/queries/usage.d.ts +23 -3
  21. package/dist/src/db/queries/usage.js +35 -3
  22. package/dist/src/db/queries/usage.js.map +4 -4
  23. package/dist/src/db/schema.d.ts +18 -3
  24. package/dist/src/env.js.map +2 -2
  25. package/dist/src/errors.d.ts +17 -4
  26. package/dist/src/errors.js +14 -2
  27. package/dist/src/errors.js.map +3 -3
  28. package/dist/src/index.d.ts +78 -6
  29. package/dist/src/index.js +26 -8
  30. package/dist/src/index.js.map +12 -12
  31. package/dist/src/lib/plans.js.map +2 -2
  32. package/dist/src/logger.js.map +3 -3
  33. package/dist/src/node/archive-client.js +22 -6
  34. package/dist/src/node/archive-client.js.map +5 -5
  35. package/dist/src/node/client.js.map +2 -2
  36. package/dist/src/node/hiro-client.js +47 -11
  37. package/dist/src/node/hiro-client.js.map +5 -5
  38. package/dist/src/node/hiro-pg-client.js +131 -26
  39. package/dist/src/node/hiro-pg-client.js.map +3 -3
  40. package/dist/src/node/local-client.d.ts +15 -2
  41. package/dist/src/node/local-client.js.map +2 -2
  42. package/dist/src/queue/index.js +8 -4
  43. package/dist/src/queue/index.js.map +5 -5
  44. package/dist/src/queue/listener.js.map +2 -2
  45. package/dist/src/queue/recovery.js +6 -2
  46. package/dist/src/queue/recovery.js.map +5 -5
  47. package/dist/src/schemas/filters.js +2 -2
  48. package/dist/src/schemas/filters.js.map +3 -3
  49. package/dist/src/schemas/index.d.ts +45 -1
  50. package/dist/src/schemas/index.js +5 -3
  51. package/dist/src/schemas/index.js.map +5 -5
  52. package/dist/src/schemas/subgraphs.d.ts +45 -1
  53. package/dist/src/schemas/subgraphs.js.map +2 -2
  54. package/dist/src/types.d.ts +1 -1
  55. package/migrations/0001_initial.ts +295 -159
  56. package/migrations/0002_api_keys.ts +44 -28
  57. package/migrations/0003_tenant_isolation.ts +116 -107
  58. package/migrations/0004_accounts_and_usage.ts +81 -75
  59. package/migrations/0005_sessions.ts +33 -33
  60. package/migrations/0006_tx_index.ts +6 -2
  61. package/migrations/0007_contracts.ts +38 -24
  62. package/migrations/0008_drop_contracts.ts +33 -19
  63. package/migrations/0009_waitlist.ts +12 -12
  64. package/migrations/0010_waitlist_status.ts +5 -5
  65. package/migrations/0011_account_insights.ts +52 -52
  66. package/migrations/0012_view_health_snapshots.ts +21 -21
  67. package/migrations/0013_view_processing_stats.ts +32 -32
  68. package/migrations/0014_view_table_snapshots.ts +24 -24
  69. package/migrations/0015_rename_views_to_subgraphs.ts +137 -75
  70. package/migrations/0016_rename_webhook_to_endpoint.ts +12 -4
  71. package/migrations/0017_security_hardening.ts +32 -0
  72. package/migrations/0018_subgraph_gaps.ts +39 -0
  73. 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({ account_id: accountId, date: today, api_requests: 1, deliveries: 0 }).onConflict((oc) => oc.columns(["account_id", "date"]).doUpdateSet({
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({ account_id: accountId, date: today, api_requests: 0, deliveries: count }).onConflict((oc) => oc.columns(["account_id", "date"]).doUpdateSet({
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=31E68DFE6E6CCA6264756E2164756E21
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 streams: number;\n subgraphs: number;\n apiRequestsPerDay: number;\n deliveriesPerMonth: number;\n storageBytes: number;\n}\n\nexport const FREE_PLAN: PlanLimits = {\n streams: 3,\n subgraphs: 2,\n apiRequestsPerDay: 1_000,\n deliveriesPerMonth: 5_000,\n storageBytes: 100 * 1024 * 1024, // 100MB\n};\n\nexport function getPlanLimits(plan: string): PlanLimits {\n switch (plan) {\n case \"free\":\n default:\n return FREE_PLAN;\n }\n}\n",
6
- "import { sql, type Kysely } from \"kysely\";\nimport type { Database } from \"../types.ts\";\nimport { getPlanLimits } from \"../../lib/plans.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n db: Kysely<Database>,\n accountId: string,\n): Promise<void> {\n const today = new Date().toISOString().slice(0, 10);\n await db\n .insertInto(\"usage_daily\")\n .values({ account_id: accountId, date: today, api_requests: 1, deliveries: 0 })\n .onConflict((oc) =>\n oc.columns([\"account_id\", \"date\"]).doUpdateSet({\n api_requests: sql`usage_daily.api_requests + 1`,\n }),\n )\n .execute();\n}\n\n/** Increment delivery counter for today. */\nexport async function incrementDeliveries(\n db: Kysely<Database>,\n accountId: string,\n count = 1,\n): Promise<void> {\n const today = new Date().toISOString().slice(0, 10);\n await db\n .insertInto(\"usage_daily\")\n .values({ account_id: accountId, date: today, api_requests: 0, deliveries: count })\n .onConflict((oc) =>\n oc.columns([\"account_id\", \"date\"]).doUpdateSet({\n deliveries: sql`usage_daily.deliveries + ${count}`,\n }),\n )\n .execute();\n}\n\nexport interface UsageSummary {\n apiRequestsToday: number;\n deliveriesThisMonth: number;\n storageBytes: number;\n}\n\n/** Get current usage for an account. */\nexport async function getUsage(\n db: Kysely<Database>,\n accountId: string,\n): Promise<UsageSummary> {\n const today = new Date().toISOString().slice(0, 10);\n const monthStart = today.slice(0, 7) + \"-01\"; // YYYY-MM-01\n\n // Today's API requests\n const dailyRow = await db\n .selectFrom(\"usage_daily\")\n .select(\"api_requests\")\n .where(\"account_id\", \"=\", accountId)\n .where(\"date\", \"=\", today)\n .executeTakeFirst();\n\n // This month's deliveries\n const monthlyRow = await db\n .selectFrom(\"usage_daily\")\n .select(sql<number>`COALESCE(SUM(deliveries), 0)`.as(\"total\"))\n .where(\"account_id\", \"=\", accountId)\n .where(\"date\", \">=\", monthStart)\n .executeTakeFirst();\n\n // Latest storage snapshot\n const storageRow = await db\n .selectFrom(\"usage_snapshots\")\n .select(\"storage_bytes\")\n .where(\"account_id\", \"=\", accountId)\n .orderBy(\"measured_at\", \"desc\")\n .limit(1)\n .executeTakeFirst();\n\n return {\n apiRequestsToday: dailyRow?.api_requests ?? 0,\n deliveriesThisMonth: Number(monthlyRow?.total ?? 0),\n storageBytes: Number(storageRow?.storage_bytes ?? 0),\n };\n}\n\nexport interface LimitCheck {\n allowed: boolean;\n limits: ReturnType<typeof getPlanLimits>;\n current: UsageSummary & { streams: number; subgraphs: number };\n exceeded?: string;\n}\n\n/** Check if an account is within plan limits. */\nexport async function checkLimits(\n db: Kysely<Database>,\n accountId: string,\n plan: string,\n): Promise<LimitCheck> {\n const limits = getPlanLimits(plan);\n const usage = await getUsage(db, accountId);\n\n // Count streams owned by this account's keys\n const streamCount = await db\n .selectFrom(\"streams\")\n .innerJoin(\"api_keys\", \"streams.api_key_id\", \"api_keys.id\")\n .select(sql<number>`count(*)`.as(\"count\"))\n .where(\"api_keys.account_id\", \"=\", accountId)\n .executeTakeFirst();\n\n const subgraphCount = await db\n .selectFrom(\"subgraphs\")\n .innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n .select(sql<number>`count(*)`.as(\"count\"))\n .where(\"api_keys.account_id\", \"=\", accountId)\n .executeTakeFirst();\n\n const current = {\n ...usage,\n streams: Number(streamCount?.count ?? 0),\n subgraphs: Number(subgraphCount?.count ?? 0),\n };\n\n // Check each limit\n if (current.streams >= limits.streams) {\n return { allowed: false, limits, current, exceeded: \"streams\" };\n }\n if (current.subgraphs >= limits.subgraphs) {\n return { allowed: false, limits, current, exceeded: \"subgraphs\" };\n }\n if (current.apiRequestsToday >= limits.apiRequestsPerDay) {\n return { allowed: false, limits, current, exceeded: \"api_requests\" };\n }\n if (current.deliveriesThisMonth >= limits.deliveriesPerMonth) {\n return { allowed: false, limits, current, exceeded: \"deliveries\" };\n }\n if (current.storageBytes >= limits.storageBytes) {\n return { allowed: false, limits, current, exceeded: \"storage\" };\n }\n\n return { 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 // Get all accounts with subgraphs\n const accountSubgraphs = await db\n .selectFrom(\"subgraphs\")\n .innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n .select([\"api_keys.account_id\", \"subgraphs.schema_name\"])\n .where(\"subgraphs.schema_name\", \"is not\", null)\n .execute();\n\n // Group schemas by account\n const byAccount = new Map<string, string[]>();\n for (const row of accountSubgraphs) {\n const schemas = byAccount.get(row.account_id) ?? [];\n if (row.schema_name) schemas.push(row.schema_name);\n byAccount.set(row.account_id, schemas);\n }\n\n for (const [accountId, schemas] of byAccount) {\n let totalBytes = 0;\n for (const schema of schemas) {\n try {\n const 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 totalBytes += Number((result.rows[0] as any)?.size ?? 0);\n } catch {\n // Schema may not exist\n }\n }\n\n await db\n .insertInto(\"usage_snapshots\")\n .values({\n account_id: accountId,\n storage_bytes: totalBytes,\n })\n .execute();\n }\n}\n"
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": "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",
9
- "debugId": "31E68DFE6E6CCA6264756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "C9AA7973D9E596F264756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -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 | null;
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 | null;
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
- export { WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateSubgraph, UpdateStreamRow, UpdateStreamMetrics, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, SubgraphsTable, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, Subgraph, StreamsTable, StreamMetricsTable, StreamMetrics, Stream, SessionsTable, Session, MagicLinksTable, MagicLink, JobsTable, Job, InsertTransaction, InsertSubgraphHealthSnapshot, 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 };
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 };
@@ -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 const networks = val.split(\",\").map((n) => n.trim()).filter(Boolean);\n const valid = [\"mainnet\", \"testnet\"];\n for (const n of networks) {\n if (!valid.includes(n)) {\n throw new Error(`Invalid network: ${n}. Must be one of: ${valid.join(\", \")}`);\n }\n }\n return networks as (\"mainnet\" | \"testnet\")[];\n});\n\ninterface EnvSchemaOutput {\n DATABASE_URL?: string;\n NETWORK?: \"mainnet\" | \"testnet\";\n NETWORKS?: (\"mainnet\" | \"testnet\")[];\n LOG_LEVEL: \"debug\" | \"info\" | \"warn\" | \"error\";\n NODE_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 DATABASE_URL: z.preprocess(\n (val) => (typeof val === \"string\" && val.length === 0) ? undefined : val,\n z.string().url().optional(),\n ),\n NETWORK: z.enum([\"mainnet\", \"testnet\"]).optional(),\n NETWORKS: networksSchema.optional(),\n LOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n}) as unknown as z.ZodType<EnvSchemaOutput>;\n\nexport type Env = EnvSchemaOutput & {\n enabledNetworks: (\"mainnet\" | \"testnet\")[];\n};\n\nlet cachedEnv: Env | null = null;\n\nexport function getEnv(): Env {\n if (cachedEnv) {\n return cachedEnv;\n }\n\n const result = envSchema.safeParse(process.env);\n\n if (!result.success) {\n console.error(\"❌ Invalid environment configuration:\");\n console.error(z.treeifyError(result.error));\n throw new Error(\"Invalid environment configuration\");\n }\n\n // Compute enabled networks from NETWORKS or NETWORK\n let enabledNetworks: (\"mainnet\" | \"testnet\")[];\n if (result.data.NETWORKS && result.data.NETWORKS.length > 0) {\n enabledNetworks = result.data.NETWORKS;\n } else if (result.data.NETWORK) {\n enabledNetworks = [result.data.NETWORK];\n } else {\n enabledNetworks = [\"mainnet\"]; // Default\n }\n\n cachedEnv = { ...result.data, enabledNetworks };\n return cachedEnv;\n}\n\n// Export for testing\nexport { envSchema };\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,EACnD,MAAM,WAAW,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,EACnE,MAAM,QAAQ,CAAC,WAAW,SAAS;AAAA,EACnC,WAAW,KAAK,UAAU;AAAA,IACxB,IAAI,CAAC,MAAM,SAAS,CAAC,GAAG;AAAA,MACtB,MAAM,IAAI,MAAM,oBAAoB,sBAAsB,MAAM,KAAK,IAAI,GAAG;AAAA,IAC9E;AAAA,EACF;AAAA,EACA,OAAO;AAAA,CACR;AAYD,IAAM,YAAwC,EAAE,OAAO;AAAA,EACrD,cAAc,EAAE,WACd,CAAC,QAAS,OAAO,QAAQ,YAAY,IAAI,WAAW,IAAK,YAAY,KACrE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAC5B;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,EAAE,KAAK,CAAC,eAAe,cAAc,MAAM,CAAC,EAAE,QAAQ,aAAa;AAC/E,CAAC;AAMD,IAAI,YAAwB;AAErB,SAAS,MAAM,GAAQ;AAAA,EAC5B,IAAI,WAAW;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,UAAU,UAAU,QAAQ,GAAG;AAAA,EAE9C,IAAI,CAAC,OAAO,SAAS;AAAA,IACnB,QAAQ,MAAM,sCAAqC;AAAA,IACnD,QAAQ,MAAM,EAAE,aAAa,OAAO,KAAK,CAAC;AAAA,IAC1C,MAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAAA,EAGA,IAAI;AAAA,EACJ,IAAI,OAAO,KAAK,YAAY,OAAO,KAAK,SAAS,SAAS,GAAG;AAAA,IAC3D,kBAAkB,OAAO,KAAK;AAAA,EAChC,EAAO,SAAI,OAAO,KAAK,SAAS;AAAA,IAC9B,kBAAkB,CAAC,OAAO,KAAK,OAAO;AAAA,EACxC,EAAO;AAAA,IACL,kBAAkB,CAAC,SAAS;AAAA;AAAA,EAG9B,YAAY,KAAK,OAAO,MAAM,gBAAgB;AAAA,EAC9C,OAAO;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
  }
@@ -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: string;
17
+ code: ErrorCode;
6
18
  cause?: unknown;
7
- constructor(code: string, message: string, cause?: unknown);
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
- declare const CODE_TO_STATUS: Record<string, 400 | 401 | 403 | 404 | 429>;
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 };
@@ -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=47BA7DDA27F2DCB464756E2164756E21
144
+ //# debugId=04C32356C753666D64756E2164756E21
133
145
  //# sourceMappingURL=errors.js.map
@@ -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 public code: string;\n public override cause?: unknown;\n\n constructor(\n code: string,\n message: string,\n cause?: unknown\n ) {\n super(message);\n this.code = code;\n this.cause = cause;\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n\n toJSON(): { name: string; code: string; message: string; stack: string | undefined; cause: unknown } {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n stack: this.stack,\n cause: this.cause,\n };\n }\n}\n\n/**\n * Stream not found error\n */\nexport class StreamNotFoundError extends StreamsError {\n constructor(streamId: string) {\n super(\"STREAM_NOT_FOUND\", `Stream not found: ${streamId}`);\n }\n}\n\n/**\n * Validation error for invalid input\n */\nexport class ValidationError extends StreamsError {\n constructor(message: string, cause?: unknown) {\n super(\"VALIDATION_ERROR\", message, cause);\n }\n}\n\n/**\n * Database operation error\n */\nexport class DatabaseError extends StreamsError {\n constructor(message: string, cause?: unknown) {\n super(\"DATABASE_ERROR\", message, cause);\n }\n}\n\n/**\n * Delivery error\n */\nexport class DeliveryError extends StreamsError {\n constructor(\n message: string,\n public statusCode?: number,\n cause?: unknown\n ) {\n super(\"DELIVERY_ERROR\", message, cause);\n }\n\n override toJSON(): { name: string; code: string; message: string; stack: string | undefined; cause: unknown; statusCode: number | undefined } {\n const base = super.toJSON();\n return {\n name: base.name,\n code: base.code,\n message: base.message,\n stack: base.stack,\n cause: base.cause,\n statusCode: this.statusCode,\n };\n }\n}\n\n/**\n * Filter evaluation error\n */\nexport class FilterEvaluationError extends StreamsError {\n constructor(message: string, cause?: unknown) {\n super(\"FILTER_EVALUATION_ERROR\", message, cause);\n }\n}\n\nexport class AuthenticationError extends StreamsError {\n constructor(message: string) {\n super(\"AUTHENTICATION_ERROR\", message);\n }\n}\n\nexport class AuthorizationError extends StreamsError {\n constructor(message: string) {\n super(\"AUTHORIZATION_ERROR\", message);\n }\n}\n\nexport class RateLimitError extends StreamsError {\n constructor(message: string) {\n super(\"RATE_LIMIT_ERROR\", message);\n }\n}\n\nexport class ForbiddenError extends StreamsError {\n constructor(message = \"Forbidden\") {\n super(\"FORBIDDEN\", message);\n }\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). */\nexport const CODE_TO_STATUS: Record<string, 400 | 401 | 403 | 404 | 429> = {\n AUTHENTICATION_ERROR: 401,\n AUTHORIZATION_ERROR: 403,\n RATE_LIMIT_ERROR: 429,\n FORBIDDEN: 403,\n STREAM_NOT_FOUND: 404,\n VIEW_NOT_FOUND: 404,\n VALIDATION_ERROR: 400,\n} as const;\n\n/**\n * Safely extract error message from unknown error value\n */\nexport function getErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\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": ";;;;;;;;;;;;;;;;;AAGO,MAAM,qBAAqB,MAAM;AAAA,EAC/B;AAAA,EACS;AAAA,EAEhB,WAAW,CACT,MACA,SACA,OACA;AAAA,IACA,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,EAGlD,MAAM,GAA+F;AAAA,IACnG,OAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,IACd;AAAA;AAEJ;AAAA;AAKO,MAAM,4BAA4B,aAAa;AAAA,EACpD,WAAW,CAAC,UAAkB;AAAA,IAC5B,MAAM,oBAAoB,qBAAqB,UAAU;AAAA;AAE7D;AAAA;AAKO,MAAM,wBAAwB,aAAa;AAAA,EAChD,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC5C,MAAM,oBAAoB,SAAS,KAAK;AAAA;AAE5C;AAAA;AAKO,MAAM,sBAAsB,aAAa;AAAA,EAC9C,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC5C,MAAM,kBAAkB,SAAS,KAAK;AAAA;AAE1C;AAAA;AAKO,MAAM,sBAAsB,aAAa;AAAA,EAGrC;AAAA,EAFT,WAAW,CACT,SACO,YACP,OACA;AAAA,IACA,MAAM,kBAAkB,SAAS,KAAK;AAAA,IAH/B;AAAA;AAAA,EAMA,MAAM,GAA+H;AAAA,IAC5I,MAAM,OAAO,MAAM,OAAO;AAAA,IAC1B,OAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,IACnB;AAAA;AAEJ;AAAA;AAKO,MAAM,8BAA8B,aAAa;AAAA,EACtD,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC5C,MAAM,2BAA2B,SAAS,KAAK;AAAA;AAEnD;AAAA;AAEO,MAAM,4BAA4B,aAAa;AAAA,EACpD,WAAW,CAAC,SAAiB;AAAA,IAC3B,MAAM,wBAAwB,OAAO;AAAA;AAEzC;AAAA;AAEO,MAAM,2BAA2B,aAAa;AAAA,EACnD,WAAW,CAAC,SAAiB;AAAA,IAC3B,MAAM,uBAAuB,OAAO;AAAA;AAExC;AAAA;AAEO,MAAM,uBAAuB,aAAa;AAAA,EAC/C,WAAW,CAAC,SAAiB;AAAA,IAC3B,MAAM,oBAAoB,OAAO;AAAA;AAErC;AAAA;AAEO,MAAM,uBAAuB,aAAa;AAAA,EAC/C,WAAW,CAAC,UAAU,aAAa;AAAA,IACjC,MAAM,aAAa,OAAO;AAAA;AAE9B;AAIO,IAAM,iBAA8D;AAAA,EACzE,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AACpB;AAKO,SAAS,eAAe,CAAC,KAAsB;AAAA,EACpD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA;",
8
- "debugId": "47BA7DDA27F2DCB464756E2164756E21",
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
  }
@@ -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 | null;
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 | null;
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: string;
355
+ code: ErrorCode;
329
356
  cause?: unknown;
330
- constructor(code: string, message: string, cause?: unknown);
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
- declare const CODE_TO_STATUS: Record<string, 400 | 401 | 403 | 404 | 429>;
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
- ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" }
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, { message: "At least one field must be provided for update" });
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=4EF79202801DC1C664756E2164756E21
691
+ //# debugId=FE31159620AFAA0264756E2164756E21
674
692
  //# sourceMappingURL=index.js.map