@secondlayer/shared 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/src/crypto/hmac.d.ts +1 -1
  2. package/dist/src/crypto/hmac.js +6 -2
  3. package/dist/src/crypto/hmac.js.map +3 -3
  4. package/dist/src/db/index.d.ts +85 -8
  5. package/dist/src/db/index.js +6 -2
  6. package/dist/src/db/index.js.map +2 -2
  7. package/dist/src/db/jsonb.js +6 -2
  8. package/dist/src/db/jsonb.js.map +2 -2
  9. package/dist/src/db/queries/accounts.d.ts +77 -5
  10. package/dist/src/db/queries/accounts.js +17 -2
  11. package/dist/src/db/queries/accounts.js.map +3 -3
  12. package/dist/src/db/queries/integrity.d.ts +75 -4
  13. package/dist/src/db/queries/integrity.js +6 -2
  14. package/dist/src/db/queries/integrity.js.map +2 -2
  15. package/dist/src/db/queries/metrics.d.ts +75 -4
  16. package/dist/src/db/queries/metrics.js +6 -2
  17. package/dist/src/db/queries/metrics.js.map +2 -2
  18. package/dist/src/db/queries/{views.d.ts → subgraphs.d.ts} +89 -18
  19. package/dist/src/db/queries/{views.js → subgraphs.js} +37 -33
  20. package/dist/src/db/queries/subgraphs.js.map +11 -0
  21. package/dist/src/db/queries/usage.d.ts +78 -7
  22. package/dist/src/db/queries/usage.js +13 -9
  23. package/dist/src/db/queries/usage.js.map +4 -4
  24. package/dist/src/db/schema.d.ts +85 -8
  25. package/dist/src/env.d.ts +1 -1
  26. package/dist/src/env.js +8 -4
  27. package/dist/src/env.js.map +3 -3
  28. package/dist/src/errors.d.ts +3 -3
  29. package/dist/src/errors.js +9 -5
  30. package/dist/src/errors.js.map +3 -3
  31. package/dist/src/index.d.ts +104 -27
  32. package/dist/src/index.js +24 -20
  33. package/dist/src/index.js.map +9 -9
  34. package/dist/src/lib/plans.d.ts +1 -1
  35. package/dist/src/lib/plans.js +7 -3
  36. package/dist/src/lib/plans.js.map +3 -3
  37. package/dist/src/logger.js +8 -4
  38. package/dist/src/logger.js.map +3 -3
  39. package/dist/src/node/client.js +6 -2
  40. package/dist/src/node/client.js.map +2 -2
  41. package/dist/src/node/hiro-client.js +8 -4
  42. package/dist/src/node/hiro-client.js.map +3 -3
  43. package/dist/src/node/local-client.d.ts +75 -4
  44. package/dist/src/node/local-client.js +6 -2
  45. package/dist/src/node/local-client.js.map +3 -3
  46. package/dist/src/queue/index.js +6 -2
  47. package/dist/src/queue/index.js.map +2 -2
  48. package/dist/src/queue/listener.js +6 -2
  49. package/dist/src/queue/listener.js.map +2 -2
  50. package/dist/src/queue/recovery.js +6 -2
  51. package/dist/src/queue/recovery.js.map +2 -2
  52. package/dist/src/schemas/filters.d.ts +1 -1
  53. package/dist/src/schemas/filters.js +7 -3
  54. package/dist/src/schemas/filters.js.map +3 -3
  55. package/dist/src/schemas/index.d.ts +17 -17
  56. package/dist/src/schemas/index.js +19 -15
  57. package/dist/src/schemas/index.js.map +6 -6
  58. package/dist/src/schemas/{views.d.ts → subgraphs.d.ts} +9 -9
  59. package/dist/src/schemas/{views.js → subgraphs.js} +12 -8
  60. package/dist/src/schemas/subgraphs.js.map +10 -0
  61. package/dist/src/types.d.ts +2 -2
  62. package/dist/src/types.js +1 -12
  63. package/dist/src/types.js.map +1 -1
  64. package/migrations/0009_waitlist.ts +19 -0
  65. package/migrations/0010_waitlist_status.ts +12 -0
  66. package/migrations/0011_account_insights.ts +63 -0
  67. package/migrations/0012_view_health_snapshots.ts +29 -0
  68. package/migrations/0013_view_processing_stats.ts +42 -0
  69. package/migrations/0014_view_table_snapshots.ts +33 -0
  70. package/migrations/0015_rename_views_to_subgraphs.ts +136 -0
  71. package/migrations/0016_rename_webhook_to_endpoint.ts +12 -0
  72. package/package.json +8 -8
  73. package/dist/src/db/queries/views.js.map +0 -11
  74. package/dist/src/schemas/views.js.map +0 -10
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Generate a random secret for webhook signing
2
+ * Generate a random secret for delivery signing
3
3
  * Returns 32 bytes as a 64-character hex string
4
4
  */
5
5
  declare function generateSecret(): string;
@@ -1,12 +1,16 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
 
@@ -71,5 +75,5 @@ export {
71
75
  createSignatureHeader
72
76
  };
73
77
 
74
- //# debugId=C5FB6F078225904664756E2164756E21
78
+ //# debugId=A51CF8494ADEA11C64756E2164756E21
75
79
  //# sourceMappingURL=hmac.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/crypto/hmac.ts"],
