@secondlayer/shared 0.7.0 → 0.7.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.
@@ -52,7 +52,7 @@ interface StreamsTable {
52
52
  options: Generated<unknown>;
53
53
  endpoint_url: string;
54
54
  signing_secret: string | null;
55
- api_key_id: string | null;
55
+ api_key_id: string;
56
56
  created_at: Generated<Date>;
57
57
  updated_at: Generated<Date>;
58
58
  }
@@ -111,7 +111,7 @@ interface SubgraphsTable {
111
111
  last_error_at: Date | null;
112
112
  total_processed: Generated<number>;
113
113
  total_errors: Generated<number>;
114
- api_key_id: string | null;
114
+ api_key_id: string;
115
115
  created_at: Generated<Date>;
116
116
  updated_at: Generated<Date>;
117
117
  }
@@ -151,6 +151,7 @@ interface MagicLinksTable {
151
151
  token: string;
152
152
  expires_at: Date;
153
153
  used_at: Date | null;
154
+ failed_attempts: Generated<number>;
154
155
  created_at: Generated<Date>;
155
156
  }
156
157
  interface UsageDailyTable {
@@ -42,7 +42,9 @@ function getDb(connectionString) {
42
42
  if (!db) {
43
43
  const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/streams_dev";
44
44
  const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || url.includes("@postgres:");
45
+ const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
45
46
  rawClient = postgres(url, {
47
+ max: poolMax,
46
48
  ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" }
47
49
  });
48
50
  db = new Kysely({
@@ -75,5 +77,5 @@ export {
75
77
  closeDb
76
78
  };
77
79
 
78
- //# debugId=0350F4EABDF4D64C64756E2164756E21
80
+ //# debugId=EDB0A373449368CA64756E2164756E21
79
81
  //# sourceMappingURL=index.js.map
@@ -3,9 +3,9 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/index.ts"],
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
- "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"
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 const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n rawClient = postgres(url, {\n max: poolMax,\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": "0350F4EABDF4D64C64756E2164756E21",
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;AA0CA,gBAAS;AAvCT,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,MAAM,UAAU,SAAS,QAAQ,IAAI,qBAAqB,MAAM,EAAE;AAAA,IAClE,YAAY,SAAS,KAAK;AAAA,MACxB,KAAK;AAAA,MACL,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": "EDB0A373449368CA64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -38,7 +38,7 @@ interface StreamsTable {
38
38
  options: Generated<unknown>;
39
39
  endpoint_url: string;
40
40
  signing_secret: string | null;
41
- api_key_id: string | null;
41
+ api_key_id: string;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
44
44
  }
@@ -97,7 +97,7 @@ interface SubgraphsTable {
97
97
  last_error_at: Date | null;
98
98
  total_processed: Generated<number>;
99
99
  total_errors: Generated<number>;
100
- api_key_id: string | null;
100
+ api_key_id: string;
101
101
  created_at: Generated<Date>;
102
102
  updated_at: Generated<Date>;
103
103
  }
@@ -137,6 +137,7 @@ interface MagicLinksTable {
137
137
  token: string;
138
138
  expires_at: Date;
139
139
  used_at: Date | null;
140
+ failed_attempts: Generated<number>;
140
141
  created_at: Generated<Date>;
141
142
  }
142
143
  interface UsageDailyTable {
@@ -246,7 +247,7 @@ declare function isEmailAllowed(db: Kysely<Database>, email: string): Promise<bo
246
247
  declare function createMagicLink(db: Kysely<Database>, email: string, token: string, expiresInMs?: number): Promise<void>;
247
248
  /**
248
249
  * Verify a magic link token. Returns the email if valid, null otherwise.
249
- * Marks the token as used atomically.
250
+ * Marks the token as used atomically. Rejects after 5 failed attempts.
250
251
  */
251
252
  declare function verifyMagicLink(db: Kysely<Database>, token: string): Promise<string | null>;
252
253
  export { verifyMagicLink, upsertAccount, isEmailAllowed, getAccountById, createMagicLink };
@@ -39,8 +39,11 @@ async function createMagicLink(db, email, token, expiresInMs = 15 * 60 * 1000) {
39
39
  }).execute();
40
40
  }
41
41
  async function verifyMagicLink(db, token) {
42
- const result = await db.updateTable("magic_links").set({ used_at: new Date }).where("token", "=", token).where("used_at", "is", null).where("expires_at", ">", new Date).returning("email").executeTakeFirst();
43
- return result?.email ?? null;
42
+ const result = await db.updateTable("magic_links").set({ used_at: new Date }).where("token", "=", token).where("used_at", "is", null).where("expires_at", ">", new Date).where("failed_attempts", "<", 5).returning("email").executeTakeFirst();
43
+ if (result?.email)
44
+ return result.email;
45
+ await db.updateTable("magic_links").set({ failed_attempts: sql`failed_attempts + 1` }).where("token", "=", token).where("used_at", "is", null).where("expires_at", ">", new Date).execute();
46
+ return null;
44
47
  }
45
48
  export {
46
49
  verifyMagicLink,
@@ -50,5 +53,5 @@ export {
50
53
  createMagicLink
51
54
  };
52
55
 
53
- //# debugId=F1197D197EF2B0A364756E2164756E21
56
+ //# debugId=20A55F621EB14D5064756E2164756E21
54
57
  //# 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 { 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"
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. Rejects after 5 failed attempts.\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 .where(\"failed_attempts\", \"<\", 5)\n .returning(\"email\")\n .executeTakeFirst();\n\n if (result?.email) return result.email;\n\n // Increment failed attempts if token exists but didn't verify\n await db\n .updateTable(\"magic_links\")\n .set({ failed_attempts: sql`failed_attempts + 1` })\n .where(\"token\", \"=\", token)\n .where(\"used_at\", \"is\", null)\n .where(\"expires_at\", \">\", new Date())\n .execute();\n\n return null;\n}\n"
6
6
  ],
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",
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,MAAM,mBAAmB,KAAK,CAAC,EAC/B,UAAU,OAAO,EACjB,iBAAiB;AAAA,EAEpB,IAAI,QAAQ;AAAA,IAAO,OAAO,OAAO;AAAA,EAGjC,MAAM,GACH,YAAY,aAAa,EACzB,IAAI,EAAE,iBAAiB,yBAAyB,CAAC,EACjD,MAAM,SAAS,KAAK,KAAK,EACzB,MAAM,WAAW,MAAM,IAAI,EAC3B,MAAM,cAAc,KAAK,IAAI,IAAM,EACnC,QAAQ;AAAA,EAEX,OAAO;AAAA;",
8
+ "debugId": "20A55F621EB14D5064756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -38,7 +38,7 @@ interface StreamsTable {
38
38
  options: Generated<unknown>;
39
39
  endpoint_url: string;
40
40
  signing_secret: string | null;
41
- api_key_id: string | null;
41
+ api_key_id: string;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
44
44
  }
@@ -97,7 +97,7 @@ interface SubgraphsTable {
97
97
  last_error_at: Date | null;
98
98
  total_processed: Generated<number>;
99
99
  total_errors: Generated<number>;
100
- api_key_id: string | null;
100
+ api_key_id: string;
101
101
  created_at: Generated<Date>;
102
102
  updated_at: Generated<Date>;
103
103
  }
@@ -137,6 +137,7 @@ interface MagicLinksTable {
137
137
  token: string;
138
138
  expires_at: Date;
139
139
  used_at: Date | null;
140
+ failed_attempts: Generated<number>;
140
141
  created_at: Generated<Date>;
141
142
  }
142
143
  interface UsageDailyTable {
@@ -38,7 +38,7 @@ interface StreamsTable {
38
38
  options: Generated<unknown>;
39
39
  endpoint_url: string;
40
40
  signing_secret: string | null;
41
- api_key_id: string | null;
41
+ api_key_id: string;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
44
44
  }
@@ -97,7 +97,7 @@ interface SubgraphsTable {
97
97
  last_error_at: Date | null;
98
98
  total_processed: Generated<number>;
99
99
  total_errors: Generated<number>;
100
- api_key_id: string | null;
100
+ api_key_id: string;
101
101
  created_at: Generated<Date>;
102
102
  updated_at: Generated<Date>;
103
103
  }
@@ -137,6 +137,7 @@ interface MagicLinksTable {
137
137
  token: string;
138
138
  expires_at: Date;
139
139
  used_at: Date | null;
140
+ failed_attempts: Generated<number>;
140
141
  created_at: Generated<Date>;
141
142
  }
142
143
  interface UsageDailyTable {
@@ -38,7 +38,7 @@ interface StreamsTable {
38
38
  options: Generated<unknown>;
39
39
  endpoint_url: string;
40
40
  signing_secret: string | null;
41
- api_key_id: string | null;
41
+ api_key_id: string;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
44
44
  }
@@ -97,7 +97,7 @@ interface SubgraphsTable {
97
97
  last_error_at: Date | null;
98
98
  total_processed: Generated<number>;
99
99
  total_errors: Generated<number>;
100
- api_key_id: string | null;
100
+ api_key_id: string;
101
101
  created_at: Generated<Date>;
102
102
  updated_at: Generated<Date>;
103
103
  }
@@ -137,6 +137,7 @@ interface MagicLinksTable {
137
137
  token: string;
138
138
  expires_at: Date;
139
139
  used_at: Date | null;
140
+ failed_attempts: Generated<number>;
140
141
  created_at: Generated<Date>;
141
142
  }
142
143
  interface UsageDailyTable {
@@ -48,7 +48,7 @@ async function registerSubgraph(db, data) {
48
48
  definition: jsonb(data.definition),
49
49
  schema_hash: data.schemaHash,
50
50
  handler_path: data.handlerPath,
51
- api_key_id: data.apiKeyId ?? null,
51
+ api_key_id: data.apiKeyId,
52
52
  schema_name: data.schemaName ?? null
53
53
  }).onConflict((oc) => oc.columns(["name", "api_key_id"]).doUpdateSet({
54
54
  version: data.version,
@@ -111,5 +111,5 @@ export {
111
111
  deleteSubgraph
112
112
  };
113
113
 
114
- //# debugId=A3A252C7C09E8C5564756E2164756E21
114
+ //# debugId=CA1F8ED652ED1B5C64756E2164756E21
115
115
  //# sourceMappingURL=subgraphs.js.map
@@ -3,9 +3,9 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/queries/subgraphs.ts"],
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
- "import { sql, type Kysely } from \"kysely\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name.\n * With keyPrefix: \"subgraph_{prefix}_{name}\" (tenant-isolated)\n * Without keyPrefix: \"subgraph_{name}\" (backward compat)\n */\nexport function pgSchemaName(subgraphName: string, keyPrefix?: string): string {\n const safeName = subgraphName.replace(/-/g, \"_\");\n if (!keyPrefix) {\n return `subgraph_${safeName}`;\n }\n const safePrefix = keyPrefix.replace(/^sk-sl_/, \"\").replace(/-/g, \"_\");\n return `subgraph_${safePrefix}_${safeName}`;\n}\n\nexport async function registerSubgraph(\n db: Kysely<Database>,\n data: {\n name: string;\n version: string;\n definition: Record<string, unknown>;\n schemaHash: string;\n handlerPath: string;\n apiKeyId?: string;\n schemaName?: string;\n },\n): Promise<Subgraph> {\n return await db\n .insertInto(\"subgraphs\")\n .values({\n name: data.name,\n version: data.version,\n definition: jsonb(data.definition) as any,\n schema_hash: data.schemaHash,\n handler_path: data.handlerPath,\n api_key_id: data.apiKeyId ?? null,\n schema_name: data.schemaName ?? null,\n })\n .onConflict((oc) =>\n oc.columns([\"name\", \"api_key_id\"]).doUpdateSet({\n version: data.version,\n definition: jsonb(data.definition) as any,\n schema_hash: data.schemaHash,\n handler_path: data.handlerPath,\n schema_name: data.schemaName ?? null,\n updated_at: new Date(),\n }),\n )\n .returningAll()\n .executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(db: Kysely<Database>, name: string, apiKeyId?: string): Promise<Subgraph | null> {\n let query = db\n .selectFrom(\"subgraphs\")\n .selectAll()\n .where(\"name\", \"=\", name);\n\n if (apiKeyId) {\n query = query.where(\"api_key_id\", \"=\", apiKeyId);\n }\n\n return (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(db: Kysely<Database>, apiKeyId?: string): Promise<Subgraph[]> {\n let query = db.selectFrom(\"subgraphs\").selectAll();\n if (apiKeyId) {\n query = query.where(\"api_key_id\", \"=\", apiKeyId);\n }\n return query.execute();\n}\n\nexport async function updateSubgraphStatus(\n db: Kysely<Database>,\n name: string,\n status: string,\n lastProcessedBlock?: number,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({\n status,\n ...(lastProcessedBlock !== undefined ? { last_processed_block: lastProcessedBlock } : {}),\n updated_at: new Date(),\n })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function recordSubgraphProcessed(\n db: Kysely<Database>,\n name: string,\n processed: number,\n errors: number,\n lastError?: string,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({\n total_processed: sql`total_processed + ${processed}`,\n total_errors: sql`total_errors + ${errors}`,\n ...(lastError\n ? { last_error: lastError, last_error_at: new Date() }\n : {}),\n updated_at: new Date(),\n })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n db: Kysely<Database>,\n name: string,\n handlerPath: string,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({ handler_path: handlerPath, updated_at: new Date() })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function deleteSubgraph(db: Kysely<Database>, name: string, apiKeyId?: string): Promise<Subgraph | null> {\n const subgraph = await getSubgraph(db, name, apiKeyId);\n if (!subgraph) return null;\n\n // Use stored schema_name if available, otherwise compute\n const schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n // Drop the subgraph's schema (CASCADE drops all tables within)\n await sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(db);\n\n // Remove from registry\n await db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n return subgraph;\n}\n"
6
+ "import { sql, type Kysely } from \"kysely\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name.\n * With keyPrefix: \"subgraph_{prefix}_{name}\" (tenant-isolated)\n * Without keyPrefix: \"subgraph_{name}\" (backward compat)\n */\nexport function pgSchemaName(subgraphName: string, keyPrefix?: string): string {\n const safeName = subgraphName.replace(/-/g, \"_\");\n if (!keyPrefix) {\n return `subgraph_${safeName}`;\n }\n const safePrefix = keyPrefix.replace(/^sk-sl_/, \"\").replace(/-/g, \"_\");\n return `subgraph_${safePrefix}_${safeName}`;\n}\n\nexport async function registerSubgraph(\n db: Kysely<Database>,\n data: {\n name: string;\n version: string;\n definition: Record<string, unknown>;\n schemaHash: string;\n handlerPath: string;\n apiKeyId?: string;\n schemaName?: string;\n },\n): Promise<Subgraph> {\n return await db\n .insertInto(\"subgraphs\")\n .values({\n name: data.name,\n version: data.version,\n definition: jsonb(data.definition) as any,\n schema_hash: data.schemaHash,\n handler_path: data.handlerPath,\n api_key_id: data.apiKeyId!,\n schema_name: data.schemaName ?? null,\n })\n .onConflict((oc) =>\n oc.columns([\"name\", \"api_key_id\"]).doUpdateSet({\n version: data.version,\n definition: jsonb(data.definition) as any,\n schema_hash: data.schemaHash,\n handler_path: data.handlerPath,\n schema_name: data.schemaName ?? null,\n updated_at: new Date(),\n }),\n )\n .returningAll()\n .executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(db: Kysely<Database>, name: string, apiKeyId?: string): Promise<Subgraph | null> {\n let query = db\n .selectFrom(\"subgraphs\")\n .selectAll()\n .where(\"name\", \"=\", name);\n\n if (apiKeyId) {\n query = query.where(\"api_key_id\", \"=\", apiKeyId);\n }\n\n return (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(db: Kysely<Database>, apiKeyId?: string): Promise<Subgraph[]> {\n let query = db.selectFrom(\"subgraphs\").selectAll();\n if (apiKeyId) {\n query = query.where(\"api_key_id\", \"=\", apiKeyId);\n }\n return query.execute();\n}\n\nexport async function updateSubgraphStatus(\n db: Kysely<Database>,\n name: string,\n status: string,\n lastProcessedBlock?: number,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({\n status,\n ...(lastProcessedBlock !== undefined ? { last_processed_block: lastProcessedBlock } : {}),\n updated_at: new Date(),\n })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function recordSubgraphProcessed(\n db: Kysely<Database>,\n name: string,\n processed: number,\n errors: number,\n lastError?: string,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({\n total_processed: sql`total_processed + ${processed}`,\n total_errors: sql`total_errors + ${errors}`,\n ...(lastError\n ? { last_error: lastError, last_error_at: new Date() }\n : {}),\n updated_at: new Date(),\n })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n db: Kysely<Database>,\n name: string,\n handlerPath: string,\n): Promise<void> {\n await db\n .updateTable(\"subgraphs\")\n .set({ handler_path: handlerPath, updated_at: new Date() })\n .where(\"name\", \"=\", name)\n .execute();\n}\n\nexport async function deleteSubgraph(db: Kysely<Database>, name: string, apiKeyId?: string): Promise<Subgraph | null> {\n const subgraph = await getSubgraph(db, name, apiKeyId);\n if (!subgraph) return null;\n\n // Use stored schema_name if available, otherwise compute\n const schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n // Drop the subgraph's schema (CASCADE drops all tables within)\n await sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(db);\n\n // Remove from registry\n await db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n return subgraph;\n}\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "A3A252C7C09E8C5564756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "CA1F8ED652ED1B5C64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -46,7 +46,7 @@ interface StreamsTable {
46
46
  options: Generated<unknown>;
47
47
  endpoint_url: string;
48
48
  signing_secret: string | null;
49
- api_key_id: string | null;
49
+ api_key_id: string;
50
50
  created_at: Generated<Date>;
51
51
  updated_at: Generated<Date>;
52
52
  }
@@ -105,7 +105,7 @@ interface SubgraphsTable {
105
105
  last_error_at: Date | null;
106
106
  total_processed: Generated<number>;
107
107
  total_errors: Generated<number>;
108
- api_key_id: string | null;
108
+ api_key_id: string;
109
109
  created_at: Generated<Date>;
110
110
  updated_at: Generated<Date>;
111
111
  }
@@ -145,6 +145,7 @@ interface MagicLinksTable {
145
145
  token: string;
146
146
  expires_at: Date;
147
147
  used_at: Date | null;
148
+ failed_attempts: Generated<number>;
148
149
  created_at: Generated<Date>;
149
150
  }
150
151
  interface UsageDailyTable {
@@ -258,6 +259,13 @@ interface UsageSummary {
258
259
  }
259
260
  /** Get current usage for an account. */
260
261
  declare function getUsage(db: Kysely<Database>, accountId: string): Promise<UsageSummary>;
262
+ interface DailyUsage {
263
+ date: string;
264
+ apiRequests: number;
265
+ deliveries: number;
266
+ }
267
+ /** Get last 7 days of daily usage, filling missing days with 0. */
268
+ declare function getDailyUsage(db: Kysely<Database>, accountId: string): Promise<DailyUsage[]>;
261
269
  interface LimitCheck {
262
270
  allowed: boolean;
263
271
  limits: ReturnType<typeof getPlanLimits>;
@@ -274,4 +282,4 @@ declare function checkLimits(db: Kysely<Database>, accountId: string, plan: stri
274
282
  * for each tenant's subgraph schemas.
275
283
  */
276
284
  declare function measureStorage(db: Kysely<Database>): Promise<void>;
277
- export { measureStorage, incrementDeliveries, incrementApiRequests, getUsage, checkLimits, UsageSummary, LimitCheck };
285
+ export { measureStorage, incrementDeliveries, incrementApiRequests, getUsage, getDailyUsage, checkLimits, UsageSummary, LimitCheck, DailyUsage };
@@ -56,6 +56,27 @@ async function getUsage(db, accountId) {
56
56
  storageBytes: Number(storageRow?.storage_bytes ?? 0)
57
57
  };
58
58
  }
59
+ async function getDailyUsage(db, accountId) {
60
+ 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();
61
+ const byDate = new Map(rows.map((r) => {
62
+ const d = r.date;
63
+ const key = d instanceof Date ? d.toISOString().slice(0, 10) : String(d).slice(0, 10);
64
+ return [key, r];
65
+ }));
66
+ const result = [];
67
+ for (let i = 6;i >= 0; i--) {
68
+ const d = new Date;
69
+ d.setDate(d.getDate() - i);
70
+ const dateStr = d.toISOString().slice(0, 10);
71
+ const row = byDate.get(dateStr);
72
+ result.push({
73
+ date: dateStr,
74
+ apiRequests: row?.api_requests ?? 0,
75
+ deliveries: row?.deliveries ?? 0
76
+ });
77
+ }
78
+ return result;
79
+ }
59
80
  async function checkLimits(db, accountId, plan) {
60
81
  const limits = getPlanLimits(plan);
61
82
  const usage = await getUsage(db, accountId);
@@ -114,8 +135,9 @@ export {
114
135
  incrementDeliveries,
115
136
  incrementApiRequests,
116
137
  getUsage,
138
+ getDailyUsage,
117
139
  checkLimits
118
140
  };
119
141
 
120
- //# debugId=31E68DFE6E6CCA6264756E2164756E21
142
+ //# debugId=DDD1942F27B4B83564756E2164756E21
121
143
  //# sourceMappingURL=usage.js.map
@@ -3,9 +3,9 @@
3
3
  "sources": ["../src/lib/plans.ts", "../src/db/queries/usage.ts"],
4
4
  "sourcesContent": [
5
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"
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 DailyUsage {\n date: string;\n apiRequests: number;\n deliveries: number;\n}\n\n/** Get last 7 days of daily usage, filling missing days with 0. */\nexport async function getDailyUsage(\n db: Kysely<Database>,\n accountId: string,\n): Promise<DailyUsage[]> {\n const rows = await db\n .selectFrom(\"usage_daily\")\n .select([\"date\", \"api_requests\", \"deliveries\"])\n .where(\"account_id\", \"=\", accountId)\n .where(\"date\", \">=\", sql<string>`NOW()::date - 6`)\n .orderBy(\"date\", \"asc\")\n .execute();\n\n // Fill missing days with 0 (normalize date to YYYY-MM-DD string)\n const byDate = new Map(rows.map((r) => {\n const d = r.date as unknown;\n const key = d instanceof Date ? d.toISOString().slice(0, 10) : String(d).slice(0, 10);\n return [key, r];\n }));\n const result: DailyUsage[] = [];\n for (let i = 6; i >= 0; i--) {\n const d = new Date();\n d.setDate(d.getDate() - i);\n const dateStr = d.toISOString().slice(0, 10);\n const row = byDate.get(dateStr);\n result.push({\n date: dateStr,\n apiRequests: row?.api_requests ?? 0,\n deliveries: row?.deliveries ?? 0,\n });\n }\n return result;\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"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "31E68DFE6E6CCA6264756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "DDD1942F27B4B83564756E2164756E21",
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
  }
@@ -96,7 +96,7 @@ interface SubgraphsTable {
96
96
  last_error_at: Date | null;
97
97
  total_processed: Generated<number>;
98
98
  total_errors: Generated<number>;
99
- api_key_id: string | null;
99
+ api_key_id: string;
100
100
  created_at: Generated<Date>;
101
101
  updated_at: Generated<Date>;
102
102
  }
@@ -136,6 +136,7 @@ interface MagicLinksTable {
136
136
  token: string;
137
137
  expires_at: Date;
138
138
  used_at: Date | null;
139
+ failed_attempts: Generated<number>;
139
140
  created_at: Generated<Date>;
140
141
  }
141
142
  interface UsageDailyTable {
@@ -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 STREAM_NOT_FOUND: \"STREAM_NOT_FOUND\",\n VALIDATION_ERROR: \"VALIDATION_ERROR\",\n DATABASE_ERROR: \"DATABASE_ERROR\",\n DELIVERY_ERROR: \"DELIVERY_ERROR\",\n FILTER_EVALUATION_ERROR: \"FILTER_EVALUATION_ERROR\",\n AUTHENTICATION_ERROR: \"AUTHENTICATION_ERROR\",\n AUTHORIZATION_ERROR: \"AUTHORIZATION_ERROR\",\n RATE_LIMIT_ERROR: \"RATE_LIMIT_ERROR\",\n FORBIDDEN: \"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 public code: ErrorCode;\n public override cause?: unknown;\n\n constructor(\n code: ErrorCode,\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). */\ntype MappedCode = Extract<\n ErrorCode,\n | \"AUTHENTICATION_ERROR\"\n | \"AUTHORIZATION_ERROR\"\n | \"RATE_LIMIT_ERROR\"\n | \"FORBIDDEN\"\n | \"STREAM_NOT_FOUND\"\n | \"VALIDATION_ERROR\"\n>;\nexport const CODE_TO_STATUS: Record<MappedCode, 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 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"
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,EACxB,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;AACb;AAAA;AAOO,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;AAaO,IAAM,iBAAkE;AAAA,EAC7E,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,kBAAkB;AACpB;AAKO,SAAS,eAAe,CAAC,KAAsB;AAAA,EACpD,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
  }
@@ -96,7 +96,7 @@ interface SubgraphsTable {
96
96
  last_error_at: Date | null;
97
97
  total_processed: Generated<number>;
98
98
  total_errors: Generated<number>;
99
- api_key_id: string | null;
99
+ api_key_id: string;
100
100
  created_at: Generated<Date>;
101
101
  updated_at: Generated<Date>;
102
102
  }
@@ -136,6 +136,7 @@ interface MagicLinksTable {
136
136
  token: string;
137
137
  expires_at: Date;
138
138
  used_at: Date | null;
139
+ failed_attempts: Generated<number>;
139
140
  created_at: Generated<Date>;
140
141
  }
141
142
  interface UsageDailyTable {
@@ -321,13 +322,25 @@ declare function getDb(connectionString?: string): Kysely<Database>;
321
322
  declare function getRawClient(): ReturnType<typeof postgres>;
322
323
  /** Close the DB connection pool. Call in CLI commands to allow process exit. */
323
324
  declare function closeDb(): Promise<void>;
325
+ declare const ErrorCodes: {
326
+ readonly STREAM_NOT_FOUND: "STREAM_NOT_FOUND"
327
+ readonly VALIDATION_ERROR: "VALIDATION_ERROR"
328
+ readonly DATABASE_ERROR: "DATABASE_ERROR"
329
+ readonly DELIVERY_ERROR: "DELIVERY_ERROR"
330
+ readonly FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR"
331
+ readonly AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR"
332
+ readonly AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR"
333
+ readonly RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR"
334
+ readonly FORBIDDEN: "FORBIDDEN"
335
+ };
336
+ type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
324
337
  /**
325
338
  * Base error class for all Stacks Streams errors
326
339
  */
327
340
  declare class StreamsError extends Error {
328
- code: string;
341
+ code: ErrorCode;
329
342
  cause?: unknown;
330
- constructor(code: string, message: string, cause?: unknown);
343
+ constructor(code: ErrorCode, message: string, cause?: unknown);
331
344
  toJSON(): {
332
345
  name: string
333
346
  code: string
@@ -389,7 +402,8 @@ declare class ForbiddenError extends StreamsError {
389
402
  }
390
403
  /** Error code → HTTP status. Used by API middleware for code-based matching
391
404
  * (avoids cross-bundle instanceof failures from bunup class duplication). */
392
- declare const CODE_TO_STATUS: Record<string, 400 | 401 | 403 | 404 | 429>;
405
+ type MappedCode = Extract<ErrorCode, "AUTHENTICATION_ERROR" | "AUTHORIZATION_ERROR" | "RATE_LIMIT_ERROR" | "FORBIDDEN" | "STREAM_NOT_FOUND" | "VALIDATION_ERROR">;
406
+ declare const CODE_TO_STATUS: Record<MappedCode, 400 | 401 | 403 | 404 | 429>;
393
407
  /**
394
408
  * Safely extract error message from unknown error value
395
409
  */
@@ -725,4 +739,4 @@ declare function createSignatureHeader(payload: string, secret: string, timestam
725
739
  * Returns true if valid, false otherwise
726
740
  */
727
741
  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 };
742
+ 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, 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,7 +41,9 @@ 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 = parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
44
45
  rawClient = postgres(url, {
46
+ max: poolMax,
45
47
  ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" }
46
48
  });
47
49
  db = new Kysely({
@@ -66,6 +68,18 @@ async function closeDb() {
66
68
  }
67
69
  }
68
70
  // src/errors.ts
71
+ var ErrorCodes = {
72
+ STREAM_NOT_FOUND: "STREAM_NOT_FOUND",
73
+ VALIDATION_ERROR: "VALIDATION_ERROR",
74
+ DATABASE_ERROR: "DATABASE_ERROR",
75
+ DELIVERY_ERROR: "DELIVERY_ERROR",
76
+ FILTER_EVALUATION_ERROR: "FILTER_EVALUATION_ERROR",
77
+ AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR",
78
+ AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR",
79
+ RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR",
80
+ FORBIDDEN: "FORBIDDEN"
81
+ };
82
+
69
83
  class StreamsError extends Error {
70
84
  code;
71
85
  cause;
@@ -159,7 +173,6 @@ var CODE_TO_STATUS = {
159
173
  RATE_LIMIT_ERROR: 429,
160
174
  FORBIDDEN: 403,
161
175
  STREAM_NOT_FOUND: 404,
162
- VIEW_NOT_FOUND: 404,
163
176
  VALIDATION_ERROR: 400
164
177
  };
165
178
  function getErrorMessage(err) {
@@ -658,6 +671,7 @@ export {
658
671
  FtBurnFilterSchema,
659
672
  ForbiddenError,
660
673
  FilterEvaluationError,
674
+ ErrorCodes,
661
675
  DeploySubgraphRequestSchema,
662
676
  DeliveryPayloadSchema,
663
677
  DeliveryError,
@@ -670,5 +684,5 @@ export {
670
684
  AuthenticationError
671
685
  };
672
686
 
673
- //# debugId=4EF79202801DC1C664756E2164756E21
687
+ //# debugId=C1B5835384CBB78564756E2164756E21
674
688
  //# sourceMappingURL=index.js.map
@@ -3,8 +3,8 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/index.ts", "../src/errors.ts", "../src/env.ts", "../src/logger.ts", "../src/queue/index.ts", "../src/schemas/filters.ts", "../src/schemas/subgraphs.ts", "../src/schemas/stream.ts", "../src/crypto/hmac.ts"],
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
- "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
- "/**\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",
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 const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n rawClient = postgres(url, {\n max: poolMax,\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
+ "export const ErrorCodes = {\n STREAM_NOT_FOUND: \"STREAM_NOT_FOUND\",\n VALIDATION_ERROR: \"VALIDATION_ERROR\",\n DATABASE_ERROR: \"DATABASE_ERROR\",\n DELIVERY_ERROR: \"DELIVERY_ERROR\",\n FILTER_EVALUATION_ERROR: \"FILTER_EVALUATION_ERROR\",\n AUTHENTICATION_ERROR: \"AUTHENTICATION_ERROR\",\n AUTHORIZATION_ERROR: \"AUTHORIZATION_ERROR\",\n RATE_LIMIT_ERROR: \"RATE_LIMIT_ERROR\",\n FORBIDDEN: \"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 public code: ErrorCode;\n public override cause?: unknown;\n\n constructor(\n code: ErrorCode,\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). */\ntype MappedCode = Extract<\n ErrorCode,\n | \"AUTHENTICATION_ERROR\"\n | \"AUTHORIZATION_ERROR\"\n | \"RATE_LIMIT_ERROR\"\n | \"FORBIDDEN\"\n | \"STREAM_NOT_FOUND\"\n | \"VALIDATION_ERROR\"\n>;\nexport const CODE_TO_STATUS: Record<MappedCode, 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 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",
8
8
  "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",
9
9
  "import { getEnv } from \"./env.ts\";\n\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass Logger {\n private _level?: LogLevel;\n private _isProduction?: boolean;\n private _initialized = false;\n\n private init() {\n if (this._initialized) return;\n this._initialized = true;\n try {\n const env = getEnv();\n this._level = env.LOG_LEVEL;\n this._isProduction = env.NODE_ENV === \"production\";\n } catch {\n // Fallback when env is unavailable (e.g. tests without DATABASE_URL)\n this._level = \"info\";\n this._isProduction = false;\n }\n }\n\n private get level(): LogLevel {\n this.init();\n return this._level!;\n }\n\n private get isProduction(): boolean {\n this.init();\n return this._isProduction!;\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n }\n\n private formatMessage(level: LogLevel, message: string, meta?: Record<string, any>) {\n const timestamp = new Date().toISOString();\n\n if (this.isProduction) {\n // JSON output for production\n return JSON.stringify({\n timestamp,\n level,\n message,\n ...meta,\n });\n }\n\n // Human-readable output for development\n const metaStr = meta ? ` ${JSON.stringify(meta)}` : \"\";\n return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"debug\")) {\n console.debug(this.formatMessage(\"debug\", message, meta));\n }\n }\n\n info(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"info\")) {\n console.info(this.formatMessage(\"info\", message, meta));\n }\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"warn\")) {\n console.warn(this.formatMessage(\"warn\", message, meta));\n }\n }\n\n error(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"error\")) {\n console.error(this.formatMessage(\"error\", message, meta));\n }\n }\n}\n\n// Export singleton instance\nexport const logger: Logger = new Logger();\n",
10
10
  "import { sql } from \"kysely\";\nimport { getDb } from \"../db/index.ts\";\nimport type { Job } from \"../db/types.ts\";\nimport { randomUUID } from \"crypto\";\n\nexport interface QueueStats {\n pending: number;\n processing: number;\n completed: number;\n failed: number;\n total: number;\n}\n\n// Worker identifier for this process\nconst WORKER_ID: string = `worker-${randomUUID().slice(0, 8)}`;\n\n/**\n * Enqueue a new job for stream evaluation\n */\nexport async function enqueue(\n streamId: string,\n blockHeight: number,\n backfill = false\n): Promise<string> {\n const db = getDb();\n\n const row = await db\n .insertInto(\"jobs\")\n .values({\n stream_id: streamId,\n block_height: blockHeight,\n backfill,\n status: \"pending\",\n attempts: 0,\n })\n .returning([\"id\"])\n .executeTakeFirstOrThrow();\n\n return row.id;\n}\n\n/**\n * Claim a pending job using SKIP LOCKED to prevent concurrent access\n * Returns null if no jobs available\n */\nexport async function claim(): Promise<Job | null> {\n const db = getDb();\n\n const { rows } = await sql<Job>`\n UPDATE jobs\n SET\n status = 'processing',\n locked_at = NOW(),\n locked_by = ${WORKER_ID},\n attempts = attempts + 1\n WHERE id = (\n SELECT id FROM jobs\n WHERE status = 'pending'\n ORDER BY\n backfill ASC,\n block_height ASC,\n created_at ASC\n FOR UPDATE SKIP LOCKED\n LIMIT 1\n )\n RETURNING *\n `.execute(db);\n\n return rows[0] ?? null;\n}\n\n/**\n * Mark a job as completed\n */\nexport async function complete(jobId: string): Promise<void> {\n const db = getDb();\n\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"completed\",\n completed_at: new Date(),\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n}\n\n/**\n * Mark a job as failed\n * Re-queues if under max attempts, otherwise marks as permanently failed\n */\nexport async function fail(\n jobId: string,\n error: string,\n maxAttempts = 3\n): Promise<void> {\n const db = getDb();\n\n const job = await db\n .selectFrom(\"jobs\")\n .select(\"attempts\")\n .where(\"id\", \"=\", jobId)\n .executeTakeFirst();\n\n if (!job) return;\n\n if (job.attempts < maxAttempts) {\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"pending\",\n error,\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n } else {\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"failed\",\n error,\n completed_at: new Date(),\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n }\n}\n\n/**\n * Get queue statistics\n */\nexport async function stats(): Promise<QueueStats> {\n const { rows } = await sql<{ status: string; count: string }>`\n SELECT status, COUNT(*) as count\n FROM jobs\n GROUP BY status\n `.execute(getDb());\n\n const counts: Record<string, number> = {};\n for (const row of rows) {\n counts[row.status] = parseInt(row.count, 10);\n }\n\n return {\n pending: counts[\"pending\"] || 0,\n processing: counts[\"processing\"] || 0,\n completed: counts[\"completed\"] || 0,\n failed: counts[\"failed\"] || 0,\n total: Object.values(counts).reduce((a, b) => a + b, 0),\n };\n}\n\n/**\n * Get worker ID for this process\n */\nexport function getWorkerId(): string {\n return WORKER_ID;\n}\n\nexport { WORKER_ID };\n",
@@ -13,7 +13,7 @@
13
13
  "import { z } from \"zod/v4\";\nimport { StreamFilterSchema, type StreamFilter } from \"./filters.ts\";\n\n// ── Type interfaces ──────────────────────────────────────────────────\n\nexport interface StreamOptions {\n decodeClarityValues: boolean;\n includeRawTx: boolean;\n includeBlockMetadata: boolean;\n rateLimit: number;\n timeoutMs: number;\n maxRetries: number;\n}\n\nexport interface CreateStream {\n name: string;\n endpointUrl: string;\n filters: StreamFilter[];\n options?: StreamOptions;\n startBlock?: number;\n endBlock?: number;\n}\n\nexport interface UpdateStream {\n name?: string;\n endpointUrl?: string;\n filters?: StreamFilter[];\n options?: Partial<StreamOptions>;\n}\n\nexport interface DeliveryPayload {\n streamId: string;\n streamName: string;\n block: {\n height: number;\n hash: string;\n parentHash: string;\n burnBlockHeight: number;\n timestamp: number;\n };\n matches: {\n transactions: Array<{\n txId: string;\n type: string;\n sender: string;\n status: string;\n contractId: string | null;\n functionName: string | null;\n rawTx?: string;\n }>;\n events: Array<{\n txId: string;\n eventIndex: number;\n type: string;\n data?: any;\n }>;\n };\n isBackfill: boolean;\n deliveredAt: string;\n}\n\nexport interface StreamMetricsResponse {\n totalDeliveries: number;\n failedDeliveries: number;\n lastTriggeredAt: string | null;\n lastTriggeredBlock: number | null;\n errorMessage: string | null;\n}\n\nexport interface StreamResponse {\n id: string;\n name: string;\n status: \"inactive\" | \"active\" | \"paused\" | \"failed\";\n endpointUrl: string;\n filters: StreamFilter[];\n options: StreamOptions;\n totalDeliveries: number;\n failedDeliveries: number;\n lastTriggeredAt?: string | null;\n lastTriggeredBlock?: number | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n// ── Zod schemas ──────────────────────────────────────────────────────\n\n// Stream options schema (internal, keeps ZodObject methods like .partial())\nconst streamOptionsShape = z.object({\n decodeClarityValues: z.boolean().default(true),\n includeRawTx: z.boolean().default(false),\n includeBlockMetadata: z.boolean().default(true),\n rateLimit: z.number().int().positive().max(100).default(10),\n timeoutMs: z.number().int().positive().max(30000).default(10000),\n maxRetries: z.number().int().min(0).max(10).default(3),\n});\n\n// Cast: .default() makes _input fields optional, but output type matches StreamOptions\nexport const StreamOptionsSchema: z.ZodType<StreamOptions> =\n streamOptionsShape as unknown as z.ZodType<StreamOptions>;\n\nexport const CreateStreamSchema: z.ZodType<CreateStream> = z.object({\n name: z.string().min(1).max(255),\n endpointUrl: z.string().url(),\n filters: z.array(StreamFilterSchema).min(1),\n options: streamOptionsShape.optional(),\n startBlock: z.number().int().positive().optional(),\n endBlock: z.number().int().positive().optional(),\n}) as unknown as z.ZodType<CreateStream>;\n\nexport const UpdateStreamSchema: z.ZodType<UpdateStream> = z.object({\n name: z.string().min(1).max(255).optional(),\n endpointUrl: z.string().url().optional(),\n filters: z.array(StreamFilterSchema).min(1).optional(),\n options: streamOptionsShape.partial().optional(),\n}).refine(\n (data) => Object.keys(data).length > 0,\n { message: \"At least one field must be provided for update\" }\n) as unknown as z.ZodType<UpdateStream>;\n\nexport const DeliveryPayloadSchema: z.ZodType<DeliveryPayload> = z.object({\n streamId: z.string().uuid(),\n streamName: z.string(),\n block: z.object({\n height: z.number(),\n hash: z.string(),\n parentHash: z.string(),\n burnBlockHeight: z.number(),\n timestamp: z.number(),\n }),\n matches: z.object({\n transactions: z.array(z.object({\n txId: z.string(),\n type: z.string(),\n sender: z.string(),\n status: z.string(),\n contractId: z.string().nullable(),\n functionName: z.string().nullable(),\n rawTx: z.string().optional(),\n })),\n events: z.array(z.object({\n txId: z.string(),\n eventIndex: z.number(),\n type: z.string(),\n data: z.any(),\n })),\n }),\n isBackfill: z.boolean(),\n deliveredAt: z.string().datetime(),\n}) as unknown as z.ZodType<DeliveryPayload>;\n\nexport const StreamMetricsSchema: z.ZodType<StreamMetricsResponse> = z.object({\n totalDeliveries: z.number(),\n failedDeliveries: z.number(),\n lastTriggeredAt: z.string().datetime().nullable(),\n lastTriggeredBlock: z.number().nullable(),\n errorMessage: z.string().nullable(),\n});\n\nexport const StreamResponseSchema: z.ZodType<StreamResponse> = z.object({\n id: z.string().uuid(),\n name: z.string(),\n status: z.enum([\"inactive\", \"active\", \"paused\", \"failed\"]),\n endpointUrl: z.string().url(),\n filters: z.array(StreamFilterSchema),\n options: streamOptionsShape,\n totalDeliveries: z.number().int().default(0),\n failedDeliveries: z.number().int().default(0),\n lastTriggeredAt: z.string().datetime().nullable().optional(),\n lastTriggeredBlock: z.number().int().nullable().optional(),\n errorMessage: z.string().nullable().optional(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime(),\n}) as unknown as z.ZodType<StreamResponse>;\n\n// API response types\nexport interface CreateStreamResponse {\n stream: StreamResponse;\n signingSecret: string;\n}\n\nexport interface ListStreamsResponse {\n streams: StreamResponse[];\n total: number;\n}\n\nexport interface BulkPauseResponse {\n paused: number;\n streams: StreamResponse[];\n}\n\nexport interface BulkResumeResponse {\n resumed: number;\n streams: StreamResponse[];\n}\n",
14
14
  "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"
15
15
  ],
16
- "mappings": "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",
17
- "debugId": "4EF79202801DC1C664756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "C1B5835384CBB78564756E2164756E21",
18
18
  "names": []
19
19
  }
@@ -38,7 +38,7 @@ interface StreamsTable {
38
38
  options: Generated<unknown>;
39
39
  endpoint_url: string;
40
40
  signing_secret: string | null;
41
- api_key_id: string | null;
41
+ api_key_id: string;
42
42
  created_at: Generated<Date>;
43
43
  updated_at: Generated<Date>;
44
44
  }
@@ -97,7 +97,7 @@ interface SubgraphsTable {
97
97
  last_error_at: Date | null;
98
98
  total_processed: Generated<number>;
99
99
  total_errors: Generated<number>;
100
- api_key_id: string | null;
100
+ api_key_id: string;
101
101
  created_at: Generated<Date>;
102
102
  updated_at: Generated<Date>;
103
103
  }
@@ -137,6 +137,7 @@ interface MagicLinksTable {
137
137
  token: string;
138
138
  expires_at: Date;
139
139
  used_at: Date | null;
140
+ failed_attempts: Generated<number>;
140
141
  created_at: Generated<Date>;
141
142
  }
142
143
  interface UsageDailyTable {
@@ -42,7 +42,9 @@ function getDb(connectionString) {
42
42
  if (!db) {
43
43
  const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/streams_dev";
44
44
  const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || url.includes("@postgres:");
45
+ const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
45
46
  rawClient = postgres(url, {
47
+ max: poolMax,
46
48
  ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" }
47
49
  });
48
50
  db = new Kysely({
@@ -176,5 +178,5 @@ export {
176
178
  WORKER_ID
177
179
  };
178
180
 
179
- //# debugId=D4607290C65E8FF064756E2164756E21
181
+ //# debugId=4D1E73D7224206BB64756E2164756E21
180
182
  //# sourceMappingURL=index.js.map
@@ -3,10 +3,10 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/index.ts", "../src/queue/index.ts"],
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
- "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",
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 const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n rawClient = postgres(url, {\n max: poolMax,\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
  "import { sql } from \"kysely\";\nimport { getDb } from \"../db/index.ts\";\nimport type { Job } from \"../db/types.ts\";\nimport { randomUUID } from \"crypto\";\n\nexport interface QueueStats {\n pending: number;\n processing: number;\n completed: number;\n failed: number;\n total: number;\n}\n\n// Worker identifier for this process\nconst WORKER_ID: string = `worker-${randomUUID().slice(0, 8)}`;\n\n/**\n * Enqueue a new job for stream evaluation\n */\nexport async function enqueue(\n streamId: string,\n blockHeight: number,\n backfill = false\n): Promise<string> {\n const db = getDb();\n\n const row = await db\n .insertInto(\"jobs\")\n .values({\n stream_id: streamId,\n block_height: blockHeight,\n backfill,\n status: \"pending\",\n attempts: 0,\n })\n .returning([\"id\"])\n .executeTakeFirstOrThrow();\n\n return row.id;\n}\n\n/**\n * Claim a pending job using SKIP LOCKED to prevent concurrent access\n * Returns null if no jobs available\n */\nexport async function claim(): Promise<Job | null> {\n const db = getDb();\n\n const { rows } = await sql<Job>`\n UPDATE jobs\n SET\n status = 'processing',\n locked_at = NOW(),\n locked_by = ${WORKER_ID},\n attempts = attempts + 1\n WHERE id = (\n SELECT id FROM jobs\n WHERE status = 'pending'\n ORDER BY\n backfill ASC,\n block_height ASC,\n created_at ASC\n FOR UPDATE SKIP LOCKED\n LIMIT 1\n )\n RETURNING *\n `.execute(db);\n\n return rows[0] ?? null;\n}\n\n/**\n * Mark a job as completed\n */\nexport async function complete(jobId: string): Promise<void> {\n const db = getDb();\n\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"completed\",\n completed_at: new Date(),\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n}\n\n/**\n * Mark a job as failed\n * Re-queues if under max attempts, otherwise marks as permanently failed\n */\nexport async function fail(\n jobId: string,\n error: string,\n maxAttempts = 3\n): Promise<void> {\n const db = getDb();\n\n const job = await db\n .selectFrom(\"jobs\")\n .select(\"attempts\")\n .where(\"id\", \"=\", jobId)\n .executeTakeFirst();\n\n if (!job) return;\n\n if (job.attempts < maxAttempts) {\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"pending\",\n error,\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n } else {\n await db\n .updateTable(\"jobs\")\n .set({\n status: \"failed\",\n error,\n completed_at: new Date(),\n locked_at: null,\n locked_by: null,\n })\n .where(\"id\", \"=\", jobId)\n .execute();\n }\n}\n\n/**\n * Get queue statistics\n */\nexport async function stats(): Promise<QueueStats> {\n const { rows } = await sql<{ status: string; count: string }>`\n SELECT status, COUNT(*) as count\n FROM jobs\n GROUP BY status\n `.execute(getDb());\n\n const counts: Record<string, number> = {};\n for (const row of rows) {\n counts[row.status] = parseInt(row.count, 10);\n }\n\n return {\n pending: counts[\"pending\"] || 0,\n processing: counts[\"processing\"] || 0,\n completed: counts[\"completed\"] || 0,\n failed: counts[\"failed\"] || 0,\n total: Object.values(counts).reduce((a, b) => a + b, 0),\n };\n}\n\n/**\n * Get worker ID for this process\n */\nexport function getWorkerId(): string {\n return WORKER_ID;\n}\n\nexport { WORKER_ID };\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "D4607290C65E8FF064756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "4D1E73D7224206BB64756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -42,7 +42,9 @@ function getDb(connectionString) {
42
42
  if (!db) {
43
43
  const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/streams_dev";
44
44
  const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || url.includes("@postgres:");
45
+ const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
45
46
  rawClient = postgres(url, {
47
+ max: poolMax,
46
48
  ssl: isLocal ? undefined : { rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0" }
47
49
  });
48
50
  db = new Kysely({
@@ -100,5 +102,5 @@ export {
100
102
  recoverStaleJobs
101
103
  };
102
104
 
103
- //# debugId=2CAB8C86093BD9F464756E2164756E21
105
+ //# debugId=4F3E278F7270040964756E2164756E21
104
106
  //# sourceMappingURL=recovery.js.map
@@ -3,10 +3,10 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/index.ts", "../src/queue/recovery.ts"],
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
- "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",
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 const poolMax = parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n rawClient = postgres(url, {\n max: poolMax,\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
  "import { sql } from \"kysely\";\nimport { getDb } from \"../db/index.ts\";\n\n/**\n * Recover jobs that have been locked for longer than the threshold\n * These are likely from crashed workers\n *\n * @param staleThresholdMinutes - Minutes after which a locked job is considered stale\n * @returns Number of recovered jobs\n */\nexport async function recoverStaleJobs(\n staleThresholdMinutes = 5\n): Promise<number> {\n const { rows } = await sql`\n UPDATE jobs\n SET\n status = 'pending',\n locked_at = NULL,\n locked_by = NULL\n WHERE\n status = 'processing'\n AND locked_at < NOW() - INTERVAL '${sql.raw(staleThresholdMinutes.toString())} minutes'\n RETURNING id\n `.execute(getDb());\n\n return rows.length;\n}\n\n/**\n * Run periodic stale job recovery\n * Returns a cleanup function to stop the interval\n */\nexport function startRecoveryLoop(\n intervalMs = 60000, // 1 minute\n staleThresholdMinutes = 5\n): () => void {\n const intervalId = setInterval(async () => {\n try {\n const recovered = await recoverStaleJobs(staleThresholdMinutes);\n if (recovered > 0) {\n console.log(`Recovered ${recovered} stale jobs`);\n }\n } catch (error) {\n console.error(\"Error recovering stale jobs:\", error);\n }\n }, intervalMs);\n\n return () => clearInterval(intervalId);\n}\n"
8
8
  ],
9
- "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;;ACvCF,gBAAS;AAUT,eAAsB,gBAAgB,CACpC,wBAAwB,GACP;AAAA,EACjB,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAQiB,KAAI,IAAI,sBAAsB,SAAS,CAAC;AAAA;AAAA,IAE9E,QAAQ,MAAM,CAAC;AAAA,EAEjB,OAAO,KAAK;AAAA;AAOP,SAAS,iBAAiB,CAC/B,aAAa,OACb,wBAAwB,GACZ;AAAA,EACZ,MAAM,aAAa,YAAY,YAAY;AAAA,IACzC,IAAI;AAAA,MACF,MAAM,YAAY,MAAM,iBAAiB,qBAAqB;AAAA,MAC9D,IAAI,YAAY,GAAG;AAAA,QACjB,QAAQ,IAAI,aAAa,sBAAsB;AAAA,MACjD;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,MAAM,gCAAgC,KAAK;AAAA;AAAA,KAEpD,UAAU;AAAA,EAEb,OAAO,MAAM,cAAc,UAAU;AAAA;",
10
- "debugId": "2CAB8C86093BD9F464756E2164756E21",
9
+ "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;AA0CA,gBAAS;AAvCT,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,MAAM,UAAU,SAAS,QAAQ,IAAI,qBAAqB,MAAM,EAAE;AAAA,IAClE,YAAY,SAAS,KAAK;AAAA,MACxB,KAAK;AAAA,MACL,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;;ACzCF,gBAAS;AAUT,eAAsB,gBAAgB,CACpC,wBAAwB,GACP;AAAA,EACjB,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAQiB,KAAI,IAAI,sBAAsB,SAAS,CAAC;AAAA;AAAA,IAE9E,QAAQ,MAAM,CAAC;AAAA,EAEjB,OAAO,KAAK;AAAA;AAOP,SAAS,iBAAiB,CAC/B,aAAa,OACb,wBAAwB,GACZ;AAAA,EACZ,MAAM,aAAa,YAAY,YAAY;AAAA,IACzC,IAAI;AAAA,MACF,MAAM,YAAY,MAAM,iBAAiB,qBAAqB;AAAA,MAC9D,IAAI,YAAY,GAAG;AAAA,QACjB,QAAQ,IAAI,aAAa,sBAAsB;AAAA,MACjD;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,MAAM,gCAAgC,KAAK;AAAA;AAAA,KAEpD,UAAU;AAAA,EAEb,OAAO,MAAM,cAAc,UAAU;AAAA;",
10
+ "debugId": "4F3E278F7270040964756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -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
  }
@@ -0,0 +1,20 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ export async function up(db: Kysely<any>): Promise<void> {
4
+ // Magic link: add failed attempt tracking
5
+ await sql`ALTER TABLE "magic_links" ADD COLUMN "failed_attempts" integer NOT NULL DEFAULT 0`.execute(db);
6
+
7
+ // Ownership: clean up any NULL api_key_id rows
8
+ await sql`DELETE FROM "streams" WHERE "api_key_id" IS NULL`.execute(db);
9
+ await sql`DELETE FROM "subgraphs" WHERE "api_key_id" IS NULL`.execute(db);
10
+
11
+ // Ownership: enforce NOT NULL going forward
12
+ await sql`ALTER TABLE "streams" ALTER COLUMN "api_key_id" SET NOT NULL`.execute(db);
13
+ await sql`ALTER TABLE "subgraphs" ALTER COLUMN "api_key_id" SET NOT NULL`.execute(db);
14
+ }
15
+
16
+ export async function down(db: Kysely<any>): Promise<void> {
17
+ await sql`ALTER TABLE "magic_links" DROP COLUMN "failed_attempts"`.execute(db);
18
+ await sql`ALTER TABLE "streams" ALTER COLUMN "api_key_id" DROP NOT NULL`.execute(db);
19
+ await sql`ALTER TABLE "subgraphs" ALTER COLUMN "api_key_id" DROP NOT NULL`.execute(db);
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/shared",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "main": "./dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",