@secondlayer/shared 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/src/crypto/secrets.d.ts +5 -0
  2. package/dist/src/crypto/secrets.js +69 -0
  3. package/dist/src/crypto/secrets.js.map +10 -0
  4. package/dist/src/db/index.d.ts +91 -6
  5. package/dist/src/db/index.js +53 -29
  6. package/dist/src/db/index.js.map +4 -4
  7. package/dist/src/db/jsonb.js.map +2 -2
  8. package/dist/src/db/queries/accounts.d.ts +59 -2
  9. package/dist/src/db/queries/integrity.d.ts +59 -2
  10. package/dist/src/db/queries/marketplace.d.ts +59 -2
  11. package/dist/src/db/queries/marketplace.js +6 -9
  12. package/dist/src/db/queries/marketplace.js.map +3 -3
  13. package/dist/src/db/queries/projects.d.ts +59 -2
  14. package/dist/src/db/queries/projects.js.map +2 -2
  15. package/dist/src/db/queries/subgraph-gaps.d.ts +59 -2
  16. package/dist/src/db/queries/subgraphs.d.ts +63 -5
  17. package/dist/src/db/queries/subgraphs.js +3 -9
  18. package/dist/src/db/queries/subgraphs.js.map +4 -4
  19. package/dist/src/db/queries/tenants.d.ts +493 -0
  20. package/dist/src/db/queries/tenants.js +194 -0
  21. package/dist/src/db/queries/tenants.js.map +11 -0
  22. package/dist/src/db/queries/usage.d.ts +59 -2
  23. package/dist/src/db/queries/usage.js +3 -3
  24. package/dist/src/db/queries/usage.js.map +3 -3
  25. package/dist/src/db/queries/workflows.d.ts +59 -2
  26. package/dist/src/db/queries/workflows.js +31 -3
  27. package/dist/src/db/queries/workflows.js.map +4 -4
  28. package/dist/src/db/schema.d.ts +69 -3
  29. package/dist/src/env.d.ts +10 -0
  30. package/dist/src/env.js +3 -1
  31. package/dist/src/env.js.map +3 -3
  32. package/dist/src/errors.d.ts +17 -3
  33. package/dist/src/errors.js +34 -3
  34. package/dist/src/errors.js.map +3 -3
  35. package/dist/src/index.d.ts +117 -8
  36. package/dist/src/index.js +88 -31
  37. package/dist/src/index.js.map +6 -6
  38. package/dist/src/logger.js +3 -1
  39. package/dist/src/logger.js.map +3 -3
  40. package/dist/src/mode.d.ts +30 -0
  41. package/dist/src/mode.js +43 -0
  42. package/dist/src/mode.js.map +10 -0
  43. package/dist/src/node/archive-client.js +3 -1
  44. package/dist/src/node/archive-client.js.map +3 -3
  45. package/dist/src/node/hiro-client.js +3 -1
  46. package/dist/src/node/hiro-client.js.map +3 -3
  47. package/dist/src/node/local-client.d.ts +59 -2
  48. package/dist/src/pricing.d.ts +28 -0
  49. package/dist/src/pricing.js +47 -0
  50. package/dist/src/pricing.js.map +10 -0
  51. package/dist/src/queue/listener.d.ts +11 -2
  52. package/dist/src/queue/listener.js +11 -12
  53. package/dist/src/queue/listener.js.map +3 -3
  54. package/dist/src/types.d.ts +10 -0
  55. package/migrations/0033_workflow_steps_memo_key.ts +54 -0
  56. package/migrations/0034_workflow_signer_secrets.ts +42 -0
  57. package/migrations/0035_workflow_budgets.ts +53 -0
  58. package/migrations/0036_tx_confirmed_notify.ts +36 -0
  59. package/migrations/0037_nullable_api_key.ts +35 -0
  60. package/migrations/0038_drop_workflow_tables.ts +46 -0
  61. package/migrations/0039_tenants.ts +66 -0
  62. package/migrations/0040_tenant_key_generations.ts +29 -0
  63. package/migrations/0041_subgraphs_drop_api_key_id.ts +49 -0
  64. package/migrations/0042_tenant_project_id.ts +25 -0
  65. package/package.json +18 -2