4
4
  "sourcesContent": [
5
- "import { createHmac, randomBytes } from \"crypto\";\n\n/**\n * Generate a random secret for webhook signing\n * Returns 32 bytes as a 64-character hex string\n */\nexport function generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n}\n\n/**\n * Sign a payload with HMAC-SHA256\n * Returns the signature as a hex string\n */\nexport function signPayload(payload: string, secret: string): string {\n const hmac = createHmac(\"sha256\", secret);\n hmac.update(payload);\n return hmac.digest(\"hex\");\n}\n\n/**\n * Verify an HMAC signature\n * Uses constant-time comparison to prevent timing attacks\n */\nexport function verifySignature(\n payload: string,\n signature: string,\n secret: string\n): boolean {\n const expectedSignature = signPayload(payload, secret);\n\n // Constant-time comparison\n if (signature.length !== expectedSignature.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < signature.length; i++) {\n result |= signature.charCodeAt(i) ^ expectedSignature.charCodeAt(i);\n }\n\n return result === 0;\n}\n\n/**\n * Create a Stripe-style signature header\n * Format: t=timestamp,v1=signature\n */\nexport function createSignatureHeader(\n payload: string,\n secret: string,\n timestamp?: number\n): string {\n const ts = timestamp ?? Math.floor(Date.now() / 1000);\n const signedPayload = `${ts}.${payload}`;\n const signature = signPayload(signedPayload, secret);\n\n return `t=${ts},v1=${signature}`;\n}\n\n/**\n * Parse and verify a Stripe-style signature header\n * Returns true if valid, false otherwise\n */\nexport function verifySignatureHeader(\n payload: string,\n header: string,\n secret: string,\n toleranceSeconds = 300 // 5 minutes\n): boolean {\n // Parse header\n const parts = header.split(\",\");\n const timestamp = parts\n .find((p) => p.startsWith(\"t=\"))\n ?.slice(2);\n const signature = parts\n .find((p) => p.startsWith(\"v1=\"))\n ?.slice(3);\n\n if (!timestamp || !signature) {\n return false;\n }\n\n const ts = parseInt(timestamp, 10);\n if (isNaN(ts)) {\n return false;\n }\n\n // Check timestamp is within tolerance\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > toleranceSeconds) {\n return false;\n }\n\n // Verify signature\n const signedPayload = `${ts}.${payload}`;\n return verifySignature(signedPayload, signature, secret);\n}\n"
5
+ "import { createHmac, randomBytes } from \"crypto\";\n\n/**\n * Generate a random secret for delivery signing\n * Returns 32 bytes as a 64-character hex string\n */\nexport function generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n}\n\n/**\n * Sign a payload with HMAC-SHA256\n * Returns the signature as a hex string\n */\nexport function signPayload(payload: string, secret: string): string {\n const hmac = createHmac(\"sha256\", secret);\n hmac.update(payload);\n return hmac.digest(\"hex\");\n}\n\n/**\n * Verify an HMAC signature\n * Uses constant-time comparison to prevent timing attacks\n */\nexport function verifySignature(\n payload: string,\n signature: string,\n secret: string\n): boolean {\n const expectedSignature = signPayload(payload, secret);\n\n // Constant-time comparison\n if (signature.length !== expectedSignature.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < signature.length; i++) {\n result |= signature.charCodeAt(i) ^ expectedSignature.charCodeAt(i);\n }\n\n return result === 0;\n}\n\n/**\n * Create a Stripe-style signature header\n * Format: t=timestamp,v1=signature\n */\nexport function createSignatureHeader(\n payload: string,\n secret: string,\n timestamp?: number\n): string {\n const ts = timestamp ?? Math.floor(Date.now() / 1000);\n const signedPayload = `${ts}.${payload}`;\n const signature = signPayload(signedPayload, secret);\n\n return `t=${ts},v1=${signature}`;\n}\n\n/**\n * Parse and verify a Stripe-style signature header\n * Returns true if valid, false otherwise\n */\nexport function verifySignatureHeader(\n payload: string,\n header: string,\n secret: string,\n toleranceSeconds = 300 // 5 minutes\n): boolean {\n // Parse header\n const parts = header.split(\",\");\n const timestamp = parts\n .find((p) => p.startsWith(\"t=\"))\n ?.slice(2);\n const signature = parts\n .find((p) => p.startsWith(\"v1=\"))\n ?.slice(3);\n\n if (!timestamp || !signature) {\n return false;\n }\n\n const ts = parseInt(timestamp, 10);\n if (isNaN(ts)) {\n return false;\n }\n\n // Check timestamp is within tolerance\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > toleranceSeconds) {\n return false;\n }\n\n // Verify signature\n const signedPayload = `${ts}.${payload}`;\n return verifySignature(signedPayload, signature, secret);\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAMO,SAAS,cAAc,GAAW;AAAA,EACvC,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA;AAOhC,SAAS,WAAW,CAAC,SAAiB,QAAwB;AAAA,EACnE,MAAM,OAAO,WAAW,UAAU,MAAM;AAAA,EACxC,KAAK,OAAO,OAAO;AAAA,EACnB,OAAO,KAAK,OAAO,KAAK;AAAA;AAOnB,SAAS,eAAe,CAC7B,SACA,WACA,QACS;AAAA,EACT,MAAM,oBAAoB,YAAY,SAAS,MAAM;AAAA,EAGrD,IAAI,UAAU,WAAW,kBAAkB,QAAQ;AAAA,IACjD,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS;AAAA,EACb,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,IACzC,UAAU,UAAU,WAAW,CAAC,IAAI,kBAAkB,WAAW,CAAC;AAAA,EACpE;AAAA,EAEA,OAAO,WAAW;AAAA;AAOb,SAAS,qBAAqB,CACnC,SACA,QACA,WACQ;AAAA,EACR,MAAM,KAAK,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACpD,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,MAAM,YAAY,YAAY,eAAe,MAAM;AAAA,EAEnD,OAAO,KAAK,SAAS;AAAA;AAOhB,SAAS,qBAAqB,CACnC,SACA,QACA,QACA,mBAAmB,KACV;AAAA,EAET,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAC9B,MAAM,YAAY,MACf,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,GAC7B,MAAM,CAAC;AAAA,EACX,MAAM,YAAY,MACf,KAAK,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAC9B,MAAM,CAAC;AAAA,EAEX,IAAI,CAAC,aAAa,CAAC,WAAW;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,SAAS,WAAW,EAAE;AAAA,EACjC,IAAI,MAAM,EAAE,GAAG;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACxC,IAAI,KAAK,IAAI,MAAM,EAAE,IAAI,kBAAkB;AAAA,IACzC,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,OAAO,gBAAgB,eAAe,WAAW,MAAM;AAAA;",
8
- "debugId": "C5FB6F078225904664756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAMO,SAAS,cAAc,GAAW;AAAA,EACvC,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA;AAOhC,SAAS,WAAW,CAAC,SAAiB,QAAwB;AAAA,EACnE,MAAM,OAAO,WAAW,UAAU,MAAM;AAAA,EACxC,KAAK,OAAO,OAAO;AAAA,EACnB,OAAO,KAAK,OAAO,KAAK;AAAA;AAOnB,SAAS,eAAe,CAC7B,SACA,WACA,QACS;AAAA,EACT,MAAM,oBAAoB,YAAY,SAAS,MAAM;AAAA,EAGrD,IAAI,UAAU,WAAW,kBAAkB,QAAQ;AAAA,IACjD,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS;AAAA,EACb,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,IACzC,UAAU,UAAU,WAAW,CAAC,IAAI,kBAAkB,WAAW,CAAC;AAAA,EACpE;AAAA,EAEA,OAAO,WAAW;AAAA;AAOb,SAAS,qBAAqB,CACnC,SACA,QACA,WACQ;AAAA,EACR,MAAM,KAAK,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACpD,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,MAAM,YAAY,YAAY,eAAe,MAAM;AAAA,EAEnD,OAAO,KAAK,SAAS;AAAA;AAOhB,SAAS,qBAAqB,CACnC,SACA,QACA,QACA,mBAAmB,KACV;AAAA,EAET,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAC9B,MAAM,YAAY,MACf,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,GAC7B,MAAM,CAAC;AAAA,EACX,MAAM,YAAY,MACf,KAAK,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAC9B,MAAM,CAAC;AAAA,EAEX,IAAI,CAAC,aAAa,CAAC,WAAW;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,SAAS,WAAW,EAAE;AAAA,EACjC,IAAI,MAAM,EAAE,GAAG;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACxC,IAAI,KAAK,IAAI,MAAM,EAAE,IAAI,kBAAkB;AAAA,IACzC,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,OAAO,gBAAgB,eAAe,WAAW,MAAM;AAAA;",
8
+ "debugId": "A51CF8494ADEA11C64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -50,8 +50,8 @@ interface StreamsTable {
50
50
  status: Generated<string>;
51
51
  filters: unknown;
52
52
  options: Generated<unknown>;
53
- webhook_url: string;
54
- webhook_secret: string | null;
53
+ endpoint_url: string;
54
+ signing_secret: string | null;
55
55
  api_key_id: string | null;
56
56
  created_at: Generated<Date>;
57
57
  updated_at: Generated<Date>;
@@ -97,7 +97,7 @@ interface DeliveriesTable {
97
97
  payload: unknown;
98
98
  created_at: Generated<Date>;
99
99
  }
100
- interface ViewsTable {
100
+ interface SubgraphsTable {
101
101
  id: Generated<string>;
102
102
  name: string;
103
103
  version: Generated<string>;
@@ -165,6 +165,71 @@ interface UsageSnapshotsTable {
165
165
  measured_at: Generated<Date>;
166
166
  storage_bytes: Generated<number>;
167
167
  }
168
+ interface WaitlistTable {
169
+ id: Generated<string>;
170
+ email: string;
171
+ source: Generated<string>;
172
+ status: Generated<string>;
173
+ created_at: Generated<Date>;
174
+ }
175
+ interface AccountInsightsTable {
176
+ id: Generated<string>;
177
+ account_id: string;
178
+ category: string;
179
+ insight_type: string;
180
+ resource_id: string | null;
181
+ severity: string;
182
+ title: string;
183
+ body: string;
184
+ data: unknown;
185
+ dismissed_at: Date | null;
186
+ expires_at: Date | null;
187
+ created_at: Generated<Date>;
188
+ }
189
+ interface AccountAgentRunsTable {
190
+ id: Generated<string>;
191
+ account_id: string;
192
+ started_at: Generated<Date>;
193
+ completed_at: Date | null;
194
+ status: Generated<string>;
195
+ input_tokens: Generated<number>;
196
+ output_tokens: Generated<number>;
197
+ cost_usd: Generated<number>;
198
+ insights_created: Generated<number>;
199
+ error: string | null;
200
+ }
201
+ interface SubgraphProcessingStatsTable {
202
+ id: Generated<string>;
203
+ subgraph_name: string;
204
+ api_key_id: string | null;
205
+ bucket_start: Date | null;
206
+ bucket_end: Date | null;
207
+ blocks_processed: number | null;
208
+ total_time_ms: number | null;
209
+ handler_time_ms: number | null;
210
+ flush_time_ms: number | null;
211
+ max_block_time_ms: number | null;
212
+ max_handler_time_ms: number | null;
213
+ avg_ops_per_block: number | null;
214
+ is_catchup: Generated<boolean>;
215
+ created_at: Generated<Date>;
216
+ }
217
+ interface SubgraphTableSnapshotsTable {
218
+ id: Generated<string>;
219
+ subgraph_name: string;
220
+ api_key_id: string | null;
221
+ table_name: string;
222
+ row_count: number | null;
223
+ created_at: Generated<Date>;
224
+ }
225
+ interface SubgraphHealthSnapshotsTable {
226
+ id: Generated<string>;
227
+ subgraph_id: string;
228
+ total_processed: number;
229
+ total_errors: number;
230
+ last_processed_block: number | null;
231
+ captured_at: Generated<Date>;
232
+ }
168
233
  interface Database {
169
234
  blocks: BlocksTable;
170
235
  transactions: TransactionsTable;
@@ -174,13 +239,19 @@ interface Database {
174
239
  jobs: JobsTable;
175
240
  index_progress: IndexProgressTable;
176
241
  deliveries: DeliveriesTable;
177
- views: ViewsTable;
242
+ subgraphs: SubgraphsTable;
178
243
  api_keys: ApiKeysTable;
179
244
  accounts: AccountsTable;
180
245
  sessions: SessionsTable;
181
246
  magic_links: MagicLinksTable;
182
247
  usage_daily: UsageDailyTable;
183
248
  usage_snapshots: UsageSnapshotsTable;
249
+ waitlist: WaitlistTable;
250
+ account_insights: AccountInsightsTable;
251
+ account_agent_runs: AccountAgentRunsTable;
252
+ subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
253
+ subgraph_processing_stats: SubgraphProcessingStatsTable;
254
+ subgraph_table_snapshots: SubgraphTableSnapshotsTable;
184
255
  }
185
256
  type Block = Selectable<BlocksTable>;
186
257
  type InsertBlock = Insertable<BlocksTable>;
@@ -206,9 +277,9 @@ type UpdateIndexProgress = Updateable<IndexProgressTable>;
206
277
  type Delivery = Selectable<DeliveriesTable>;
207
278
  type InsertDelivery = Insertable<DeliveriesTable>;
208
279
  type UpdateDelivery = Updateable<DeliveriesTable>;
209
- type View = Selectable<ViewsTable>;
210
- type InsertView = Insertable<ViewsTable>;
211
- type UpdateView = Updateable<ViewsTable>;
280
+ type Subgraph = Selectable<SubgraphsTable>;
281
+ type InsertSubgraph = Insertable<SubgraphsTable>;
282
+ type UpdateSubgraph = Updateable<SubgraphsTable>;
212
283
  type ApiKey = Selectable<ApiKeysTable>;
213
284
  type InsertApiKey = Insertable<ApiKeysTable>;
214
285
  type UpdateApiKey = Updateable<ApiKeysTable>;
@@ -220,10 +291,16 @@ type Session = Selectable<SessionsTable>;
220
291
  type InsertSession = Insertable<SessionsTable>;
221
292
  type UsageDaily = Selectable<UsageDailyTable>;
222
293
  type UsageSnapshot = Selectable<UsageSnapshotsTable>;
294
+ type AccountInsight = Selectable<AccountInsightsTable>;
295
+ type InsertAccountInsight = Insertable<AccountInsightsTable>;
296
+ type AccountAgentRun = Selectable<AccountAgentRunsTable>;
297
+ type InsertAccountAgentRun = Insertable<AccountAgentRunsTable>;
298
+ type SubgraphHealthSnapshot = Selectable<SubgraphHealthSnapshotsTable>;
299
+ type InsertSubgraphHealthSnapshot = Insertable<SubgraphHealthSnapshotsTable>;
223
300
  import { sql } from "kysely";
224
301
  declare function getDb(connectionString?: string): Kysely<Database>;
225
302
  /** Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.) */
226
303
  declare function getRawClient(): ReturnType<typeof postgres>;
227
304
  /** Close the DB connection pool. Call in CLI commands to allow process exit. */
228
305
  declare function closeDb(): Promise<void>;
229
- export { sql, parseJsonb, jsonb, getRawClient, getDb, closeDb, ViewsTable, View, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateView, UpdateTransaction, UpdateStreamRow, UpdateStreamMetrics, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, StreamsTable, StreamMetricsTable, StreamMetrics, Stream, SessionsTable, Session, MagicLinksTable, MagicLink, JobsTable, Job, InsertView, InsertTransaction, InsertStreamMetrics, InsertStream, InsertSession, InsertMagicLink, InsertJob, InsertIndexProgress, InsertEvent, InsertDelivery, InsertBlock, InsertApiKey, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Delivery, DeliveriesTable, Database, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, Account };
306
+ export { sql, parseJsonb, jsonb, getRawClient, getDb, closeDb, 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 };
@@ -1,12 +1,16 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
 
@@ -71,5 +75,5 @@ export {
71
75
  closeDb
72
76
  };
73
77
 
74
- //# debugId=F675FEF083D960AD64756E2164756E21
78
+ //# debugId=0350F4EABDF4D64C64756E2164756E21
75
79
  //# sourceMappingURL=index.js.map
@@ -5,7 +5,7 @@
5
5
  "import { sql, type RawBuilder } from \"kysely\";\n\n/**\n * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.\n * Kysely + postgres.js double-encodes JSON when using parameterized queries\n * with ::jsonb casts. This uses sql.raw to inline a properly escaped literal.\n */\nexport function jsonb(value: unknown): RawBuilder<unknown> {\n const escaped = JSON.stringify(value).replace(/'/g, \"''\");\n return sql`${sql.raw(`'${escaped}'::jsonb`)}`;\n}\n\n/**\n * Safely parse a JSONB value from the database.\n * Handles double-encoded strings where postgres.js returns a JSON string\n * instead of a parsed object.\n */\nexport function parseJsonb<T = unknown>(value: unknown): T {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value) as T;\n } catch {\n return value as T;\n }\n }\n return (value ?? {}) as T;\n}\n",
6
6
  "import { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport type { Database } from \"./types.ts\";\n\nlet db: Kysely<Database> | null = null;\nlet rawClient: ReturnType<typeof postgres> | null = null;\n\nexport function getDb(connectionString?: string): Kysely<Database> {\n if (!db) {\n const url = connectionString || process.env.DATABASE_URL || \"postgres://postgres:postgres@localhost:5432/streams_dev\";\n\n // Always use SSL for remote databases, just disable cert verification if needed\n const isLocal = url.includes(\"localhost\") || url.includes(\"127.0.0.1\") || url.includes(\"@postgres:\");\n rawClient = postgres(url, {\n ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== \"0\" },\n });\n db = new Kysely<Database>({\n dialect: new PostgresJSDialect({ postgres: rawClient }),\n });\n }\n return db;\n}\n\n/** Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.) */\nexport function getRawClient(): ReturnType<typeof postgres> {\n if (!rawClient) getDb();\n return rawClient!;\n}\n\n/** Close the DB connection pool. Call in CLI commands to allow process exit. */\nexport async function closeDb(): Promise<void> {\n if (db) {\n await db.destroy();\n db = null;\n }\n if (rawClient) {\n await rawClient.end();\n rawClient = null;\n }\n}\n\nimport { sql } from \"kysely\";\nexport { sql };\nexport * from \"./types.ts\";\nexport { jsonb, parseJsonb } from \"./jsonb.ts\";\n"
7
7
  ],
8
- "mappings": ";;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EACzD,MAAM,UAAU,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA,EACxD,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQrC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EACzD,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI;AAAA,MACF,OAAO,KAAK,MAAM,KAAK;AAAA,MACvB,MAAM;AAAA,MACN,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;;;ACzBpB;AACA;AACA;AAwCA,gBAAS;AArCT,IAAI,KAA8B;AAClC,IAAI,YAAgD;AAE7C,SAAS,KAAK,CAAC,kBAA6C;AAAA,EACjE,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,MAAM,oBAAoB,QAAQ,IAAI,gBAAgB;AAAA,IAG5D,MAAM,UAAU,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,YAAY;AAAA,IACnG,YAAY,SAAS,KAAK;AAAA,MACxB,KAAK,UAAU,YAAY,EAAE,oBAAoB,QAAQ,IAAI,iCAAiC,IAAI;AAAA,IACpG,CAAC;AAAA,IACD,KAAK,IAAI,OAAiB;AAAA,MACxB,SAAS,IAAI,kBAAkB,EAAE,UAAU,UAAU,CAAC;AAAA,IACxD,CAAC;AAAA,EACH;AAAA,EACA,OAAO;AAAA;AAIF,SAAS,YAAY,GAAgC;AAAA,EAC1D,IAAI,CAAC;AAAA,IAAW,MAAM;AAAA,EACtB,OAAO;AAAA;AAIT,eAAsB,OAAO,GAAkB;AAAA,EAC7C,IAAI,IAAI;AAAA,IACN,MAAM,GAAG,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA,IAAI,WAAW;AAAA,IACb,MAAM,UAAU,IAAI;AAAA,IACpB,YAAY;AAAA,EACd;AAAA;",
9
- "debugId": "F675FEF083D960AD64756E2164756E21",
8
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EACzD,MAAM,UAAU,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA,EACxD,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQrC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EACzD,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI;AAAA,MACF,OAAO,KAAK,MAAM,KAAK;AAAA,MACvB,MAAM;AAAA,MACN,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;;;ACzBpB;AACA;AACA;AAwCA,gBAAS;AArCT,IAAI,KAA8B;AAClC,IAAI,YAAgD;AAE7C,SAAS,KAAK,CAAC,kBAA6C;AAAA,EACjE,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,MAAM,oBAAoB,QAAQ,IAAI,gBAAgB;AAAA,IAG5D,MAAM,UAAU,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,YAAY;AAAA,IACnG,YAAY,SAAS,KAAK;AAAA,MACxB,KAAK,UAAU,YAAY,EAAE,oBAAoB,QAAQ,IAAI,iCAAiC,IAAI;AAAA,IACpG,CAAC;AAAA,IACD,KAAK,IAAI,OAAiB;AAAA,MACxB,SAAS,IAAI,kBAAkB,EAAE,UAAU,UAAU,CAAC;AAAA,IACxD,CAAC;AAAA,EACH;AAAA,EACA,OAAO;AAAA;AAIF,SAAS,YAAY,GAAgC;AAAA,EAC1D,IAAI,CAAC;AAAA,IAAW,MAAM;AAAA,EACtB,OAAO;AAAA;AAIT,eAAsB,OAAO,GAAkB;AAAA,EAC7C,IAAI,IAAI;AAAA,IACN,MAAM,GAAG,QAAQ;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA,IAAI,WAAW;AAAA,IACb,MAAM,UAAU,IAAI;AAAA,IACpB,YAAY;AAAA,EACd;AAAA;",
9
+ "debugId": "0350F4EABDF4D64C64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -1,12 +1,16 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
 
@@ -31,5 +35,5 @@ export {
31
35
  jsonb
32
36
  };
33
37
 
34
- //# debugId=FD7B2A33BAF805D564756E2164756E21
38
+ //# debugId=A6577D9BF54F45FE64756E2164756E21
35
39
  //# sourceMappingURL=jsonb.js.map
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "import { sql, type RawBuilder } from \"kysely\";\n\n/**\n * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.\n * Kysely + postgres.js double-encodes JSON when using parameterized queries\n * with ::jsonb casts. This uses sql.raw to inline a properly escaped literal.\n */\nexport function jsonb(value: unknown): RawBuilder<unknown> {\n const escaped = JSON.stringify(value).replace(/'/g, \"''\");\n return sql`${sql.raw(`'${escaped}'::jsonb`)}`;\n}\n\n/**\n * Safely parse a JSONB value from the database.\n * Handles double-encoded strings where postgres.js returns a JSON string\n * instead of a parsed object.\n */\nexport function parseJsonb<T = unknown>(value: unknown): T {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value) as T;\n } catch {\n return value as T;\n }\n }\n return (value ?? {}) as T;\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EACzD,MAAM,UAAU,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA,EACxD,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQrC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EACzD,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI;AAAA,MACF,OAAO,KAAK,MAAM,KAAK;AAAA,MACvB,MAAM;AAAA,MACN,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;",
8
- "debugId": "FD7B2A33BAF805D564756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EACzD,MAAM,UAAU,KAAK,UAAU,KAAK,EAAE,QAAQ,MAAM,IAAI;AAAA,EACxD,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQrC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EACzD,IAAI,OAAO,UAAU,UAAU;AAAA,IAC7B,IAAI;AAAA,MACF,OAAO,KAAK,MAAM,KAAK;AAAA,MACvB,MAAM;AAAA,MACN,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;",
8
+ "debugId": "A6577D9BF54F45FE64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -36,8 +36,8 @@ interface StreamsTable {
36
36
  status: Generated<string>;
37
37
  filters: unknown;
38
38
  options: Generated<unknown>;
39
- webhook_url: string;
40
- webhook_secret: string | null;
39
+ endpoint_url: string;
40
+ signing_secret: string | null;
41
41
  api_key_id: string | null;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
@@ -83,7 +83,7 @@ interface DeliveriesTable {
83
83
  payload: unknown;
84
84
  created_at: Generated<Date>;
85
85
  }
86
- interface ViewsTable {
86
+ interface SubgraphsTable {
87
87
  id: Generated<string>;
88
88
  name: string;
89
89
  version: Generated<string>;
@@ -151,6 +151,71 @@ interface UsageSnapshotsTable {
151
151
  measured_at: Generated<Date>;
152
152
  storage_bytes: Generated<number>;
153
153
  }
154
+ interface WaitlistTable {
155
+ id: Generated<string>;
156
+ email: string;
157
+ source: Generated<string>;
158
+ status: Generated<string>;
159
+ created_at: Generated<Date>;
160
+ }
161
+ interface AccountInsightsTable {
162
+ id: Generated<string>;
163
+ account_id: string;
164
+ category: string;
165
+ insight_type: string;
166
+ resource_id: string | null;
167
+ severity: string;
168
+ title: string;
169
+ body: string;
170
+ data: unknown;
171
+ dismissed_at: Date | null;
172
+ expires_at: Date | null;
173
+ created_at: Generated<Date>;
174
+ }
175
+ interface AccountAgentRunsTable {
176
+ id: Generated<string>;
177
+ account_id: string;
178
+ started_at: Generated<Date>;
179
+ completed_at: Date | null;
180
+ status: Generated<string>;
181
+ input_tokens: Generated<number>;
182
+ output_tokens: Generated<number>;
183
+ cost_usd: Generated<number>;
184
+ insights_created: Generated<number>;
185
+ error: string | null;
186
+ }
187
+ interface SubgraphProcessingStatsTable {
188
+ id: Generated<string>;
189
+ subgraph_name: string;
190
+ api_key_id: string | null;
191
+ bucket_start: Date | null;
192
+ bucket_end: Date | null;
193
+ blocks_processed: number | null;
194
+ total_time_ms: number | null;
195
+ handler_time_ms: number | null;
196
+ flush_time_ms: number | null;
197
+ max_block_time_ms: number | null;
198
+ max_handler_time_ms: number | null;
199
+ avg_ops_per_block: number | null;
200
+ is_catchup: Generated<boolean>;
201
+ created_at: Generated<Date>;
202
+ }
203
+ interface SubgraphTableSnapshotsTable {
204
+ id: Generated<string>;
205
+ subgraph_name: string;
206
+ api_key_id: string | null;
207
+ table_name: string;
208
+ row_count: number | null;
209
+ created_at: Generated<Date>;
210
+ }
211
+ interface SubgraphHealthSnapshotsTable {
212
+ id: Generated<string>;
213
+ subgraph_id: string;
214
+ total_processed: number;
215
+ total_errors: number;
216
+ last_processed_block: number | null;
217
+ captured_at: Generated<Date>;
218
+ }
154
219
  interface Database {
155
220
  blocks: BlocksTable;
156
221
  transactions: TransactionsTable;
@@ -160,21 +225,28 @@ interface Database {
160
225
  jobs: JobsTable;
161
226
  index_progress: IndexProgressTable;
162
227
  deliveries: DeliveriesTable;
163
- views: ViewsTable;
228
+ subgraphs: SubgraphsTable;
164
229
  api_keys: ApiKeysTable;
165
230
  accounts: AccountsTable;
166
231
  sessions: SessionsTable;
167
232
  magic_links: MagicLinksTable;
168
233
  usage_daily: UsageDailyTable;
169
234
  usage_snapshots: UsageSnapshotsTable;
235
+ waitlist: WaitlistTable;
236
+ account_insights: AccountInsightsTable;
237
+ account_agent_runs: AccountAgentRunsTable;
238
+ subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
239
+ subgraph_processing_stats: SubgraphProcessingStatsTable;
240
+ subgraph_table_snapshots: SubgraphTableSnapshotsTable;
170
241
  }
171
242
  type Account = Selectable<AccountsTable>;
172
243
  declare function upsertAccount(db: Kysely<Database>, email: string): Promise<Account>;
173
244
  declare function getAccountById(db: Kysely<Database>, id: string): Promise<Account | null>;
245
+ declare function isEmailAllowed(db: Kysely<Database>, email: string): Promise<boolean>;
174
246
  declare function createMagicLink(db: Kysely<Database>, email: string, token: string, expiresInMs?: number): Promise<void>;
175
247
  /**
176
248
  * Verify a magic link token. Returns the email if valid, null otherwise.
177
249
  * Marks the token as used atomically.
178
250
  */
179
251
  declare function verifyMagicLink(db: Kysely<Database>, token: string): Promise<string | null>;
180
- export { verifyMagicLink, upsertAccount, getAccountById, createMagicLink };
252
+ export { verifyMagicLink, upsertAccount, isEmailAllowed, getAccountById, createMagicLink };
@@ -1,22 +1,36 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
 
13
17
  // src/db/queries/accounts.ts
18
+ import { sql } from "kysely";
14
19
  async function upsertAccount(db, email) {
15
20
  return await db.insertInto("accounts").values({ email }).onConflict((oc) => oc.column("email").doUpdateSet({ email })).returningAll().executeTakeFirstOrThrow();
16
21
  }
17
22
  async function getAccountById(db, id) {
18
23
  return await db.selectFrom("accounts").selectAll().where("id", "=", id).executeTakeFirst() ?? null;
19
24
  }
25
+ async function isEmailAllowed(db, email) {
26
+ const result = await sql`
27
+ SELECT 1 AS found FROM accounts WHERE email = ${email}
28
+ UNION ALL
29
+ SELECT 1 AS found FROM waitlist WHERE email = ${email} AND status = 'approved'
30
+ LIMIT 1
31
+ `.execute(db);
32
+ return result.rows.length > 0;
33
+ }
20
34
  async function createMagicLink(db, email, token, expiresInMs = 15 * 60 * 1000) {
21
35
  await db.insertInto("magic_links").values({
22
36
  email,
@@ -31,9 +45,10 @@ async function verifyMagicLink(db, token) {
31
45
  export {
32
46
  verifyMagicLink,
33
47
  upsertAccount,
48
+ isEmailAllowed,
34
49
  getAccountById,
35
50
  createMagicLink
36
51
  };
37
52
 
38
- //# debugId=BF026A17168292E864756E2164756E21
53
+ //# debugId=F1197D197EF2B0A364756E2164756E21
39
54
  //# sourceMappingURL=accounts.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/queries/accounts.ts"],
4
4
  "sourcesContent": [
5
- "import type { Kysely } from \"kysely\";\nimport type { Database, Account } from \"../types.ts\";\n\nexport async function upsertAccount(\n db: Kysely<Database>,\n email: string,\n): Promise<Account> {\n return await db\n .insertInto(\"accounts\")\n .values({ email })\n .onConflict((oc) =>\n oc.column(\"email\").doUpdateSet({ email }), // no-op update to return existing\n )\n .returningAll()\n .executeTakeFirstOrThrow();\n}\n\nexport async function getAccountById(\n db: Kysely<Database>,\n id: string,\n): Promise<Account | null> {\n return (\n (await db\n .selectFrom(\"accounts\")\n .selectAll()\n .where(\"id\", \"=\", id)\n .executeTakeFirst()) ?? null\n );\n}\n\nexport async function createMagicLink(\n db: Kysely<Database>,\n email: string,\n token: string,\n expiresInMs: number = 15 * 60 * 1000,\n): Promise<void> {\n await db\n .insertInto(\"magic_links\")\n .values({\n email,\n token,\n expires_at: new Date(Date.now() + expiresInMs),\n })\n .execute();\n}\n\n/**\n * Verify a magic link token. Returns the email if valid, null otherwise.\n * Marks the token as used atomically.\n */\nexport async function verifyMagicLink(\n db: Kysely<Database>,\n token: string,\n): Promise<string | null> {\n const result = await db\n .updateTable(\"magic_links\")\n .set({ used_at: new Date() })\n .where(\"token\", \"=\", token)\n .where(\"used_at\", \"is\", null)\n .where(\"expires_at\", \">\", new Date())\n .returning(\"email\")\n .executeTakeFirst();\n\n return result?.email ?? null;\n}\n"
5
+ "import { sql, type Kysely } from \"kysely\";\nimport type { Database, Account } from \"../types.ts\";\n\nexport async function upsertAccount(\n db: Kysely<Database>,\n email: string,\n): Promise<Account> {\n return await db\n .insertInto(\"accounts\")\n .values({ email })\n .onConflict((oc) =>\n oc.column(\"email\").doUpdateSet({ email }), // no-op update to return existing\n )\n .returningAll()\n .executeTakeFirstOrThrow();\n}\n\nexport async function getAccountById(\n db: Kysely<Database>,\n id: string,\n): Promise<Account | null> {\n return (\n (await db\n .selectFrom(\"accounts\")\n .selectAll()\n .where(\"id\", \"=\", id)\n .executeTakeFirst()) ?? null\n );\n}\n\nexport async function isEmailAllowed(\n db: Kysely<Database>,\n email: string,\n): Promise<boolean> {\n const result = await sql<{ found: number }>`\n SELECT 1 AS found FROM accounts WHERE email = ${email}\n UNION ALL\n SELECT 1 AS found FROM waitlist WHERE email = ${email} AND status = 'approved'\n LIMIT 1\n `.execute(db);\n\n return result.rows.length > 0;\n}\n\nexport async function createMagicLink(\n db: Kysely<Database>,\n email: string,\n token: string,\n expiresInMs: number = 15 * 60 * 1000,\n): Promise<void> {\n await db\n .insertInto(\"magic_links\")\n .values({\n email,\n token,\n expires_at: new Date(Date.now() + expiresInMs),\n })\n .execute();\n}\n\n/**\n * Verify a magic link token. Returns the email if valid, null otherwise.\n * Marks the token as used atomically.\n */\nexport async function verifyMagicLink(\n db: Kysely<Database>,\n token: string,\n): Promise<string | null> {\n const result = await db\n .updateTable(\"magic_links\")\n .set({ used_at: new Date() })\n .where(\"token\", \"=\", token)\n .where(\"used_at\", \"is\", null)\n .where(\"expires_at\", \">\", new Date())\n .returning(\"email\")\n .executeTakeFirst();\n\n return result?.email ?? null;\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;AAGA,eAAsB,aAAa,CACjC,IACA,OACkB;AAAA,EAClB,OAAO,MAAM,GACV,WAAW,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,EAChB,WAAW,CAAC,OACX,GAAG,OAAO,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,CAC1C,EACC,aAAa,EACb,wBAAwB;AAAA;AAG7B,eAAsB,cAAc,CAClC,IACA,IACyB;AAAA,EACzB,OACG,MAAM,GACJ,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,MAAM,KAAK,EAAE,EACnB,iBAAiB,KAAM;AAAA;AAI9B,eAAsB,eAAe,CACnC,IACA,OACA,OACA,cAAsB,KAAK,KAAK,MACjB;AAAA,EACf,MAAM,GACH,WAAW,aAAa,EACxB,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,WAAW;AAAA,EAC/C,CAAC,EACA,QAAQ;AAAA;AAOb,eAAsB,eAAe,CACnC,IACA,OACwB;AAAA,EACxB,MAAM,SAAS,MAAM,GAClB,YAAY,aAAa,EACzB,IAAI,EAAE,SAAS,IAAI,KAAO,CAAC,EAC3B,MAAM,SAAS,KAAK,KAAK,EACzB,MAAM,WAAW,MAAM,IAAI,EAC3B,MAAM,cAAc,KAAK,IAAI,IAAM,EACnC,UAAU,OAAO,EACjB,iBAAiB;AAAA,EAEpB,OAAO,QAAQ,SAAS;AAAA;",
8
- "debugId": "BF026A17168292E864756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAGA,eAAsB,aAAa,CACjC,IACA,OACkB;AAAA,EAClB,OAAO,MAAM,GACV,WAAW,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,EAChB,WAAW,CAAC,OACX,GAAG,OAAO,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,CAC1C,EACC,aAAa,EACb,wBAAwB;AAAA;AAG7B,eAAsB,cAAc,CAClC,IACA,IACyB;AAAA,EACzB,OACG,MAAM,GACJ,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,MAAM,KAAK,EAAE,EACnB,iBAAiB,KAAM;AAAA;AAI9B,eAAsB,cAAc,CAClC,IACA,OACkB;AAAA,EAClB,MAAM,SAAS,MAAM;AAAA,oDAC6B;AAAA;AAAA,oDAEA;AAAA;AAAA,IAEhD,QAAQ,EAAE;AAAA,EAEZ,OAAO,OAAO,KAAK,SAAS;AAAA;AAG9B,eAAsB,eAAe,CACnC,IACA,OACA,OACA,cAAsB,KAAK,KAAK,MACjB;AAAA,EACf,MAAM,GACH,WAAW,aAAa,EACxB,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,WAAW;AAAA,EAC/C,CAAC,EACA,QAAQ;AAAA;AAOb,eAAsB,eAAe,CACnC,IACA,OACwB;AAAA,EACxB,MAAM,SAAS,MAAM,GAClB,YAAY,aAAa,EACzB,IAAI,EAAE,SAAS,IAAI,KAAO,CAAC,EAC3B,MAAM,SAAS,KAAK,KAAK,EACzB,MAAM,WAAW,MAAM,IAAI,EAC3B,MAAM,cAAc,KAAK,IAAI,IAAM,EACnC,UAAU,OAAO,EACjB,iBAAiB;AAAA,EAEpB,OAAO,QAAQ,SAAS;AAAA;",
8
+ "debugId": "F1197D197EF2B0A364756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -36,8 +36,8 @@ interface StreamsTable {
36
36
  status: Generated<string>;
37
37
  filters: unknown;
38
38
  options: Generated<unknown>;
39
- webhook_url: string;
40
- webhook_secret: string | null;
39
+ endpoint_url: string;
40
+ signing_secret: string | null;
41
41
  api_key_id: string | null;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
@@ -83,7 +83,7 @@ interface DeliveriesTable {
83
83
  payload: unknown;
84
84
  created_at: Generated<Date>;
85
85
  }
86
- interface ViewsTable {
86
+ interface SubgraphsTable {
87
87
  id: Generated<string>;
88
88
  name: string;
89
89
  version: Generated<string>;
@@ -151,6 +151,71 @@ interface UsageSnapshotsTable {
151
151
  measured_at: Generated<Date>;
152
152
  storage_bytes: Generated<number>;
153
153
  }
154
+ interface WaitlistTable {
155
+ id: Generated<string>;
156
+ email: string;
157
+ source: Generated<string>;
158
+ status: Generated<string>;
159
+ created_at: Generated<Date>;
160
+ }
161
+ interface AccountInsightsTable {
162
+ id: Generated<string>;
163
+ account_id: string;
164
+ category: string;
165
+ insight_type: string;
166
+ resource_id: string | null;
167
+ severity: string;
168
+ title: string;
169
+ body: string;
170
+ data: unknown;
171
+ dismissed_at: Date | null;
172
+ expires_at: Date | null;
173
+ created_at: Generated<Date>;
174
+ }
175
+ interface AccountAgentRunsTable {
176
+ id: Generated<string>;
177
+ account_id: string;
178
+ started_at: Generated<Date>;
179
+ completed_at: Date | null;
180
+ status: Generated<string>;
181
+ input_tokens: Generated<number>;
182
+ output_tokens: Generated<number>;
183
+ cost_usd: Generated<number>;
184
+ insights_created: Generated<number>;
185
+ error: string | null;
186
+ }
187
+ interface SubgraphProcessingStatsTable {
188
+ id: Generated<string>;
189
+ subgraph_name: string;
190
+ api_key_id: string | null;
191
+ bucket_start: Date | null;
192
+ bucket_end: Date | null;
193
+ blocks_processed: number | null;
194
+ total_time_ms: number | null;
195
+ handler_time_ms: number | null;
196
+ flush_time_ms: number | null;
197
+ max_block_time_ms: number | null;
198
+ max_handler_time_ms: number | null;
199
+ avg_ops_per_block: number | null;
200
+ is_catchup: Generated<boolean>;
201
+ created_at: Generated<Date>;
202
+ }
203
+ interface SubgraphTableSnapshotsTable {
204
+ id: Generated<string>;
205
+ subgraph_name: string;
206
+ api_key_id: string | null;
207
+ table_name: string;
208
+ row_count: number | null;
209
+ created_at: Generated<Date>;
210
+ }
211
+ interface SubgraphHealthSnapshotsTable {
212
+ id: Generated<string>;
213
+ subgraph_id: string;
214
+ total_processed: number;
215
+ total_errors: number;
216
+ last_processed_block: number | null;
217
+ captured_at: Generated<Date>;
218
+ }
154
219
  interface Database {
155
220
  blocks: BlocksTable;
156
221
  transactions: TransactionsTable;
@@ -160,13 +225,19 @@ interface Database {
160
225
  jobs: JobsTable;
161
226
  index_progress: IndexProgressTable;
162
227
  deliveries: DeliveriesTable;
163
- views: ViewsTable;
228
+ subgraphs: SubgraphsTable;
164
229
  api_keys: ApiKeysTable;
165
230
  accounts: AccountsTable;
166
231
  sessions: SessionsTable;
167
232
  magic_links: MagicLinksTable;
168
233
  usage_daily: UsageDailyTable;
169
234
  usage_snapshots: UsageSnapshotsTable;
235
+ waitlist: WaitlistTable;
236
+ account_insights: AccountInsightsTable;
237
+ account_agent_runs: AccountAgentRunsTable;
238
+ subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
239
+ subgraph_processing_stats: SubgraphProcessingStatsTable;
240
+ subgraph_table_snapshots: SubgraphTableSnapshotsTable;
170
241
  }
171
242
  interface Gap {
172
243
  gapStart: number;
@@ -1,12 +1,16 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
 
@@ -64,5 +68,5 @@ export {
64
68
  computeContiguousTip
65
69
  };
66
70
 
67
- //# debugId=370F0F5D6FDDF61064756E2164756E21
71
+ //# debugId=C8E32B40B73BEACD64756E2164756E21
68
72
  //# sourceMappingURL=integrity.js.map
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "import { sql, type Kysely } from \"kysely\";\nimport type { Database } from \"../types.ts\";\n\nexport interface Gap {\n gapStart: number;\n gapEnd: number;\n size: number;\n}\n\nexport async function findGaps(db: Kysely<Database>, limit?: number): Promise<Gap[]> {\n const limitClause = limit ? sql`LIMIT ${limit}` : sql``;\n const { rows } = await sql<{ gap_start: string; gap_end: string; size: string }>`\n SELECT gap_start, gap_end, gap_end - gap_start + 1 AS size\n FROM (\n SELECT height + 1 AS gap_start, next_height - 1 AS gap_end\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n ) gaps\n ORDER BY gap_start\n ${limitClause}\n `.execute(db);\n\n return rows.map((r) => ({\n gapStart: Number(r.gap_start),\n gapEnd: Number(r.gap_end),\n size: Number(r.size),\n }));\n}\n\nexport async function countMissingBlocks(db: Kysely<Database>): Promise<number> {\n const { rows } = await sql<{ total: string }>`\n SELECT COALESCE(SUM(next_height - height - 1), 0) AS total\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n `.execute(db);\n\n return Number(rows[0]?.total ?? 0);\n}\n\nexport async function computeContiguousTip(db: Kysely<Database>, fromHeight: number): Promise<number> {\n const { rows } = await sql<{ tip: string }>`\n SELECT COALESCE(MAX(height), ${fromHeight}) AS tip\n FROM (\n SELECT height, height - ROW_NUMBER() OVER (ORDER BY height) AS grp\n FROM blocks WHERE canonical = true AND height >= ${fromHeight}\n ) sub\n WHERE grp = (\n SELECT height - ROW_NUMBER() OVER (ORDER BY height)\n FROM blocks WHERE canonical = true AND height = ${fromHeight}\n )\n `.execute(db);\n\n return Number(rows[0]?.tip ?? fromHeight);\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;AAAA;AASA,eAAsB,QAAQ,CAAC,IAAsB,OAAgC;AAAA,EACnF,MAAM,cAAc,QAAQ,YAAY,UAAU;AAAA,EAClD,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWnB;AAAA,IACF,QAAQ,EAAE;AAAA,EAEZ,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,UAAU,OAAO,EAAE,SAAS;AAAA,IAC5B,QAAQ,OAAO,EAAE,OAAO;AAAA,IACxB,MAAM,OAAO,EAAE,IAAI;AAAA,EACrB,EAAE;AAAA;AAGJ,eAAsB,kBAAkB,CAAC,IAAuC;AAAA,EAC9E,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOrB,QAAQ,EAAE;AAAA,EAEZ,OAAO,OAAO,KAAK,IAAI,SAAS,CAAC;AAAA;AAGnC,eAAsB,oBAAoB,CAAC,IAAsB,YAAqC;AAAA,EACpG,QAAQ,SAAS,MAAM;AAAA,mCACU;AAAA;AAAA;AAAA,yDAGsB;AAAA;AAAA;AAAA;AAAA,wDAID;AAAA;AAAA,IAEpD,QAAQ,EAAE;AAAA,EAEZ,OAAO,OAAO,KAAK,IAAI,OAAO,UAAU;AAAA;",
8
- "debugId": "370F0F5D6FDDF61064756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AASA,eAAsB,QAAQ,CAAC,IAAsB,OAAgC;AAAA,EACnF,MAAM,cAAc,QAAQ,YAAY,UAAU;AAAA,EAClD,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWnB;AAAA,IACF,QAAQ,EAAE;AAAA,EAEZ,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,UAAU,OAAO,EAAE,SAAS;AAAA,IAC5B,QAAQ,OAAO,EAAE,OAAO;AAAA,IACxB,MAAM,OAAO,EAAE,IAAI;AAAA,EACrB,EAAE;AAAA;AAGJ,eAAsB,kBAAkB,CAAC,IAAuC;AAAA,EAC9E,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOrB,QAAQ,EAAE;AAAA,EAEZ,OAAO,OAAO,KAAK,IAAI,SAAS,CAAC;AAAA;AAGnC,eAAsB,oBAAoB,CAAC,IAAsB,YAAqC;AAAA,EACpG,QAAQ,SAAS,MAAM;AAAA,mCACU;AAAA;AAAA;AAAA,yDAGsB;AAAA;AAAA;AAAA;AAAA,wDAID;AAAA;AAAA,IAEpD,QAAQ,EAAE;AAAA,EAEZ,OAAO,OAAO,KAAK,IAAI,OAAO,UAAU;AAAA;",
8
+ "debugId": "C8E32B40B73BEACD64756E2164756E21",
9
9
  "names": []
10
10
  }