@secondlayer/shared 0.12.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -7
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.js.map +2 -2
- package/dist/src/crypto/secrets.d.ts +5 -0
- package/dist/src/crypto/secrets.js +69 -0
- package/dist/src/crypto/secrets.js.map +10 -0
- package/dist/src/db/index.d.ts +37 -64
- package/dist/src/db/index.js +2 -2
- package/dist/src/db/index.js.map +2 -2
- package/dist/src/db/queries/accounts.d.ts +30 -51
- package/dist/src/db/queries/integrity.d.ts +30 -51
- package/dist/src/db/queries/marketplace.d.ts +30 -51
- package/dist/src/db/queries/projects.d.ts +30 -51
- package/dist/src/db/queries/subgraph-gaps.d.ts +30 -51
- package/dist/src/db/queries/subgraphs.d.ts +31 -51
- package/dist/src/db/queries/subgraphs.js +3 -1
- package/dist/src/db/queries/subgraphs.js.map +3 -3
- package/dist/src/db/queries/usage.d.ts +31 -56
- package/dist/src/db/queries/usage.js +1 -19
- package/dist/src/db/queries/usage.js.map +4 -4
- package/dist/src/db/queries/workflows.d.ts +35 -53
- package/dist/src/db/queries/workflows.js +130 -13
- package/dist/src/db/queries/workflows.js.map +5 -4
- package/dist/src/db/schema.d.ts +37 -64
- package/dist/src/errors.d.ts +19 -50
- package/dist/src/errors.js +28 -45
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +59 -256
- package/dist/src/index.js +32 -234
- package/dist/src/index.js.map +7 -9
- package/dist/src/lib/plans.d.ts +0 -1
- package/dist/src/lib/plans.js +1 -2
- package/dist/src/lib/plans.js.map +3 -3
- package/dist/src/node/local-client.d.ts +30 -51
- package/dist/src/pricing.d.ts +28 -0
- package/dist/src/pricing.js +47 -0
- package/dist/src/pricing.js.map +10 -0
- package/dist/src/queue/listener.d.ts +1 -18
- package/dist/src/queue/listener.js +2 -12
- package/dist/src/queue/listener.js.map +3 -3
- package/dist/src/schemas/filters.d.ts +3 -3
- package/dist/src/schemas/filters.js +3 -3
- package/dist/src/schemas/filters.js.map +3 -3
- package/dist/src/schemas/index.d.ts +5 -100
- package/dist/src/schemas/index.js +4 -88
- package/dist/src/schemas/index.js.map +5 -6
- package/dist/src/schemas/subgraphs.d.ts +2 -0
- package/dist/src/schemas/subgraphs.js +2 -1
- package/dist/src/schemas/subgraphs.js.map +3 -3
- package/dist/src/schemas/workflows.d.ts +4 -0
- package/dist/src/schemas/workflows.js +5 -1
- package/dist/src/schemas/workflows.js.map +3 -3
- package/dist/src/types.d.ts +1 -53
- package/migrations/0030_workflow_source_code.ts +21 -0
- package/migrations/0031_subgraph_source_code.ts +18 -0
- package/migrations/0032_drop_streams_tables.ts +43 -0
- package/migrations/0033_workflow_steps_memo_key.ts +54 -0
- package/migrations/0034_workflow_signer_secrets.ts +42 -0
- package/migrations/0035_workflow_budgets.ts +53 -0
- package/migrations/0036_tx_confirmed_notify.ts +36 -0
- package/package.json +11 -15
- package/dist/src/db/queries/metrics.d.ts +0 -419
- package/dist/src/db/queries/metrics.js +0 -55
- package/dist/src/db/queries/metrics.js.map +0 -10
- package/dist/src/queue/index.d.ts +0 -50
- package/dist/src/queue/index.js +0 -184
- package/dist/src/queue/index.js.map +0 -12
- package/dist/src/queue/recovery.d.ts +0 -14
- package/dist/src/queue/recovery.js +0 -108
- package/dist/src/queue/recovery.js.map +0 -12
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
interface PlanLimits {
|
|
2
|
-
streams: number;
|
|
3
2
|
subgraphs: number;
|
|
4
3
|
apiRequestsPerDay: number;
|
|
5
4
|
deliveriesPerMonth: number;
|
|
@@ -40,40 +39,6 @@ interface EventsTable {
|
|
|
40
39
|
data: unknown;
|
|
41
40
|
created_at: Generated<Date>;
|
|
42
41
|
}
|
|
43
|
-
interface StreamsTable {
|
|
44
|
-
id: Generated<string>;
|
|
45
|
-
name: string;
|
|
46
|
-
status: Generated<string>;
|
|
47
|
-
filters: unknown;
|
|
48
|
-
options: Generated<unknown>;
|
|
49
|
-
endpoint_url: string;
|
|
50
|
-
signing_secret: string | null;
|
|
51
|
-
api_key_id: string;
|
|
52
|
-
project_id: string | null;
|
|
53
|
-
created_at: Generated<Date>;
|
|
54
|
-
updated_at: Generated<Date>;
|
|
55
|
-
}
|
|
56
|
-
interface StreamMetricsTable {
|
|
57
|
-
stream_id: string;
|
|
58
|
-
last_triggered_at: Date | null;
|
|
59
|
-
last_triggered_block: number | null;
|
|
60
|
-
total_deliveries: Generated<number>;
|
|
61
|
-
failed_deliveries: Generated<number>;
|
|
62
|
-
error_message: string | null;
|
|
63
|
-
}
|
|
64
|
-
interface JobsTable {
|
|
65
|
-
id: Generated<string>;
|
|
66
|
-
stream_id: string;
|
|
67
|
-
block_height: number;
|
|
68
|
-
status: Generated<string>;
|
|
69
|
-
attempts: Generated<number>;
|
|
70
|
-
locked_at: Date | null;
|
|
71
|
-
locked_by: string | null;
|
|
72
|
-
error: string | null;
|
|
73
|
-
backfill: Generated<boolean>;
|
|
74
|
-
created_at: Generated<Date>;
|
|
75
|
-
completed_at: Date | null;
|
|
76
|
-
}
|
|
77
42
|
interface IndexProgressTable {
|
|
78
43
|
network: string;
|
|
79
44
|
last_indexed_block: Generated<number>;
|
|
@@ -81,19 +46,6 @@ interface IndexProgressTable {
|
|
|
81
46
|
highest_seen_block: Generated<number>;
|
|
82
47
|
updated_at: Generated<Date>;
|
|
83
48
|
}
|
|
84
|
-
interface DeliveriesTable {
|
|
85
|
-
id: Generated<string>;
|
|
86
|
-
stream_id: string;
|
|
87
|
-
job_id: string | null;
|
|
88
|
-
block_height: number;
|
|
89
|
-
status: string;
|
|
90
|
-
status_code: number | null;
|
|
91
|
-
response_time_ms: number | null;
|
|
92
|
-
attempts: Generated<number>;
|
|
93
|
-
error: string | null;
|
|
94
|
-
payload: unknown;
|
|
95
|
-
created_at: Generated<Date>;
|
|
96
|
-
}
|
|
97
49
|
interface SubgraphsTable {
|
|
98
50
|
id: Generated<string>;
|
|
99
51
|
name: string;
|
|
@@ -114,6 +66,7 @@ interface SubgraphsTable {
|
|
|
114
66
|
api_key_id: string | null;
|
|
115
67
|
account_id: string;
|
|
116
68
|
handler_code: string | null;
|
|
69
|
+
source_code: string | null;
|
|
117
70
|
project_id: string | null;
|
|
118
71
|
is_public: Generated<boolean>;
|
|
119
72
|
tags: Generated<string[]>;
|
|
@@ -312,6 +265,7 @@ interface WorkflowDefinitionsTable {
|
|
|
312
265
|
trigger_type: string;
|
|
313
266
|
trigger_config: unknown;
|
|
314
267
|
handler_path: string;
|
|
268
|
+
source_code: string | null;
|
|
315
269
|
retries_config: unknown | null;
|
|
316
270
|
timeout_ms: number | null;
|
|
317
271
|
api_key_id: string;
|
|
@@ -348,6 +302,8 @@ interface WorkflowStepsTable {
|
|
|
348
302
|
started_at: Date | null;
|
|
349
303
|
completed_at: Date | null;
|
|
350
304
|
duration_ms: number | null;
|
|
305
|
+
memo_key: string | null;
|
|
306
|
+
parent_step_id: string | null;
|
|
351
307
|
created_at: Generated<Date>;
|
|
352
308
|
}
|
|
353
309
|
interface WorkflowQueueTable {
|
|
@@ -382,11 +338,7 @@ interface Database {
|
|
|
382
338
|
blocks: BlocksTable;
|
|
383
339
|
transactions: TransactionsTable;
|
|
384
340
|
events: EventsTable;
|
|
385
|
-
streams: StreamsTable;
|
|
386
|
-
stream_metrics: StreamMetricsTable;
|
|
387
|
-
jobs: JobsTable;
|
|
388
341
|
index_progress: IndexProgressTable;
|
|
389
|
-
deliveries: DeliveriesTable;
|
|
390
342
|
subgraphs: SubgraphsTable;
|
|
391
343
|
api_keys: ApiKeysTable;
|
|
392
344
|
accounts: AccountsTable;
|
|
@@ -413,11 +365,35 @@ interface Database {
|
|
|
413
365
|
workflow_queue: WorkflowQueueTable;
|
|
414
366
|
workflow_schedules: WorkflowSchedulesTable;
|
|
415
367
|
workflow_cursors: WorkflowCursorsTable;
|
|
368
|
+
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
369
|
+
workflow_budgets: WorkflowBudgetsTable;
|
|
370
|
+
}
|
|
371
|
+
interface WorkflowBudgetsTable {
|
|
372
|
+
id: Generated<string>;
|
|
373
|
+
workflow_definition_id: string;
|
|
374
|
+
/** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
|
|
375
|
+
period: string;
|
|
376
|
+
ai_usd_used: Generated<string>;
|
|
377
|
+
ai_tokens_used: Generated<string>;
|
|
378
|
+
chain_microstx_used: Generated<string>;
|
|
379
|
+
chain_tx_count: Generated<number>;
|
|
380
|
+
run_count: Generated<number>;
|
|
381
|
+
step_count: Generated<number>;
|
|
382
|
+
reset_at: Date;
|
|
383
|
+
created_at: Generated<Date>;
|
|
384
|
+
updated_at: Generated<Date>;
|
|
385
|
+
}
|
|
386
|
+
interface WorkflowSignerSecretsTable {
|
|
387
|
+
id: Generated<string>;
|
|
388
|
+
account_id: string;
|
|
389
|
+
name: string;
|
|
390
|
+
/** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
|
|
391
|
+
encrypted_value: Buffer;
|
|
392
|
+
created_at: Generated<Date>;
|
|
393
|
+
updated_at: Generated<Date>;
|
|
416
394
|
}
|
|
417
395
|
/** Increment API request counter for today. Fire-and-forget safe. */
|
|
418
396
|
declare function incrementApiRequests(db: Kysely<Database>, accountId: string): Promise<void>;
|
|
419
|
-
/** Increment delivery counter for today. */
|
|
420
|
-
declare function incrementDeliveries(db: Kysely<Database>, accountId: string, count?: number): Promise<void>;
|
|
421
397
|
interface UsageSummary {
|
|
422
398
|
apiRequestsToday: number;
|
|
423
399
|
deliveriesThisMonth: number;
|
|
@@ -436,7 +412,6 @@ interface LimitCheck {
|
|
|
436
412
|
allowed: boolean;
|
|
437
413
|
limits: ReturnType<typeof getPlanLimits>;
|
|
438
414
|
current: UsageSummary & {
|
|
439
|
-
streams: number
|
|
440
415
|
subgraphs: number
|
|
441
416
|
};
|
|
442
417
|
exceeded?: string;
|
|
@@ -448,4 +423,4 @@ declare function checkLimits(db: Kysely<Database>, accountId: string, plan: stri
|
|
|
448
423
|
* for each tenant's subgraph schemas.
|
|
449
424
|
*/
|
|
450
425
|
declare function measureStorage(db: Kysely<Database>): Promise<void>;
|
|
451
|
-
export { measureStorage,
|
|
426
|
+
export { measureStorage, incrementApiRequests, getUsage, getDailyUsage, checkLimits, UsageSummary, LimitCheck, DailyUsage };
|
|
@@ -16,7 +16,6 @@ var __export = (target, all) => {
|
|
|
16
16
|
|
|
17
17
|
// src/lib/plans.ts
|
|
18
18
|
var FREE_PLAN = {
|
|
19
|
-
streams: 3,
|
|
20
19
|
subgraphs: 2,
|
|
21
20
|
apiRequestsPerDay: 1000,
|
|
22
21
|
deliveriesPerMonth: 5000,
|
|
@@ -43,17 +42,6 @@ async function incrementApiRequests(db, accountId) {
|
|
|
43
42
|
api_requests: sql`usage_daily.api_requests + 1`
|
|
44
43
|
})).execute();
|
|
45
44
|
}
|
|
46
|
-
async function incrementDeliveries(db, accountId, count = 1) {
|
|
47
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
48
|
-
await db.insertInto("usage_daily").values({
|
|
49
|
-
account_id: accountId,
|
|
50
|
-
date: today,
|
|
51
|
-
api_requests: 0,
|
|
52
|
-
deliveries: count
|
|
53
|
-
}).onConflict((oc) => oc.columns(["account_id", "date"]).doUpdateSet({
|
|
54
|
-
deliveries: sql`usage_daily.deliveries + ${count}`
|
|
55
|
-
})).execute();
|
|
56
|
-
}
|
|
57
45
|
async function getUsage(db, accountId) {
|
|
58
46
|
const today = new Date().toISOString().slice(0, 10);
|
|
59
47
|
const monthStart = today.slice(0, 7) + "-01";
|
|
@@ -90,16 +78,11 @@ async function getDailyUsage(db, accountId) {
|
|
|
90
78
|
async function checkLimits(db, accountId, plan) {
|
|
91
79
|
const limits = getPlanLimits(plan);
|
|
92
80
|
const usage = await getUsage(db, accountId);
|
|
93
|
-
const streamCount = await db.selectFrom("streams").innerJoin("api_keys", "streams.api_key_id", "api_keys.id").select(sql`count(*)`.as("count")).where("api_keys.account_id", "=", accountId).executeTakeFirst();
|
|
94
81
|
const subgraphCount = await db.selectFrom("subgraphs").innerJoin("api_keys", "subgraphs.api_key_id", "api_keys.id").select(sql`count(*)`.as("count")).where("api_keys.account_id", "=", accountId).executeTakeFirst();
|
|
95
82
|
const current = {
|
|
96
83
|
...usage,
|
|
97
|
-
streams: Number(streamCount?.count ?? 0),
|
|
98
84
|
subgraphs: Number(subgraphCount?.count ?? 0)
|
|
99
85
|
};
|
|
100
|
-
if (current.streams >= limits.streams) {
|
|
101
|
-
return { allowed: false, limits, current, exceeded: "streams" };
|
|
102
|
-
}
|
|
103
86
|
if (current.subgraphs >= limits.subgraphs) {
|
|
104
87
|
return { allowed: false, limits, current, exceeded: "subgraphs" };
|
|
105
88
|
}
|
|
@@ -142,12 +125,11 @@ async function measureStorage(db) {
|
|
|
142
125
|
}
|
|
143
126
|
export {
|
|
144
127
|
measureStorage,
|
|
145
|
-
incrementDeliveries,
|
|
146
128
|
incrementApiRequests,
|
|
147
129
|
getUsage,
|
|
148
130
|
getDailyUsage,
|
|
149
131
|
checkLimits
|
|
150
132
|
};
|
|
151
133
|
|
|
152
|
-
//# debugId=
|
|
134
|
+
//# debugId=0844CA82D7046A1564756E2164756E21
|
|
153
135
|
//# sourceMappingURL=usage.js.map
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/lib/plans.ts", "../src/db/queries/usage.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export interface PlanLimits {\n\
|
|
6
|
-
"import { type Kysely, sql } from \"kysely\";\nimport { getPlanLimits } from \"../../lib/plans.ts\";\nimport type { Database } from \"../types.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait db\n\t\t.insertInto(\"usage_daily\")\n\t\t.values({\n\t\t\taccount_id: accountId,\n\t\t\tdate: today,\n\t\t\tapi_requests: 1,\n\t\t\tdeliveries: 0,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"account_id\", \"date\"]).doUpdateSet({\n\t\t\t\tapi_requests: sql`usage_daily.api_requests + 1`,\n\t\t\t}),\n\t\t)\n\t\t.execute();\n}\n\
|
|
5
|
+
"export interface PlanLimits {\n\tsubgraphs: number;\n\tapiRequestsPerDay: number;\n\tdeliveriesPerMonth: number;\n\tstorageBytes: number;\n}\n\nexport const FREE_PLAN: PlanLimits = {\n\tsubgraphs: 2,\n\tapiRequestsPerDay: 1_000,\n\tdeliveriesPerMonth: 5_000,\n\tstorageBytes: 100 * 1024 * 1024,\n};\n\nexport function getPlanLimits(plan: string): PlanLimits {\n\tswitch (plan) {\n\t\tcase \"free\":\n\t\tdefault:\n\t\t\treturn FREE_PLAN;\n\t}\n}\n",
|
|
6
|
+
"import { type Kysely, sql } from \"kysely\";\nimport { getPlanLimits } from \"../../lib/plans.ts\";\nimport type { Database } from \"../types.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait db\n\t\t.insertInto(\"usage_daily\")\n\t\t.values({\n\t\t\taccount_id: accountId,\n\t\t\tdate: today,\n\t\t\tapi_requests: 1,\n\t\t\tdeliveries: 0,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"account_id\", \"date\"]).doUpdateSet({\n\t\t\t\tapi_requests: sql`usage_daily.api_requests + 1`,\n\t\t\t}),\n\t\t)\n\t\t.execute();\n}\n\nexport interface UsageSummary {\n\tapiRequestsToday: number;\n\tdeliveriesThisMonth: number;\n\tstorageBytes: number;\n}\n\n/** Get current usage for an account. */\nexport async function getUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<UsageSummary> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tconst monthStart = today.slice(0, 7) + \"-01\"; // YYYY-MM-01\n\n\t// Today's API requests\n\tconst dailyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(\"api_requests\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \"=\", today)\n\t\t.executeTakeFirst();\n\n\t// This month's deliveries\n\tconst monthlyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(deliveries), 0)`.as(\"total\"))\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", monthStart)\n\t\t.executeTakeFirst();\n\n\t// Latest storage snapshot\n\tconst storageRow = await db\n\t\t.selectFrom(\"usage_snapshots\")\n\t\t.select(\"storage_bytes\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"measured_at\", \"desc\")\n\t\t.limit(1)\n\t\t.executeTakeFirst();\n\n\treturn {\n\t\tapiRequestsToday: dailyRow?.api_requests ?? 0,\n\t\tdeliveriesThisMonth: Number(monthlyRow?.total ?? 0),\n\t\tstorageBytes: Number(storageRow?.storage_bytes ?? 0),\n\t};\n}\n\nexport interface DailyUsage {\n\tdate: string;\n\tapiRequests: number;\n\tdeliveries: number;\n}\n\n/** Get last 7 days of daily usage, filling missing days with 0. */\nexport async function getDailyUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<DailyUsage[]> {\n\tconst rows = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select([\"date\", \"api_requests\", \"deliveries\"])\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", sql<string>`NOW()::date - 6`)\n\t\t.orderBy(\"date\", \"asc\")\n\t\t.execute();\n\n\t// Fill missing days with 0 (normalize date to YYYY-MM-DD string)\n\tconst byDate = new Map(\n\t\trows.map((r) => {\n\t\t\tconst d = r.date as unknown;\n\t\t\tconst key =\n\t\t\t\td instanceof Date\n\t\t\t\t\t? d.toISOString().slice(0, 10)\n\t\t\t\t\t: String(d).slice(0, 10);\n\t\t\treturn [key, r];\n\t\t}),\n\t);\n\tconst result: DailyUsage[] = [];\n\tfor (let i = 6; i >= 0; i--) {\n\t\tconst d = new Date();\n\t\td.setDate(d.getDate() - i);\n\t\tconst dateStr = d.toISOString().slice(0, 10);\n\t\tconst row = byDate.get(dateStr);\n\t\tresult.push({\n\t\t\tdate: dateStr,\n\t\t\tapiRequests: row?.api_requests ?? 0,\n\t\t\tdeliveries: row?.deliveries ?? 0,\n\t\t});\n\t}\n\treturn result;\n}\n\nexport interface LimitCheck {\n\tallowed: boolean;\n\tlimits: ReturnType<typeof getPlanLimits>;\n\tcurrent: UsageSummary & { subgraphs: number };\n\texceeded?: string;\n}\n\n/** Check if an account is within plan limits. */\nexport async function checkLimits(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tplan: string,\n): Promise<LimitCheck> {\n\tconst limits = getPlanLimits(plan);\n\tconst usage = await getUsage(db, accountId);\n\n\tconst subgraphCount = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n\t\t.select(sql<number>`count(*)`.as(\"count\"))\n\t\t.where(\"api_keys.account_id\", \"=\", accountId)\n\t\t.executeTakeFirst();\n\n\tconst current = {\n\t\t...usage,\n\t\tsubgraphs: Number(subgraphCount?.count ?? 0),\n\t};\n\n\tif (current.subgraphs >= limits.subgraphs) {\n\t\treturn { allowed: false, limits, current, exceeded: \"subgraphs\" };\n\t}\n\tif (current.apiRequestsToday >= limits.apiRequestsPerDay) {\n\t\treturn { allowed: false, limits, current, exceeded: \"api_requests\" };\n\t}\n\tif (current.deliveriesThisMonth >= limits.deliveriesPerMonth) {\n\t\treturn { allowed: false, limits, current, exceeded: \"deliveries\" };\n\t}\n\tif (current.storageBytes >= limits.storageBytes) {\n\t\treturn { allowed: false, limits, current, exceeded: \"storage\" };\n\t}\n\n\treturn { allowed: true, limits, current };\n}\n\n/**\n * Measure storage for all accounts by querying pg_total_relation_size\n * for each tenant's subgraph schemas.\n */\nexport async function measureStorage(db: Kysely<Database>): Promise<void> {\n\t// Get all accounts with subgraphs\n\tconst accountSubgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.innerJoin(\"api_keys\", \"subgraphs.api_key_id\", \"api_keys.id\")\n\t\t.select([\"api_keys.account_id\", \"subgraphs.schema_name\"])\n\t\t.where(\"subgraphs.schema_name\", \"is not\", null)\n\t\t.execute();\n\n\t// Group schemas by account\n\tconst byAccount = new Map<string, string[]>();\n\tfor (const row of accountSubgraphs) {\n\t\tconst schemas = byAccount.get(row.account_id) ?? [];\n\t\tif (row.schema_name) schemas.push(row.schema_name);\n\t\tbyAccount.set(row.account_id, schemas);\n\t}\n\n\tfor (const [accountId, schemas] of byAccount) {\n\t\tlet totalBytes = 0;\n\t\tfor (const schema of schemas) {\n\t\t\ttry {\n\t\t\t\tconst result = await sql<{ size: string }>`\n SELECT COALESCE(SUM(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename))), 0)::text as size\n FROM pg_tables WHERE schemaname = ${schema}\n `.execute(db);\n\t\t\t\ttotalBytes += Number((result.rows[0] as any)?.size ?? 0);\n\t\t\t} catch {\n\t\t\t\t// Schema may not exist\n\t\t\t}\n\t\t}\n\n\t\tawait db\n\t\t\t.insertInto(\"usage_snapshots\")\n\t\t\t.values({\n\t\t\t\taccount_id: accountId,\n\t\t\t\tstorage_bytes: totalBytes,\n\t\t\t})\n\t\t\t.execute();\n\t}\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "0844CA82D7046A1564756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -32,40 +32,6 @@ interface EventsTable {
|
|
|
32
32
|
data: unknown;
|
|
33
33
|
created_at: Generated<Date>;
|
|
34
34
|
}
|
|
35
|
-
interface StreamsTable {
|
|
36
|
-
id: Generated<string>;
|
|
37
|
-
name: string;
|
|
38
|
-
status: Generated<string>;
|
|
39
|
-
filters: unknown;
|
|
40
|
-
options: Generated<unknown>;
|
|
41
|
-
endpoint_url: string;
|
|
42
|
-
signing_secret: string | null;
|
|
43
|
-
api_key_id: string;
|
|
44
|
-
project_id: string | null;
|
|
45
|
-
created_at: Generated<Date>;
|
|
46
|
-
updated_at: Generated<Date>;
|
|
47
|
-
}
|
|
48
|
-
interface StreamMetricsTable {
|
|
49
|
-
stream_id: string;
|
|
50
|
-
last_triggered_at: Date | null;
|
|
51
|
-
last_triggered_block: number | null;
|
|
52
|
-
total_deliveries: Generated<number>;
|
|
53
|
-
failed_deliveries: Generated<number>;
|
|
54
|
-
error_message: string | null;
|
|
55
|
-
}
|
|
56
|
-
interface JobsTable {
|
|
57
|
-
id: Generated<string>;
|
|
58
|
-
stream_id: string;
|
|
59
|
-
block_height: number;
|
|
60
|
-
status: Generated<string>;
|
|
61
|
-
attempts: Generated<number>;
|
|
62
|
-
locked_at: Date | null;
|
|
63
|
-
locked_by: string | null;
|
|
64
|
-
error: string | null;
|
|
65
|
-
backfill: Generated<boolean>;
|
|
66
|
-
created_at: Generated<Date>;
|
|
67
|
-
completed_at: Date | null;
|
|
68
|
-
}
|
|
69
35
|
interface IndexProgressTable {
|
|
70
36
|
network: string;
|
|
71
37
|
last_indexed_block: Generated<number>;
|
|
@@ -73,19 +39,6 @@ interface IndexProgressTable {
|
|
|
73
39
|
highest_seen_block: Generated<number>;
|
|
74
40
|
updated_at: Generated<Date>;
|
|
75
41
|
}
|
|
76
|
-
interface DeliveriesTable {
|
|
77
|
-
id: Generated<string>;
|
|
78
|
-
stream_id: string;
|
|
79
|
-
job_id: string | null;
|
|
80
|
-
block_height: number;
|
|
81
|
-
status: string;
|
|
82
|
-
status_code: number | null;
|
|
83
|
-
response_time_ms: number | null;
|
|
84
|
-
attempts: Generated<number>;
|
|
85
|
-
error: string | null;
|
|
86
|
-
payload: unknown;
|
|
87
|
-
created_at: Generated<Date>;
|
|
88
|
-
}
|
|
89
42
|
interface SubgraphsTable {
|
|
90
43
|
id: Generated<string>;
|
|
91
44
|
name: string;
|
|
@@ -106,6 +59,7 @@ interface SubgraphsTable {
|
|
|
106
59
|
api_key_id: string | null;
|
|
107
60
|
account_id: string;
|
|
108
61
|
handler_code: string | null;
|
|
62
|
+
source_code: string | null;
|
|
109
63
|
project_id: string | null;
|
|
110
64
|
is_public: Generated<boolean>;
|
|
111
65
|
tags: Generated<string[]>;
|
|
@@ -304,6 +258,7 @@ interface WorkflowDefinitionsTable {
|
|
|
304
258
|
trigger_type: string;
|
|
305
259
|
trigger_config: unknown;
|
|
306
260
|
handler_path: string;
|
|
261
|
+
source_code: string | null;
|
|
307
262
|
retries_config: unknown | null;
|
|
308
263
|
timeout_ms: number | null;
|
|
309
264
|
api_key_id: string;
|
|
@@ -340,6 +295,8 @@ interface WorkflowStepsTable {
|
|
|
340
295
|
started_at: Date | null;
|
|
341
296
|
completed_at: Date | null;
|
|
342
297
|
duration_ms: number | null;
|
|
298
|
+
memo_key: string | null;
|
|
299
|
+
parent_step_id: string | null;
|
|
343
300
|
created_at: Generated<Date>;
|
|
344
301
|
}
|
|
345
302
|
interface WorkflowQueueTable {
|
|
@@ -374,11 +331,7 @@ interface Database {
|
|
|
374
331
|
blocks: BlocksTable;
|
|
375
332
|
transactions: TransactionsTable;
|
|
376
333
|
events: EventsTable;
|
|
377
|
-
streams: StreamsTable;
|
|
378
|
-
stream_metrics: StreamMetricsTable;
|
|
379
|
-
jobs: JobsTable;
|
|
380
334
|
index_progress: IndexProgressTable;
|
|
381
|
-
deliveries: DeliveriesTable;
|
|
382
335
|
subgraphs: SubgraphsTable;
|
|
383
336
|
api_keys: ApiKeysTable;
|
|
384
337
|
accounts: AccountsTable;
|
|
@@ -405,10 +358,38 @@ interface Database {
|
|
|
405
358
|
workflow_queue: WorkflowQueueTable;
|
|
406
359
|
workflow_schedules: WorkflowSchedulesTable;
|
|
407
360
|
workflow_cursors: WorkflowCursorsTable;
|
|
361
|
+
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
362
|
+
workflow_budgets: WorkflowBudgetsTable;
|
|
363
|
+
}
|
|
364
|
+
interface WorkflowBudgetsTable {
|
|
365
|
+
id: Generated<string>;
|
|
366
|
+
workflow_definition_id: string;
|
|
367
|
+
/** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
|
|
368
|
+
period: string;
|
|
369
|
+
ai_usd_used: Generated<string>;
|
|
370
|
+
ai_tokens_used: Generated<string>;
|
|
371
|
+
chain_microstx_used: Generated<string>;
|
|
372
|
+
chain_tx_count: Generated<number>;
|
|
373
|
+
run_count: Generated<number>;
|
|
374
|
+
step_count: Generated<number>;
|
|
375
|
+
reset_at: Date;
|
|
376
|
+
created_at: Generated<Date>;
|
|
377
|
+
updated_at: Generated<Date>;
|
|
378
|
+
}
|
|
379
|
+
interface WorkflowSignerSecretsTable {
|
|
380
|
+
id: Generated<string>;
|
|
381
|
+
account_id: string;
|
|
382
|
+
name: string;
|
|
383
|
+
/** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
|
|
384
|
+
encrypted_value: Buffer;
|
|
385
|
+
created_at: Generated<Date>;
|
|
386
|
+
updated_at: Generated<Date>;
|
|
408
387
|
}
|
|
409
388
|
type WorkflowDefinition = Selectable<WorkflowDefinitionsTable>;
|
|
410
389
|
type WorkflowRun = Selectable<WorkflowRunsTable>;
|
|
411
390
|
type WorkflowStep = Selectable<WorkflowStepsTable>;
|
|
391
|
+
/** Bump the patch digit of a semver string. Falls back to "1.0.1" on malformed input. */
|
|
392
|
+
declare function bumpPatch(version: string): string;
|
|
412
393
|
declare function listWorkflowDefinitions(db: Kysely<Database>, apiKeyIds?: string[]): Promise<WorkflowDefinition[]>;
|
|
413
394
|
declare function getWorkflowDefinition(db: Kysely<Database>, name: string, apiKeyIds?: string[]): Promise<WorkflowDefinition | null>;
|
|
414
395
|
declare function upsertWorkflowDefinition(db: Kysely<Database>, data: {
|
|
@@ -420,7 +401,8 @@ declare function upsertWorkflowDefinition(db: Kysely<Database>, data: {
|
|
|
420
401
|
projectId?: string
|
|
421
402
|
retriesConfig?: Record<string, unknown>
|
|
422
403
|
timeoutMs?: number
|
|
423
|
-
|
|
404
|
+
sourceCode?: string
|
|
405
|
+
expectedVersion?: string
|
|
424
406
|
}): Promise<WorkflowDefinition>;
|
|
425
407
|
declare function updateWorkflowStatus(db: Kysely<Database>, name: string, apiKeyId: string, status: string): Promise<void>;
|
|
426
408
|
declare function deleteWorkflowDefinition(db: Kysely<Database>, name: string, apiKeyId: string): Promise<void>;
|
|
@@ -437,4 +419,4 @@ declare function listWorkflowRuns(db: Kysely<Database>, definitionId: string, pa
|
|
|
437
419
|
offset?: number
|
|
438
420
|
}): Promise<WorkflowRun[]>;
|
|
439
421
|
declare function getWorkflowSteps(db: Kysely<Database>, runId: string): Promise<WorkflowStep[]>;
|
|
440
|
-
export { upsertWorkflowDefinition, updateWorkflowStatus, listWorkflowRuns, listWorkflowDefinitions, getWorkflowSteps, getWorkflowRun, getWorkflowDefinition, deleteWorkflowDefinition, createWorkflowRun };
|
|
422
|
+
export { upsertWorkflowDefinition, updateWorkflowStatus, listWorkflowRuns, listWorkflowDefinitions, getWorkflowSteps, getWorkflowRun, getWorkflowDefinition, deleteWorkflowDefinition, createWorkflowRun, bumpPatch };
|
|
@@ -31,7 +31,113 @@ function parseJsonb(value) {
|
|
|
31
31
|
return value ?? {};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// src/errors.ts
|
|
35
|
+
var ErrorCodes = {
|
|
36
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
37
|
+
DATABASE_ERROR: "DATABASE_ERROR",
|
|
38
|
+
AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR",
|
|
39
|
+
AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR",
|
|
40
|
+
RATE_LIMIT_ERROR: "RATE_LIMIT_ERROR",
|
|
41
|
+
FORBIDDEN: "FORBIDDEN",
|
|
42
|
+
VERSION_CONFLICT: "VERSION_CONFLICT",
|
|
43
|
+
NOT_FOUND: "NOT_FOUND"
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
class SecondLayerError extends Error {
|
|
47
|
+
code;
|
|
48
|
+
cause;
|
|
49
|
+
constructor(code, message, cause) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.cause = cause;
|
|
53
|
+
this.name = this.constructor.name;
|
|
54
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
55
|
+
}
|
|
56
|
+
toJSON() {
|
|
57
|
+
return {
|
|
58
|
+
name: this.name,
|
|
59
|
+
code: this.code,
|
|
60
|
+
message: this.message,
|
|
61
|
+
stack: this.stack,
|
|
62
|
+
cause: this.cause
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class NotFoundError extends SecondLayerError {
|
|
68
|
+
constructor(message) {
|
|
69
|
+
super("NOT_FOUND", message);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
class ValidationError extends SecondLayerError {
|
|
74
|
+
constructor(message, cause) {
|
|
75
|
+
super("VALIDATION_ERROR", message, cause);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
class DatabaseError extends SecondLayerError {
|
|
80
|
+
constructor(message, cause) {
|
|
81
|
+
super("DATABASE_ERROR", message, cause);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
class AuthenticationError extends SecondLayerError {
|
|
86
|
+
constructor(message) {
|
|
87
|
+
super("AUTHENTICATION_ERROR", message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
class AuthorizationError extends SecondLayerError {
|
|
92
|
+
constructor(message) {
|
|
93
|
+
super("AUTHORIZATION_ERROR", message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class RateLimitError extends SecondLayerError {
|
|
98
|
+
constructor(message) {
|
|
99
|
+
super("RATE_LIMIT_ERROR", message);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
class ForbiddenError extends SecondLayerError {
|
|
104
|
+
constructor(message = "Forbidden") {
|
|
105
|
+
super("FORBIDDEN", message);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class VersionConflictError extends SecondLayerError {
|
|
110
|
+
currentVersion;
|
|
111
|
+
expectedVersion;
|
|
112
|
+
constructor(currentVersion, expectedVersion) {
|
|
113
|
+
super("VERSION_CONFLICT", `Version conflict: expected ${expectedVersion}, current ${currentVersion}`);
|
|
114
|
+
this.currentVersion = currentVersion;
|
|
115
|
+
this.expectedVersion = expectedVersion;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var CODE_TO_STATUS = {
|
|
119
|
+
AUTHENTICATION_ERROR: 401,
|
|
120
|
+
AUTHORIZATION_ERROR: 403,
|
|
121
|
+
RATE_LIMIT_ERROR: 429,
|
|
122
|
+
FORBIDDEN: 403,
|
|
123
|
+
NOT_FOUND: 404,
|
|
124
|
+
VALIDATION_ERROR: 400
|
|
125
|
+
};
|
|
126
|
+
function getErrorMessage(err) {
|
|
127
|
+
return err instanceof Error ? err.message : String(err);
|
|
128
|
+
}
|
|
129
|
+
|
|
34
130
|
// src/db/queries/workflows.ts
|
|
131
|
+
function bumpPatch(version) {
|
|
132
|
+
const parts = version.split(".");
|
|
133
|
+
if (parts.length !== 3)
|
|
134
|
+
return "1.0.1";
|
|
135
|
+
const [major, minor, patch] = parts.map((p) => Number.parseInt(p, 10));
|
|
136
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || major === undefined || minor === undefined || patch === undefined) {
|
|
137
|
+
return "1.0.1";
|
|
138
|
+
}
|
|
139
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
140
|
+
}
|
|
35
141
|
async function listWorkflowDefinitions(db, apiKeyIds) {
|
|
36
142
|
let query = db.selectFrom("workflow_definitions").selectAll().where("status", "!=", "deleted").orderBy("created_at", "desc");
|
|
37
143
|
if (apiKeyIds?.length) {
|
|
@@ -47,26 +153,36 @@ async function getWorkflowDefinition(db, name, apiKeyIds) {
|
|
|
47
153
|
return await query.executeTakeFirst() ?? null;
|
|
48
154
|
}
|
|
49
155
|
async function upsertWorkflowDefinition(db, data) {
|
|
156
|
+
const existing = await db.selectFrom("workflow_definitions").selectAll().where("name", "=", data.name).where("api_key_id", "=", data.apiKeyId).executeTakeFirst();
|
|
157
|
+
if (existing) {
|
|
158
|
+
if (data.expectedVersion !== undefined && existing.version !== data.expectedVersion) {
|
|
159
|
+
throw new VersionConflictError(existing.version, data.expectedVersion);
|
|
160
|
+
}
|
|
161
|
+
const nextVersion = bumpPatch(existing.version);
|
|
162
|
+
return await db.updateTable("workflow_definitions").set({
|
|
163
|
+
trigger_type: data.triggerType,
|
|
164
|
+
trigger_config: jsonb(data.triggerConfig),
|
|
165
|
+
handler_path: data.handlerPath,
|
|
166
|
+
source_code: data.sourceCode ?? existing.source_code,
|
|
167
|
+
retries_config: data.retriesConfig ? jsonb(data.retriesConfig) : null,
|
|
168
|
+
timeout_ms: data.timeoutMs ?? null,
|
|
169
|
+
version: nextVersion,
|
|
170
|
+
status: "active",
|
|
171
|
+
updated_at: new Date
|
|
172
|
+
}).where("id", "=", existing.id).returningAll().executeTakeFirstOrThrow();
|
|
173
|
+
}
|
|
50
174
|
return await db.insertInto("workflow_definitions").values({
|
|
51
175
|
name: data.name,
|
|
52
176
|
trigger_type: data.triggerType,
|
|
53
177
|
trigger_config: jsonb(data.triggerConfig),
|
|
54
178
|
handler_path: data.handlerPath,
|
|
179
|
+
source_code: data.sourceCode ?? null,
|
|
55
180
|
api_key_id: data.apiKeyId,
|
|
56
181
|
project_id: data.projectId ?? null,
|
|
57
182
|
retries_config: data.retriesConfig ? jsonb(data.retriesConfig) : null,
|
|
58
183
|
timeout_ms: data.timeoutMs ?? null,
|
|
59
|
-
version:
|
|
60
|
-
}).
|
|
61
|
-
trigger_type: data.triggerType,
|
|
62
|
-
trigger_config: jsonb(data.triggerConfig),
|
|
63
|
-
handler_path: data.handlerPath,
|
|
64
|
-
retries_config: data.retriesConfig ? jsonb(data.retriesConfig) : null,
|
|
65
|
-
timeout_ms: data.timeoutMs ?? null,
|
|
66
|
-
version: data.version ?? "1.0.0",
|
|
67
|
-
status: "active",
|
|
68
|
-
updated_at: new Date
|
|
69
|
-
})).returningAll().executeTakeFirstOrThrow();
|
|
184
|
+
version: "1.0.0"
|
|
185
|
+
}).returningAll().executeTakeFirstOrThrow();
|
|
70
186
|
}
|
|
71
187
|
async function updateWorkflowStatus(db, name, apiKeyId, status) {
|
|
72
188
|
await db.updateTable("workflow_definitions").set({ status, updated_at: new Date }).where("name", "=", name).where("api_key_id", "=", apiKeyId).execute();
|
|
@@ -108,8 +224,9 @@ export {
|
|
|
108
224
|
getWorkflowRun,
|
|
109
225
|
getWorkflowDefinition,
|
|
110
226
|
deleteWorkflowDefinition,
|
|
111
|
-
createWorkflowRun
|
|
227
|
+
createWorkflowRun,
|
|
228
|
+
bumpPatch
|
|
112
229
|
};
|
|
113
230
|
|
|
114
|
-
//# debugId=
|
|
231
|
+
//# debugId=A3CE9B539936424A64756E2164756E21
|
|
115
232
|
//# sourceMappingURL=workflows.js.map
|