@@ -19,7 +19,7 @@ import { sql } from "kysely";
19
19
  async function listPublicSubgraphs(db, opts = {}) {
20
20
  const limit = Math.min(Math.max(1, opts.limit ?? 50), 100);
21
21
  const offset = Math.max(0, opts.offset ?? 0);
22
- let query = db.selectFrom("subgraphs").innerJoin("api_keys", "api_keys.id", "subgraphs.api_key_id").innerJoin("accounts", "accounts.id", "api_keys.account_id").select([
22
+ let query = db.selectFrom("subgraphs").innerJoin("accounts", "accounts.id", "subgraphs.account_id").select([
23
23
  "subgraphs.id",
24
24
  "subgraphs.name",
25
25
  "subgraphs.description",
@@ -60,10 +60,7 @@ async function listPublicSubgraphs(db, opts = {}) {
60
60
  }
61
61
  if (opts.search) {
62
62
  const term = `%${opts.search}%`;
63
- countQuery = countQuery.where((eb) => eb.or([
64
- eb("name", "ilike", term),
65
- eb("description", "ilike", term)
66
- ]));
63
+ countQuery = countQuery.where((eb) => eb.or([eb("name", "ilike", term), eb("description", "ilike", term)]));
67
64
  }
68
65
  const [rows, countRow] = await Promise.all([
69
66
  query.limit(limit).offset(offset).execute(),
@@ -75,13 +72,13 @@ async function listPublicSubgraphs(db, opts = {}) {
75
72
  };
76
73
  }
77
74
  async function getPublicSubgraph(db, name) {
78
- return db.selectFrom("subgraphs").innerJoin("api_keys", "api_keys.id", "subgraphs.api_key_id").innerJoin("accounts", "accounts.id", "api_keys.account_id").selectAll("subgraphs").select(["accounts.display_name", "accounts.slug"]).where("subgraphs.name", "=", name).where("subgraphs.is_public", "=", true).executeTakeFirst();
75
+ return db.selectFrom("subgraphs").innerJoin("accounts", "accounts.id", "subgraphs.account_id").selectAll("subgraphs").select(["accounts.display_name", "accounts.slug"]).where("subgraphs.name", "=", name).where("subgraphs.is_public", "=", true).executeTakeFirst();
79
76
  }
80
77
  async function getCreatorProfile(db, slug) {
81
78
  const account = await db.selectFrom("accounts").select(["id", "display_name", "bio", "avatar_url", "slug"]).where("slug", "=", slug).executeTakeFirst();
82
79
  if (!account)
83
80
  return null;
84
- const subgraphs = await db.selectFrom("subgraphs").innerJoin("api_keys", "api_keys.id", "subgraphs.api_key_id").select([
81
+ const subgraphs = await db.selectFrom("subgraphs").select([
85
82
  "subgraphs.id",
86
83
  "subgraphs.name",
87
84
  "subgraphs.description",
@@ -94,7 +91,7 @@ async function getCreatorProfile(db, slug) {
94
91
  "subgraphs.total_processed",
95
92
  "subgraphs.created_at",
96
93
  sql`(SELECT COALESCE(SUM(query_count), 0) FROM subgraph_usage_daily WHERE subgraph_id = subgraphs.id AND date >= CURRENT_DATE - 7)::int`.as("queries_7d")
97
- ]).where("api_keys.account_id", "=", account.id).where("subgraphs.is_public", "=", true).orderBy("subgraphs.created_at", "desc").execute();
94
+ ]).where("subgraphs.account_id", "=", account.id).where("subgraphs.is_public", "=", true).orderBy("subgraphs.created_at", "desc").execute();
98
95
  return { account, subgraphs };
99
96
  }
100
97
  async function publishSubgraph(db, subgraphId, opts) {
@@ -138,5 +135,5 @@ export {
138
135
  getCreatorProfile
139
136
  };
140
137
 
141
- //# debugId=3D863C761F66BE2664756E2164756E21
138
+ //# debugId=C477C503DAA658BE64756E2164756E21
142
139
  //# sourceMappingURL=marketplace.js.map
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/queries/marketplace.ts"],
4
4
  "sourcesContent": [
5
- "import { type Kysely, sql } from \"kysely\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * List public subgraphs with creator info and usage stats.\n */\nexport async function listPublicSubgraphs(\n\tdb: Kysely<Database>,\n\topts: {\n\t\tlimit?: number;\n\t\toffset?: number;\n\t\ttags?: string[];\n\t\tsearch?: string;\n\t\tsort?: \"recent\" | \"popular\" | \"name\";\n\t} = {},\n): Promise<{ data: any[]; meta: { total: number; limit: number; offset: number } }> {\n\tconst limit = Math.min(Math.max(1, opts.limit ?? 50), 100);\n\tconst offset = Math.max(0, opts.offset ?? 0);\n\n\tlet query = db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"api_keys.id\", \"subgraphs.api_key_id\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"api_keys.account_id\")\n\t\t.select([\n\t\t\t\"subgraphs.id\",\n\t\t\t\"subgraphs.name\",\n\t\t\t\"subgraphs.description\",\n\t\t\t\"subgraphs.tags\",\n\t\t\t\"subgraphs.status\",\n\t\t\t\"subgraphs.version\",\n\t\t\t\"subgraphs.definition\",\n\t\t\t\"subgraphs.last_processed_block\",\n\t\t\t\"subgraphs.start_block\",\n\t\t\t\"subgraphs.total_processed\",\n\t\t\t\"subgraphs.created_at\",\n\t\t\t\"subgraphs.forked_from_id\",\n\t\t\t\"accounts.display_name\",\n\t\t\t\"accounts.slug\",\n\t\t\tsql<number>`(SELECT COALESCE(SUM(query_count), 0) FROM subgraph_usage_daily WHERE subgraph_id = subgraphs.id AND date >= CURRENT_DATE - 7)::int`.as(\"queries_7d\"),\n\t\t\tsql<number>`(SELECT COUNT(*) FROM subgraphs s2 WHERE s2.forked_from_id = subgraphs.id)::int`.as(\"fork_count\"),\n\t\t])\n\t\t.where(\"subgraphs.is_public\", \"=\", true);\n\n\t// Filter by tags (AND — all must match)\n\tif (opts.tags && opts.tags.length > 0) {\n\t\tquery = query.where(\n\t\t\tsql<boolean>`subgraphs.tags @> ${sql.val(opts.tags)}::text[]`,\n\t\t);\n\t}\n\n\t// Search by name or description\n\tif (opts.search) {\n\t\tconst term = `%${opts.search}%`;\n\t\tquery = query.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"subgraphs.name\", \"ilike\", term),\n\t\t\t\teb(\"subgraphs.description\", \"ilike\", term),\n\t\t\t]),\n\t\t);\n\t}\n\n\t// Sort\n\tif (opts.sort === \"popular\") {\n\t\tquery = query.orderBy(sql`queries_7d`, \"desc\");\n\t} else if (opts.sort === \"name\") {\n\t\tquery = query.orderBy(\"subgraphs.name\", \"asc\");\n\t} else {\n\t\t// Default: recent\n\t\tquery = query.orderBy(\"subgraphs.created_at\", \"desc\");\n\t}\n\n\t// Count\n\tlet countQuery = db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select(sql<number>`count(*)::int`.as(\"count\"))\n\t\t.where(\"is_public\", \"=\", true);\n\n\tif (opts.tags && opts.tags.length > 0) {\n\t\tcountQuery = countQuery.where(\n\t\t\tsql<boolean>`tags @> ${sql.val(opts.tags)}::text[]`,\n\t\t);\n\t}\n\tif (opts.search) {\n\t\tconst term = `%${opts.search}%`;\n\t\tcountQuery = countQuery.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"name\", \"ilike\", term),\n\t\t\t\teb(\"description\", \"ilike\", term),\n\t\t\t]),\n\t\t);\n\t}\n\n\tconst [rows, countRow] = await Promise.all([\n\t\tquery.limit(limit).offset(offset).execute(),\n\t\tcountQuery.executeTakeFirst(),\n\t]);\n\n\treturn {\n\t\tdata: rows,\n\t\tmeta: { total: countRow?.count ?? 0, limit, offset },\n\t};\n}\n\n/**\n * Get a single public subgraph by name with creator info.\n */\nexport async function getPublicSubgraph(db: Kysely<Database>, name: string): Promise<any | undefined> {\n\treturn db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"api_keys.id\", \"subgraphs.api_key_id\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"api_keys.account_id\")\n\t\t.selectAll(\"subgraphs\")\n\t\t.select([\"accounts.display_name\", \"accounts.slug\"])\n\t\t.where(\"subgraphs.name\", \"=\", name)\n\t\t.where(\"subgraphs.is_public\", \"=\", true)\n\t\t.executeTakeFirst();\n}\n\n/**\n * Get a creator profile by slug with their public subgraphs.\n */\nexport async function getCreatorProfile(db: Kysely<Database>, slug: string): Promise<{ account: any; subgraphs: any[] } | null> {\n\tconst account = await db\n\t\t.selectFrom(\"accounts\")\n\t\t.select([\"id\", \"display_name\", \"bio\", \"avatar_url\", \"slug\"])\n\t\t.where(\"slug\", \"=\", slug)\n\t\t.executeTakeFirst();\n\n\tif (!account) return null;\n\n\tconst subgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"api_keys.id\", \"subgraphs.api_key_id\")\n\t\t.select([\n\t\t\t\"subgraphs.id\",\n\t\t\t\"subgraphs.name\",\n\t\t\t\"subgraphs.description\",\n\t\t\t\"subgraphs.tags\",\n\t\t\t\"subgraphs.status\",\n\t\t\t\"subgraphs.version\",\n\t\t\t\"subgraphs.definition\",\n\t\t\t\"subgraphs.last_processed_block\",\n\t\t\t\"subgraphs.start_block\",\n\t\t\t\"subgraphs.total_processed\",\n\t\t\t\"subgraphs.created_at\",\n\t\t\tsql<number>`(SELECT COALESCE(SUM(query_count), 0) FROM subgraph_usage_daily WHERE subgraph_id = subgraphs.id AND date >= CURRENT_DATE - 7)::int`.as(\"queries_7d\"),\n\t\t])\n\t\t.where(\"api_keys.account_id\", \"=\", account.id)\n\t\t.where(\"subgraphs.is_public\", \"=\", true)\n\t\t.orderBy(\"subgraphs.created_at\", \"desc\")\n\t\t.execute();\n\n\treturn { account, subgraphs };\n}\n\n/**\n * Publish a subgraph (set is_public = true).\n */\nexport async function publishSubgraph(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\topts?: { tags?: string[]; description?: string },\n): Promise<Subgraph> {\n\tconst set: Record<string, unknown> = {\n\t\tis_public: true,\n\t\tupdated_at: new Date(),\n\t};\n\tif (opts?.tags) set.tags = sql`${sql.val(opts.tags)}::text[]`;\n\tif (opts?.description !== undefined) set.description = opts.description;\n\n\treturn db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set(set)\n\t\t.where(\"id\", \"=\", subgraphId)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\n/**\n * Unpublish a subgraph (set is_public = false).\n */\nexport async function unpublishSubgraph(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<Subgraph> {\n\treturn db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ is_public: false, updated_at: new Date() })\n\t\t.where(\"id\", \"=\", subgraphId)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\n/**\n * Increment per-subgraph query count for today. Fire-and-forget safe.\n */\nexport async function incrementSubgraphQueryCount(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait sql`\n\t\tINSERT INTO subgraph_usage_daily (subgraph_id, date, query_count)\n\t\tVALUES (${subgraphId}, ${today}, 1)\n\t\tON CONFLICT (subgraph_id, date)\n\t\tDO UPDATE SET query_count = subgraph_usage_daily.query_count + 1\n\t`.execute(db);\n}\n\n/**\n * Get daily usage history for a subgraph.\n */\nexport async function getSubgraphUsageHistory(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tdays: number,\n): Promise<Array<{ date: string; query_count: number }>> {\n\treturn db\n\t\t.selectFrom(\"subgraph_usage_daily\")\n\t\t.select([\"date\", \"query_count\"])\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"date\", \">=\", sql<string>`CURRENT_DATE - ${days}::int`)\n\t\t.orderBy(\"date\", \"asc\")\n\t\t.execute();\n}\n\n/**\n * Get total query count for a subgraph over last N days.\n */\nexport async function getSubgraphQueryTotal(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tdays: number,\n): Promise<number> {\n\tconst row = await db\n\t\t.selectFrom(\"subgraph_usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(query_count), 0)::int`.as(\"total\"))\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"date\", \">=\", sql<string>`CURRENT_DATE - ${days}::int`)\n\t\t.executeTakeFirst();\n\treturn row?.total ?? 0;\n}\n"
5
+ "import { type Kysely, sql } from \"kysely\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * List public subgraphs with creator info and usage stats.\n */\nexport async function listPublicSubgraphs(\n\tdb: Kysely<Database>,\n\topts: {\n\t\tlimit?: number;\n\t\toffset?: number;\n\t\ttags?: string[];\n\t\tsearch?: string;\n\t\tsort?: \"recent\" | \"popular\" | \"name\";\n\t} = {},\n): Promise<{\n\tdata: any[];\n\tmeta: { total: number; limit: number; offset: number };\n}> {\n\tconst limit = Math.min(Math.max(1, opts.limit ?? 50), 100);\n\tconst offset = Math.max(0, opts.offset ?? 0);\n\n\tlet query = db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"subgraphs.account_id\")\n\t\t.select([\n\t\t\t\"subgraphs.id\",\n\t\t\t\"subgraphs.name\",\n\t\t\t\"subgraphs.description\",\n\t\t\t\"subgraphs.tags\",\n\t\t\t\"subgraphs.status\",\n\t\t\t\"subgraphs.version\",\n\t\t\t\"subgraphs.definition\",\n\t\t\t\"subgraphs.last_processed_block\",\n\t\t\t\"subgraphs.start_block\",\n\t\t\t\"subgraphs.total_processed\",\n\t\t\t\"subgraphs.created_at\",\n\t\t\t\"subgraphs.forked_from_id\",\n\t\t\t\"accounts.display_name\",\n\t\t\t\"accounts.slug\",\n\t\t\tsql<number>`(SELECT COALESCE(SUM(query_count), 0) FROM subgraph_usage_daily WHERE subgraph_id = subgraphs.id AND date >= CURRENT_DATE - 7)::int`.as(\n\t\t\t\t\"queries_7d\",\n\t\t\t),\n\t\t\tsql<number>`(SELECT COUNT(*) FROM subgraphs s2 WHERE s2.forked_from_id = subgraphs.id)::int`.as(\n\t\t\t\t\"fork_count\",\n\t\t\t),\n\t\t])\n\t\t.where(\"subgraphs.is_public\", \"=\", true);\n\n\t// Filter by tags (AND — all must match)\n\tif (opts.tags && opts.tags.length > 0) {\n\t\tquery = query.where(\n\t\t\tsql<boolean>`subgraphs.tags @> ${sql.val(opts.tags)}::text[]`,\n\t\t);\n\t}\n\n\t// Search by name or description\n\tif (opts.search) {\n\t\tconst term = `%${opts.search}%`;\n\t\tquery = query.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"subgraphs.name\", \"ilike\", term),\n\t\t\t\teb(\"subgraphs.description\", \"ilike\", term),\n\t\t\t]),\n\t\t);\n\t}\n\n\t// Sort\n\tif (opts.sort === \"popular\") {\n\t\tquery = query.orderBy(sql`queries_7d`, \"desc\");\n\t} else if (opts.sort === \"name\") {\n\t\tquery = query.orderBy(\"subgraphs.name\", \"asc\");\n\t} else {\n\t\t// Default: recent\n\t\tquery = query.orderBy(\"subgraphs.created_at\", \"desc\");\n\t}\n\n\t// Count\n\tlet countQuery = db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select(sql<number>`count(*)::int`.as(\"count\"))\n\t\t.where(\"is_public\", \"=\", true);\n\n\tif (opts.tags && opts.tags.length > 0) {\n\t\tcountQuery = countQuery.where(\n\t\t\tsql<boolean>`tags @> ${sql.val(opts.tags)}::text[]`,\n\t\t);\n\t}\n\tif (opts.search) {\n\t\tconst term = `%${opts.search}%`;\n\t\tcountQuery = countQuery.where((eb) =>\n\t\t\teb.or([eb(\"name\", \"ilike\", term), eb(\"description\", \"ilike\", term)]),\n\t\t);\n\t}\n\n\tconst [rows, countRow] = await Promise.all([\n\t\tquery.limit(limit).offset(offset).execute(),\n\t\tcountQuery.executeTakeFirst(),\n\t]);\n\n\treturn {\n\t\tdata: rows,\n\t\tmeta: { total: countRow?.count ?? 0, limit, offset },\n\t};\n}\n\n/**\n * Get a single public subgraph by name with creator info.\n */\nexport async function getPublicSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n): Promise<any | undefined> {\n\treturn db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"subgraphs.account_id\")\n\t\t.selectAll(\"subgraphs\")\n\t\t.select([\"accounts.display_name\", \"accounts.slug\"])\n\t\t.where(\"subgraphs.name\", \"=\", name)\n\t\t.where(\"subgraphs.is_public\", \"=\", true)\n\t\t.executeTakeFirst();\n}\n\n/**\n * Get a creator profile by slug with their public subgraphs.\n */\nexport async function getCreatorProfile(\n\tdb: Kysely<Database>,\n\tslug: string,\n): Promise<{ account: any; subgraphs: any[] } | null> {\n\tconst account = await db\n\t\t.selectFrom(\"accounts\")\n\t\t.select([\"id\", \"display_name\", \"bio\", \"avatar_url\", \"slug\"])\n\t\t.where(\"slug\", \"=\", slug)\n\t\t.executeTakeFirst();\n\n\tif (!account) return null;\n\n\tconst subgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select([\n\t\t\t\"subgraphs.id\",\n\t\t\t\"subgraphs.name\",\n\t\t\t\"subgraphs.description\",\n\t\t\t\"subgraphs.tags\",\n\t\t\t\"subgraphs.status\",\n\t\t\t\"subgraphs.version\",\n\t\t\t\"subgraphs.definition\",\n\t\t\t\"subgraphs.last_processed_block\",\n\t\t\t\"subgraphs.start_block\",\n\t\t\t\"subgraphs.total_processed\",\n\t\t\t\"subgraphs.created_at\",\n\t\t\tsql<number>`(SELECT COALESCE(SUM(query_count), 0) FROM subgraph_usage_daily WHERE subgraph_id = subgraphs.id AND date >= CURRENT_DATE - 7)::int`.as(\n\t\t\t\t\"queries_7d\",\n\t\t\t),\n\t\t])\n\t\t.where(\"subgraphs.account_id\", \"=\", account.id)\n\t\t.where(\"subgraphs.is_public\", \"=\", true)\n\t\t.orderBy(\"subgraphs.created_at\", \"desc\")\n\t\t.execute();\n\n\treturn { account, subgraphs };\n}\n\n/**\n * Publish a subgraph (set is_public = true).\n */\nexport async function publishSubgraph(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\topts?: { tags?: string[]; description?: string },\n): Promise<Subgraph> {\n\tconst set: Record<string, unknown> = {\n\t\tis_public: true,\n\t\tupdated_at: new Date(),\n\t};\n\tif (opts?.tags) set.tags = sql`${sql.val(opts.tags)}::text[]`;\n\tif (opts?.description !== undefined) set.description = opts.description;\n\n\treturn db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set(set)\n\t\t.where(\"id\", \"=\", subgraphId)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\n/**\n * Unpublish a subgraph (set is_public = false).\n */\nexport async function unpublishSubgraph(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<Subgraph> {\n\treturn db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ is_public: false, updated_at: new Date() })\n\t\t.where(\"id\", \"=\", subgraphId)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\n/**\n * Increment per-subgraph query count for today. Fire-and-forget safe.\n */\nexport async function incrementSubgraphQueryCount(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait sql`\n\t\tINSERT INTO subgraph_usage_daily (subgraph_id, date, query_count)\n\t\tVALUES (${subgraphId}, ${today}, 1)\n\t\tON CONFLICT (subgraph_id, date)\n\t\tDO UPDATE SET query_count = subgraph_usage_daily.query_count + 1\n\t`.execute(db);\n}\n\n/**\n * Get daily usage history for a subgraph.\n */\nexport async function getSubgraphUsageHistory(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tdays: number,\n): Promise<Array<{ date: string; query_count: number }>> {\n\treturn db\n\t\t.selectFrom(\"subgraph_usage_daily\")\n\t\t.select([\"date\", \"query_count\"])\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"date\", \">=\", sql<string>`CURRENT_DATE - ${days}::int`)\n\t\t.orderBy(\"date\", \"asc\")\n\t\t.execute();\n}\n\n/**\n * Get total query count for a subgraph over last N days.\n */\nexport async function getSubgraphQueryTotal(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tdays: number,\n): Promise<number> {\n\tconst row = await db\n\t\t.selectFrom(\"subgraph_usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(query_count), 0)::int`.as(\"total\"))\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"date\", \">=\", sql<string>`CURRENT_DATE - ${days}::int`)\n\t\t.executeTakeFirst();\n\treturn row?.total ?? 0;\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "3D863C761F66BE2664756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "C477C503DAA658BE64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  import { Kysely } from "kysely";
2
- import { Generated, Selectable } from "kysely";
2
+ import { ColumnType, Generated, Selectable } from "kysely";
3
3
  interface BlocksTable {
4
4
  height: number;
5
5
  hash: string;
@@ -56,7 +56,6 @@ interface SubgraphsTable {
56
56
  last_error_at: Date | null;
57
57
  total_processed: Generated<number>;
58
58
  total_errors: Generated<number>;
59
- api_key_id: string | null;
60
59
  account_id: string;
61
60
  handler_code: string | null;
62
61
  source_code: string | null;
@@ -295,6 +294,8 @@ interface WorkflowStepsTable {
295
294
  started_at: Date | null;
296
295
  completed_at: Date | null;
297
296
  duration_ms: number | null;
297
+ memo_key: string | null;
298
+ parent_step_id: string | null;
298
299
  created_at: Generated<Date>;
299
300
  }
300
301
  interface WorkflowQueueTable {
@@ -356,6 +357,62 @@ interface Database {
356
357
  workflow_queue: WorkflowQueueTable;
357
358
  workflow_schedules: WorkflowSchedulesTable;
358
359
  workflow_cursors: WorkflowCursorsTable;
360
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
361
+ workflow_budgets: WorkflowBudgetsTable;
362
+ tenants: TenantsTable;
363
+ }
364
+ type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
365
+ interface TenantsTable {
366
+ id: Generated<string>;
367
+ account_id: string;
368
+ slug: string;
369
+ status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
370
+ plan: string;
371
+ cpus: ColumnType<number, number | string, number | string>;
372
+ memory_mb: number;
373
+ storage_limit_mb: number;
374
+ storage_used_mb: number | null;
375
+ pg_container_id: string | null;
376
+ api_container_id: string | null;
377
+ processor_container_id: string | null;
378
+ target_database_url_enc: Buffer;
379
+ tenant_jwt_secret_enc: Buffer;
380
+ anon_key_enc: Buffer;
381
+ service_key_enc: Buffer;
382
+ api_url_internal: string;
383
+ api_url_public: string;
384
+ trial_ends_at: Date;
385
+ suspended_at: Date | null;
386
+ last_health_check_at: Date | null;
387
+ service_gen: Generated<number>;
388
+ anon_gen: Generated<number>;
389
+ project_id: string | null;
390
+ created_at: Generated<Date>;
391
+ updated_at: Generated<Date>;
392
+ }
393
+ interface WorkflowBudgetsTable {
394
+ id: Generated<string>;
395
+ workflow_definition_id: string;
396
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
397
+ period: string;
398
+ ai_usd_used: Generated<string>;
399
+ ai_tokens_used: Generated<string>;
400
+ chain_microstx_used: Generated<string>;
401
+ chain_tx_count: Generated<number>;
402
+ run_count: Generated<number>;
403
+ step_count: Generated<number>;
404
+ reset_at: Date;
405
+ created_at: Generated<Date>;
406
+ updated_at: Generated<Date>;
407
+ }
408
+ interface WorkflowSignerSecretsTable {
409
+ id: Generated<string>;
410
+ account_id: string;
411
+ name: string;
412
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
413
+ encrypted_value: Buffer;
414
+ created_at: Generated<Date>;
415
+ updated_at: Generated<Date>;
359
416
  }
360
417
  type Project = Selectable<ProjectsTable>;
361
418
  type TeamInvitation = Selectable<TeamInvitationsTable>;
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/queries/projects.ts"],
4
4
  "sourcesContent": [
5
- "import type { Kysely } from \"kysely\";\nimport type { Database, Project, TeamInvitation } from \"../types.ts\";\n\nexport async function getProjectsByAccount(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<Project[]> {\n\treturn db\n\t\t.selectFrom(\"projects\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"created_at\", \"asc\")\n\t\t.execute();\n}\n\nexport async function getProjectBySlug(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tslug: string,\n): Promise<Project | undefined> {\n\treturn db\n\t\t.selectFrom(\"projects\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"slug\", \"=\", slug)\n\t\t.executeTakeFirst();\n}\n\nexport async function getTeamMembers(\n\tdb: Kysely<Database>,\n\tprojectId: string,\n): Promise<Array<{\n\tid: string;\n\trole: string;\n\tcreated_at: Date;\n\taccount_id: string;\n\temail: string;\n\tdisplay_name: string | null;\n\tavatar_url: string | null;\n\taccount_slug: string | null;\n}>> {\n\treturn db\n\t\t.selectFrom(\"team_members\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"team_members.account_id\")\n\t\t.select([\n\t\t\t\"team_members.id\",\n\t\t\t\"team_members.role\",\n\t\t\t\"team_members.created_at\",\n\t\t\t\"accounts.id as account_id\",\n\t\t\t\"accounts.email\",\n\t\t\t\"accounts.display_name\",\n\t\t\t\"accounts.avatar_url\",\n\t\t\t\"accounts.slug as account_slug\",\n\t\t])\n\t\t.where(\"team_members.project_id\", \"=\", projectId)\n\t\t.orderBy(\"team_members.created_at\", \"asc\")\n\t\t.execute();\n}\n\nexport async function getTeamInvitations(\n\tdb: Kysely<Database>,\n\tprojectId: string,\n): Promise<TeamInvitation[]> {\n\treturn db\n\t\t.selectFrom(\"team_invitations\")\n\t\t.selectAll()\n\t\t.where(\"project_id\", \"=\", projectId)\n\t\t.where(\"accepted_at\", \"is\", null)\n\t\t.orderBy(\"created_at\", \"desc\")\n\t\t.execute();\n}\n"
5
+ "import type { Kysely } from \"kysely\";\nimport type { Database, Project, TeamInvitation } from \"../types.ts\";\n\nexport async function getProjectsByAccount(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<Project[]> {\n\treturn db\n\t\t.selectFrom(\"projects\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"created_at\", \"asc\")\n\t\t.execute();\n}\n\nexport async function getProjectBySlug(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tslug: string,\n): Promise<Project | undefined> {\n\treturn db\n\t\t.selectFrom(\"projects\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"slug\", \"=\", slug)\n\t\t.executeTakeFirst();\n}\n\nexport async function getTeamMembers(\n\tdb: Kysely<Database>,\n\tprojectId: string,\n): Promise<\n\tArray<{\n\t\tid: string;\n\t\trole: string;\n\t\tcreated_at: Date;\n\t\taccount_id: string;\n\t\temail: string;\n\t\tdisplay_name: string | null;\n\t\tavatar_url: string | null;\n\t\taccount_slug: string | null;\n\t}>\n> {\n\treturn db\n\t\t.selectFrom(\"team_members\")\n\t\t.innerJoin(\"accounts\", \"accounts.id\", \"team_members.account_id\")\n\t\t.select([\n\t\t\t\"team_members.id\",\n\t\t\t\"team_members.role\",\n\t\t\t\"team_members.created_at\",\n\t\t\t\"accounts.id as account_id\",\n\t\t\t\"accounts.email\",\n\t\t\t\"accounts.display_name\",\n\t\t\t\"accounts.avatar_url\",\n\t\t\t\"accounts.slug as account_slug\",\n\t\t])\n\t\t.where(\"team_members.project_id\", \"=\", projectId)\n\t\t.orderBy(\"team_members.created_at\", \"asc\")\n\t\t.execute();\n}\n\nexport async function getTeamInvitations(\n\tdb: Kysely<Database>,\n\tprojectId: string,\n): Promise<TeamInvitation[]> {\n\treturn db\n\t\t.selectFrom(\"team_invitations\")\n\t\t.selectAll()\n\t\t.where(\"project_id\", \"=\", projectId)\n\t\t.where(\"accepted_at\", \"is\", null)\n\t\t.orderBy(\"created_at\", \"desc\")\n\t\t.execute();\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;AAGA,eAAsB,oBAAoB,CACzC,IACA,WACqB;AAAA,EACrB,OAAO,GACL,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,QAAQ,cAAc,KAAK,EAC3B,QAAQ;AAAA;AAGX,eAAsB,gBAAgB,CACrC,IACA,WACA,MAC+B;AAAA,EAC/B,OAAO,GACL,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,QAAQ,KAAK,IAAI,EACvB,iBAAiB;AAAA;AAGpB,eAAsB,cAAc,CACnC,IACA,WAUG;AAAA,EACH,OAAO,GACL,WAAW,cAAc,EACzB,UAAU,YAAY,eAAe,yBAAyB,EAC9D,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC,EACA,MAAM,2BAA2B,KAAK,SAAS,EAC/C,QAAQ,2BAA2B,KAAK,EACxC,QAAQ;AAAA;AAGX,eAAsB,kBAAkB,CACvC,IACA,WAC4B;AAAA,EAC5B,OAAO,GACL,WAAW,kBAAkB,EAC7B,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,eAAe,MAAM,IAAI,EAC/B,QAAQ,cAAc,MAAM,EAC5B,QAAQ;AAAA;",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAGA,eAAsB,oBAAoB,CACzC,IACA,WACqB;AAAA,EACrB,OAAO,GACL,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,QAAQ,cAAc,KAAK,EAC3B,QAAQ;AAAA;AAGX,eAAsB,gBAAgB,CACrC,IACA,WACA,MAC+B;AAAA,EAC/B,OAAO,GACL,WAAW,UAAU,EACrB,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,QAAQ,KAAK,IAAI,EACvB,iBAAiB;AAAA;AAGpB,eAAsB,cAAc,CACnC,IACA,WAYC;AAAA,EACD,OAAO,GACL,WAAW,cAAc,EACzB,UAAU,YAAY,eAAe,yBAAyB,EAC9D,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC,EACA,MAAM,2BAA2B,KAAK,SAAS,EAC/C,QAAQ,2BAA2B,KAAK,EACxC,QAAQ;AAAA;AAGX,eAAsB,kBAAkB,CACvC,IACA,WAC4B;AAAA,EAC5B,OAAO,GACL,WAAW,kBAAkB,EAC7B,UAAU,EACV,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,eAAe,MAAM,IAAI,EAC/B,QAAQ,cAAc,MAAM,EAC5B,QAAQ;AAAA;",
8
8
  "debugId": "F62DBD8C7A91B89F64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  import { Kysely } from "kysely";
2
- import { Generated } from "kysely";
2
+ import { ColumnType, Generated } from "kysely";
3
3
  interface BlocksTable {
4
4
  height: number;
5
5
  hash: string;
@@ -56,7 +56,6 @@ interface SubgraphsTable {
56
56
  last_error_at: Date | null;
57
57
  total_processed: Generated<number>;
58
58
  total_errors: Generated<number>;
59
- api_key_id: string | null;
60
59
  account_id: string;
61
60
  handler_code: string | null;
62
61
  source_code: string | null;
@@ -295,6 +294,8 @@ interface WorkflowStepsTable {
295
294
  started_at: Date | null;
296
295
  completed_at: Date | null;
297
296
  duration_ms: number | null;
297
+ memo_key: string | null;
298
+ parent_step_id: string | null;
298
299
  created_at: Generated<Date>;
299
300
  }
300
301
  interface WorkflowQueueTable {
@@ -356,6 +357,62 @@ interface Database {
356
357
  workflow_queue: WorkflowQueueTable;
357
358
  workflow_schedules: WorkflowSchedulesTable;
358
359
  workflow_cursors: WorkflowCursorsTable;
360
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
361
+ workflow_budgets: WorkflowBudgetsTable;
362
+ tenants: TenantsTable;
363
+ }
364
+ type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
365
+ interface TenantsTable {
366
+ id: Generated<string>;
367
+ account_id: string;
368
+ slug: string;
369
+ status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
370
+ plan: string;
371
+ cpus: ColumnType<number, number | string, number | string>;
372
+ memory_mb: number;
373
+ storage_limit_mb: number;
374
+ storage_used_mb: number | null;
375
+ pg_container_id: string | null;
376
+ api_container_id: string | null;
377
+ processor_container_id: string | null;
378
+ target_database_url_enc: Buffer;
379
+ tenant_jwt_secret_enc: Buffer;
380
+ anon_key_enc: Buffer;
381
+ service_key_enc: Buffer;
382
+ api_url_internal: string;
383
+ api_url_public: string;
384
+ trial_ends_at: Date;
385
+ suspended_at: Date | null;
386
+ last_health_check_at: Date | null;
387
+ service_gen: Generated<number>;
388
+ anon_gen: Generated<number>;
389
+ project_id: string | null;
390
+ created_at: Generated<Date>;
391
+ updated_at: Generated<Date>;
392
+ }
393
+ interface WorkflowBudgetsTable {
394
+ id: Generated<string>;
395
+ workflow_definition_id: string;
396
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
397
+ period: string;
398
+ ai_usd_used: Generated<string>;
399
+ ai_tokens_used: Generated<string>;
400
+ chain_microstx_used: Generated<string>;
401
+ chain_tx_count: Generated<number>;
402
+ run_count: Generated<number>;
403
+ step_count: Generated<number>;
404
+ reset_at: Date;
405
+ created_at: Generated<Date>;
406
+ updated_at: Generated<Date>;
407
+ }
408
+ interface WorkflowSignerSecretsTable {
409
+ id: Generated<string>;
410
+ account_id: string;
411
+ name: string;
412
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
413
+ encrypted_value: Buffer;
414
+ created_at: Generated<Date>;
415
+ updated_at: Generated<Date>;
359
416
  }
360
417
  interface GapRange {
361
418
  start: number;
@@ -1,5 +1,5 @@
1
1
  import { Kysely } from "kysely";
2
- import { Generated, Selectable } from "kysely";
2
+ import { ColumnType, Generated, Selectable } from "kysely";
3
3
  interface BlocksTable {
4
4
  height: number;
5
5
  hash: string;
@@ -56,7 +56,6 @@ interface SubgraphsTable {
56
56
  last_error_at: Date | null;
57
57
  total_processed: Generated<number>;
58
58
  total_errors: Generated<number>;
59
- api_key_id: string | null;
60
59
  account_id: string;
61
60
  handler_code: string | null;
62
61
  source_code: string | null;
@@ -295,6 +294,8 @@ interface WorkflowStepsTable {
295
294
  started_at: Date | null;
296
295
  completed_at: Date | null;
297
296
  duration_ms: number | null;
297
+ memo_key: string | null;
298
+ parent_step_id: string | null;
298
299
  created_at: Generated<Date>;
299
300
  }
300
301
  interface WorkflowQueueTable {
@@ -356,14 +357,71 @@ interface Database {
356
357
  workflow_queue: WorkflowQueueTable;
357
358
  workflow_schedules: WorkflowSchedulesTable;
358
359
  workflow_cursors: WorkflowCursorsTable;
360
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
361
+ workflow_budgets: WorkflowBudgetsTable;
362
+ tenants: TenantsTable;
363
+ }
364
+ type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
365
+ interface TenantsTable {
366
+ id: Generated<string>;
367
+ account_id: string;
368
+ slug: string;
369
+ status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
370
+ plan: string;
371
+ cpus: ColumnType<number, number | string, number | string>;
372
+ memory_mb: number;
373
+ storage_limit_mb: number;
374
+ storage_used_mb: number | null;
375
+ pg_container_id: string | null;
376
+ api_container_id: string | null;
377
+ processor_container_id: string | null;
378
+ target_database_url_enc: Buffer;
379
+ tenant_jwt_secret_enc: Buffer;
380
+ anon_key_enc: Buffer;
381
+ service_key_enc: Buffer;
382
+ api_url_internal: string;
383
+ api_url_public: string;
384
+ trial_ends_at: Date;
385
+ suspended_at: Date | null;
386
+ last_health_check_at: Date | null;
387
+ service_gen: Generated<number>;
388
+ anon_gen: Generated<number>;
389
+ project_id: string | null;
390
+ created_at: Generated<Date>;
391
+ updated_at: Generated<Date>;
392
+ }
393
+ interface WorkflowBudgetsTable {
394
+ id: Generated<string>;
395
+ workflow_definition_id: string;
396
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
397
+ period: string;
398
+ ai_usd_used: Generated<string>;
399
+ ai_tokens_used: Generated<string>;
400
+ chain_microstx_used: Generated<string>;
401
+ chain_tx_count: Generated<number>;
402
+ run_count: Generated<number>;
403
+ step_count: Generated<number>;
404
+ reset_at: Date;
405
+ created_at: Generated<Date>;
406
+ updated_at: Generated<Date>;
407
+ }
408
+ interface WorkflowSignerSecretsTable {
409
+ id: Generated<string>;
410
+ account_id: string;
411
+ name: string;
412
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
413
+ encrypted_value: Buffer;
414
+ created_at: Generated<Date>;
415
+ updated_at: Generated<Date>;
359
416
  }
360
417
  type Subgraph = Selectable<SubgraphsTable>;
361
418
  /**
362
419
  * Convert a subgraph name to its PostgreSQL schema name.
363
- * With accountPrefix (first 8 chars of account_id): "subgraph_{prefix}_{name}"
364
- * Without prefix: "subgraph_{name}" (backward compat / local dev)
420
+ * Every tenant DB has its own isolated schema namespace, so there's no
421
+ * account-prefix disambiguation needed every subgraph within a tenant
422
+ * just maps to `subgraph_{safeName}`.
365
423
  */
366
- declare function pgSchemaName(subgraphName: string, accountPrefix?: string): string;
424
+ declare function pgSchemaName(subgraphName: string): string;
367
425
  declare function registerSubgraph(db: Kysely<Database>, data: {
368
426
  name: string
369
427
  version: string
@@ -33,13 +33,9 @@ function parseJsonb(value) {
33
33
 
34
34
  // src/db/queries/subgraphs.ts
35
35
  import { sql as sql2 } from "kysely";
36
- function pgSchemaName(subgraphName, accountPrefix) {
36
+ function pgSchemaName(subgraphName) {
37
37
  const safeName = subgraphName.replace(/-/g, "_");
38
- if (!accountPrefix) {
39
- return `subgraph_${safeName}`;
40
- }
41
- const safePrefix = accountPrefix.replace(/-/g, "_");
42
- return `subgraph_${safePrefix}_${safeName}`;
38
+ return `subgraph_${safeName}`;
43
39
  }
44
40
  async function registerSubgraph(db, data) {
45
41
  return await db.insertInto("subgraphs").values({
@@ -48,7 +44,6 @@ async function registerSubgraph(db, data) {
48
44
  definition: jsonb(data.definition),
49
45
  schema_hash: data.schemaHash,
50
46
  handler_path: data.handlerPath,
51
- api_key_id: data.apiKeyId ?? null,
52
47
  account_id: data.accountId ?? "",
53
48
  handler_code: data.handlerCode ?? null,
54
49
  source_code: data.sourceCode ?? null,
@@ -62,7 +57,6 @@ async function registerSubgraph(db, data) {
62
57
  handler_path: data.handlerPath,
63
58
  handler_code: data.handlerCode ?? null,
64
59
  source_code: data.sourceCode ?? null,
65
- api_key_id: data.apiKeyId ?? null,
66
60
  schema_name: data.schemaName ?? null,
67
61
  start_block: data.startBlock ?? 0,
68
62
  updated_at: new Date
@@ -120,5 +114,5 @@ export {
120
114
  deleteSubgraph
121
115
  };
122
116
 
123
- //# debugId=AE95492717422CEB64756E2164756E21
117
+ //# debugId=AE963057007E387C64756E2164756E21
124
118
  //# sourceMappingURL=subgraphs.js.map
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/queries/subgraphs.ts"],
4
4
  "sourcesContent": [
5
- "import { type RawBuilder, sql } 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\tconst escaped = JSON.stringify(value, (_k, v) => (typeof v === \"bigint\" ? v.toString() : v)).replace(/'/g, \"''\");\n\treturn 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\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T;\n\t\t} catch {\n\t\t\treturn value as T;\n\t\t}\n\t}\n\treturn (value ?? {}) as T;\n}\n",
6
- "import { type Kysely, sql } 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 accountPrefix (first 8 chars of account_id): \"subgraph_{prefix}_{name}\"\n * Without prefix: \"subgraph_{name}\" (backward compat / local dev)\n */\nexport function pgSchemaName(\n\tsubgraphName: string,\n\taccountPrefix?: string,\n): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\tif (!accountPrefix) {\n\t\treturn `subgraph_${safeName}`;\n\t}\n\tconst safePrefix = accountPrefix.replace(/-/g, \"_\");\n\treturn `subgraph_${safePrefix}_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\tforkedFromId?: string;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values({\n\t\t\tname: data.name,\n\t\t\tversion: data.version,\n\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\tschema_hash: data.schemaHash,\n\t\t\thandler_path: data.handlerPath,\n\t\t\tapi_key_id: data.apiKeyId ?? null,\n\t\t\taccount_id: data.accountId ?? \"\",\n\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\tschema_name: data.schemaName ?? null,\n\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\tforked_from_id: data.forkedFromId ?? null,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet({\n\t\t\t\tversion: data.version,\n\t\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\t\tschema_hash: data.schemaHash,\n\t\t\t\thandler_path: data.handlerPath,\n\t\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\t\tapi_key_id: data.apiKeyId ?? null,\n\t\t\t\tschema_name: data.schemaName ?? null,\n\t\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t}),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ handler_path: handlerPath, updated_at: new Date() })\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within)\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n"
5
+ "import { type RawBuilder, sql } 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\tconst escaped = JSON.stringify(value, (_k, v) =>\n\t\ttypeof v === \"bigint\" ? v.toString() : v,\n\t).replace(/'/g, \"''\");\n\treturn 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\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T;\n\t\t} catch {\n\t\t\treturn value as T;\n\t\t}\n\t}\n\treturn (value ?? {}) as T;\n}\n",
6
+ "import { type Kysely, sql } 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 * Every tenant DB has its own isolated schema namespace, so there's no\n * account-prefix disambiguation needed every subgraph within a tenant\n * just maps to `subgraph_{safeName}`.\n */\nexport function pgSchemaName(subgraphName: string): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\tforkedFromId?: string;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values({\n\t\t\tname: data.name,\n\t\t\tversion: data.version,\n\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\tschema_hash: data.schemaHash,\n\t\t\thandler_path: data.handlerPath,\n\t\t\taccount_id: data.accountId ?? \"\",\n\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\tschema_name: data.schemaName ?? null,\n\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\tforked_from_id: data.forkedFromId ?? null,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet({\n\t\t\t\tversion: data.version,\n\t\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\t\tschema_hash: data.schemaHash,\n\t\t\t\thandler_path: data.handlerPath,\n\t\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\t\tschema_name: data.schemaName ?? null,\n\t\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t}),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ handler_path: handlerPath, updated_at: new Date() })\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within)\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "AE95492717422CEB64756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "AE963057007E387C64756E2164756E21",
10
10
  "names": []
11
11
  }