@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.
- 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 +91 -6
- package/dist/src/db/index.js +53 -29
- package/dist/src/db/index.js.map +4 -4
- package/dist/src/db/jsonb.js.map +2 -2
- package/dist/src/db/queries/accounts.d.ts +59 -2
- package/dist/src/db/queries/integrity.d.ts +59 -2
- package/dist/src/db/queries/marketplace.d.ts +59 -2
- package/dist/src/db/queries/marketplace.js +6 -9
- package/dist/src/db/queries/marketplace.js.map +3 -3
- package/dist/src/db/queries/projects.d.ts +59 -2
- package/dist/src/db/queries/projects.js.map +2 -2
- package/dist/src/db/queries/subgraph-gaps.d.ts +59 -2
- package/dist/src/db/queries/subgraphs.d.ts +63 -5
- package/dist/src/db/queries/subgraphs.js +3 -9
- package/dist/src/db/queries/subgraphs.js.map +4 -4
- package/dist/src/db/queries/tenants.d.ts +493 -0
- package/dist/src/db/queries/tenants.js +194 -0
- package/dist/src/db/queries/tenants.js.map +11 -0
- package/dist/src/db/queries/usage.d.ts +59 -2
- package/dist/src/db/queries/usage.js +3 -3
- package/dist/src/db/queries/usage.js.map +3 -3
- package/dist/src/db/queries/workflows.d.ts +59 -2
- package/dist/src/db/queries/workflows.js +31 -3
- package/dist/src/db/queries/workflows.js.map +4 -4
- package/dist/src/db/schema.d.ts +69 -3
- package/dist/src/env.d.ts +10 -0
- package/dist/src/env.js +3 -1
- package/dist/src/env.js.map +3 -3
- package/dist/src/errors.d.ts +17 -3
- package/dist/src/errors.js +34 -3
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +117 -8
- package/dist/src/index.js +88 -31
- package/dist/src/index.js.map +6 -6
- package/dist/src/logger.js +3 -1
- package/dist/src/logger.js.map +3 -3
- package/dist/src/mode.d.ts +30 -0
- package/dist/src/mode.js +43 -0
- package/dist/src/mode.js.map +10 -0
- package/dist/src/node/archive-client.js +3 -1
- package/dist/src/node/archive-client.js.map +3 -3
- package/dist/src/node/hiro-client.js +3 -1
- package/dist/src/node/hiro-client.js.map +3 -3
- package/dist/src/node/local-client.d.ts +59 -2
- 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 +11 -2
- package/dist/src/queue/listener.js +11 -12
- package/dist/src/queue/listener.js.map +3 -3
- package/dist/src/types.d.ts +10 -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/migrations/0037_nullable_api_key.ts +35 -0
- package/migrations/0038_drop_workflow_tables.ts +46 -0
- package/migrations/0039_tenants.ts +66 -0
- package/migrations/0040_tenant_key_generations.ts +29 -0
- package/migrations/0041_subgraphs_drop_api_key_id.ts +49 -0
- package/migrations/0042_tenant_project_id.ts +25 -0
- package/package.json +18 -2
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare function encryptSecret(plaintext: string): Buffer;
|
|
2
|
+
declare function decryptSecret(envelope: Buffer): string;
|
|
3
|
+
/** Generate a fresh 32-byte hex key suitable for `SECONDLAYER_SECRETS_KEY`. */
|
|
4
|
+
declare function generateSecretsKey(): string;
|
|
5
|
+
export { generateSecretsKey, encryptSecret, decryptSecret };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/crypto/secrets.ts
|
|
18
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
19
|
+
var KEY_ENV = "SECONDLAYER_SECRETS_KEY";
|
|
20
|
+
var IV_LEN = 12;
|
|
21
|
+
var TAG_LEN = 16;
|
|
22
|
+
function loadKey() {
|
|
23
|
+
const hex = process.env[KEY_ENV];
|
|
24
|
+
if (!hex) {
|
|
25
|
+
throw new Error(`${KEY_ENV} not set. Generate one with: openssl rand -hex 32`);
|
|
26
|
+
}
|
|
27
|
+
const key = Buffer.from(hex, "hex");
|
|
28
|
+
if (key.length !== 32) {
|
|
29
|
+
throw new Error(`${KEY_ENV} must be 32 bytes hex (got ${key.length})`);
|
|
30
|
+
}
|
|
31
|
+
return key;
|
|
32
|
+
}
|
|
33
|
+
var _cachedKey = null;
|
|
34
|
+
function getKey() {
|
|
35
|
+
if (!_cachedKey)
|
|
36
|
+
_cachedKey = loadKey();
|
|
37
|
+
return _cachedKey;
|
|
38
|
+
}
|
|
39
|
+
function encryptSecret(plaintext) {
|
|
40
|
+
const key = getKey();
|
|
41
|
+
const iv = randomBytes(IV_LEN);
|
|
42
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
43
|
+
const ciphertext = Buffer.concat([
|
|
44
|
+
cipher.update(plaintext, "utf8"),
|
|
45
|
+
cipher.final()
|
|
46
|
+
]);
|
|
47
|
+
const tag = cipher.getAuthTag();
|
|
48
|
+
return Buffer.concat([iv, tag, ciphertext]);
|
|
49
|
+
}
|
|
50
|
+
function decryptSecret(envelope) {
|
|
51
|
+
const key = getKey();
|
|
52
|
+
const iv = envelope.subarray(0, IV_LEN);
|
|
53
|
+
const tag = envelope.subarray(IV_LEN, IV_LEN + TAG_LEN);
|
|
54
|
+
const ciphertext = envelope.subarray(IV_LEN + TAG_LEN);
|
|
55
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
56
|
+
decipher.setAuthTag(tag);
|
|
57
|
+
return decipher.update(ciphertext).toString("utf8") + decipher.final("utf8");
|
|
58
|
+
}
|
|
59
|
+
function generateSecretsKey() {
|
|
60
|
+
return randomBytes(32).toString("hex");
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
generateSecretsKey,
|
|
64
|
+
encryptSecret,
|
|
65
|
+
decryptSecret
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//# debugId=0FD7F496A1099A3864756E2164756E21
|
|
69
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/crypto/secrets.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\n\n/**\n * AES-256-GCM symmetric envelope for workflow signer secrets.\n *\n * Ciphertext layout: `iv (12 bytes) || authTag (16 bytes) || ciphertext`\n *\n * The key comes from `SECONDLAYER_SECRETS_KEY` — 32 bytes hex. Callers must\n * load + cache the key once per process. Rotation strategy: when a customer\n * wants to rotate keys, re-encrypt all rows with the new key and swap the\n * env var. Not zero-downtime, but acceptable at v2 scale.\n *\n * For real KMS (AWS KMS, HashiCorp Vault, GCP KMS), wrap the same byte\n * layout behind an `EncryptSecret` / `DecryptSecret` interface in the\n * runner and swap the implementation at startup.\n */\n\nconst KEY_ENV = \"SECONDLAYER_SECRETS_KEY\";\nconst IV_LEN = 12;\nconst TAG_LEN = 16;\n\nfunction loadKey(): Buffer {\n\tconst hex = process.env[KEY_ENV];\n\tif (!hex) {\n\t\tthrow new Error(\n\t\t\t`${KEY_ENV} not set. Generate one with: openssl rand -hex 32`,\n\t\t);\n\t}\n\tconst key = Buffer.from(hex, \"hex\");\n\tif (key.length !== 32) {\n\t\tthrow new Error(`${KEY_ENV} must be 32 bytes hex (got ${key.length})`);\n\t}\n\treturn key;\n}\n\nlet _cachedKey: Buffer | null = null;\nfunction getKey(): Buffer {\n\tif (!_cachedKey) _cachedKey = loadKey();\n\treturn _cachedKey;\n}\n\nexport function encryptSecret(plaintext: string): Buffer {\n\tconst key = getKey();\n\tconst iv = randomBytes(IV_LEN);\n\tconst cipher = createCipheriv(\"aes-256-gcm\", key, iv);\n\tconst ciphertext = Buffer.concat([\n\t\tcipher.update(plaintext, \"utf8\"),\n\t\tcipher.final(),\n\t]);\n\tconst tag = cipher.getAuthTag();\n\treturn Buffer.concat([iv, tag, ciphertext]);\n}\n\nexport function decryptSecret(envelope: Buffer): string {\n\tconst key = getKey();\n\tconst iv = envelope.subarray(0, IV_LEN);\n\tconst tag = envelope.subarray(IV_LEN, IV_LEN + TAG_LEN);\n\tconst ciphertext = envelope.subarray(IV_LEN + TAG_LEN);\n\tconst decipher = createDecipheriv(\"aes-256-gcm\", key, iv);\n\tdecipher.setAuthTag(tag);\n\treturn decipher.update(ciphertext).toString(\"utf8\") + decipher.final(\"utf8\");\n}\n\n/** Generate a fresh 32-byte hex key suitable for `SECONDLAYER_SECRETS_KEY`. */\nexport function generateSecretsKey(): string {\n\treturn randomBytes(32).toString(\"hex\");\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAiBA,IAAM,UAAU;AAChB,IAAM,SAAS;AACf,IAAM,UAAU;AAEhB,SAAS,OAAO,GAAW;AAAA,EAC1B,MAAM,MAAM,QAAQ,IAAI;AAAA,EACxB,IAAI,CAAC,KAAK;AAAA,IACT,MAAM,IAAI,MACT,GAAG,0DACJ;AAAA,EACD;AAAA,EACA,MAAM,MAAM,OAAO,KAAK,KAAK,KAAK;AAAA,EAClC,IAAI,IAAI,WAAW,IAAI;AAAA,IACtB,MAAM,IAAI,MAAM,GAAG,qCAAqC,IAAI,SAAS;AAAA,EACtE;AAAA,EACA,OAAO;AAAA;AAGR,IAAI,aAA4B;AAChC,SAAS,MAAM,GAAW;AAAA,EACzB,IAAI,CAAC;AAAA,IAAY,aAAa,QAAQ;AAAA,EACtC,OAAO;AAAA;AAGD,SAAS,aAAa,CAAC,WAA2B;AAAA,EACxD,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,KAAK,YAAY,MAAM;AAAA,EAC7B,MAAM,SAAS,eAAe,eAAe,KAAK,EAAE;AAAA,EACpD,MAAM,aAAa,OAAO,OAAO;AAAA,IAChC,OAAO,OAAO,WAAW,MAAM;AAAA,IAC/B,OAAO,MAAM;AAAA,EACd,CAAC;AAAA,EACD,MAAM,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;AAAA;AAGpC,SAAS,aAAa,CAAC,UAA0B;AAAA,EACvD,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,KAAK,SAAS,SAAS,GAAG,MAAM;AAAA,EACtC,MAAM,MAAM,SAAS,SAAS,QAAQ,SAAS,OAAO;AAAA,EACtD,MAAM,aAAa,SAAS,SAAS,SAAS,OAAO;AAAA,EACrD,MAAM,WAAW,iBAAiB,eAAe,KAAK,EAAE;AAAA,EACxD,SAAS,WAAW,GAAG;AAAA,EACvB,OAAO,SAAS,OAAO,UAAU,EAAE,SAAS,MAAM,IAAI,SAAS,MAAM,MAAM;AAAA;AAIrE,SAAS,kBAAkB,GAAW;AAAA,EAC5C,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA;",
|
|
8
|
+
"debugId": "0FD7F496A1099A3864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/src/db/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ declare function jsonb(value: unknown): RawBuilder<unknown>;
|
|
|
13
13
|
declare function parseJsonb<T = unknown>(value: unknown): T;
|
|
14
14
|
import { Kysely } from "kysely";
|
|
15
15
|
import postgres from "postgres";
|
|
16
|
-
import { Generated, Insertable, Selectable, Updateable } from "kysely";
|
|
16
|
+
import { ColumnType, Generated, Insertable, Selectable, Updateable } from "kysely";
|
|
17
17
|
interface BlocksTable {
|
|
18
18
|
height: number;
|
|
19
19
|
hash: string;
|
|
@@ -70,7 +70,6 @@ interface SubgraphsTable {
|
|
|
70
70
|
last_error_at: Date | null;
|
|
71
71
|
total_processed: Generated<number>;
|
|
72
72
|
total_errors: Generated<number>;
|
|
73
|
-
api_key_id: string | null;
|
|
74
73
|
account_id: string;
|
|
75
74
|
handler_code: string | null;
|
|
76
75
|
source_code: string | null;
|
|
@@ -309,6 +308,8 @@ interface WorkflowStepsTable {
|
|
|
309
308
|
started_at: Date | null;
|
|
310
309
|
completed_at: Date | null;
|
|
311
310
|
duration_ms: number | null;
|
|
311
|
+
memo_key: string | null;
|
|
312
|
+
parent_step_id: string | null;
|
|
312
313
|
created_at: Generated<Date>;
|
|
313
314
|
}
|
|
314
315
|
interface WorkflowQueueTable {
|
|
@@ -370,6 +371,65 @@ interface Database {
|
|
|
370
371
|
workflow_queue: WorkflowQueueTable;
|
|
371
372
|
workflow_schedules: WorkflowSchedulesTable;
|
|
372
373
|
workflow_cursors: WorkflowCursorsTable;
|
|
374
|
+
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
375
|
+
workflow_budgets: WorkflowBudgetsTable;
|
|
376
|
+
tenants: TenantsTable;
|
|
377
|
+
}
|
|
378
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
379
|
+
interface TenantsTable {
|
|
380
|
+
id: Generated<string>;
|
|
381
|
+
account_id: string;
|
|
382
|
+
slug: string;
|
|
383
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
384
|
+
plan: string;
|
|
385
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
386
|
+
memory_mb: number;
|
|
387
|
+
storage_limit_mb: number;
|
|
388
|
+
storage_used_mb: number | null;
|
|
389
|
+
pg_container_id: string | null;
|
|
390
|
+
api_container_id: string | null;
|
|
391
|
+
processor_container_id: string | null;
|
|
392
|
+
target_database_url_enc: Buffer;
|
|
393
|
+
tenant_jwt_secret_enc: Buffer;
|
|
394
|
+
anon_key_enc: Buffer;
|
|
395
|
+
service_key_enc: Buffer;
|
|
396
|
+
api_url_internal: string;
|
|
397
|
+
api_url_public: string;
|
|
398
|
+
trial_ends_at: Date;
|
|
399
|
+
suspended_at: Date | null;
|
|
400
|
+
last_health_check_at: Date | null;
|
|
401
|
+
service_gen: Generated<number>;
|
|
402
|
+
anon_gen: Generated<number>;
|
|
403
|
+
project_id: string | null;
|
|
404
|
+
created_at: Generated<Date>;
|
|
405
|
+
updated_at: Generated<Date>;
|
|
406
|
+
}
|
|
407
|
+
type Tenant = Selectable<TenantsTable>;
|
|
408
|
+
type InsertTenant = Insertable<TenantsTable>;
|
|
409
|
+
type UpdateTenant = Updateable<TenantsTable>;
|
|
410
|
+
interface WorkflowBudgetsTable {
|
|
411
|
+
id: Generated<string>;
|
|
412
|
+
workflow_definition_id: string;
|
|
413
|
+
/** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
|
|
414
|
+
period: string;
|
|
415
|
+
ai_usd_used: Generated<string>;
|
|
416
|
+
ai_tokens_used: Generated<string>;
|
|
417
|
+
chain_microstx_used: Generated<string>;
|
|
418
|
+
chain_tx_count: Generated<number>;
|
|
419
|
+
run_count: Generated<number>;
|
|
420
|
+
step_count: Generated<number>;
|
|
421
|
+
reset_at: Date;
|
|
422
|
+
created_at: Generated<Date>;
|
|
423
|
+
updated_at: Generated<Date>;
|
|
424
|
+
}
|
|
425
|
+
interface WorkflowSignerSecretsTable {
|
|
426
|
+
id: Generated<string>;
|
|
427
|
+
account_id: string;
|
|
428
|
+
name: string;
|
|
429
|
+
/** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
|
|
430
|
+
encrypted_value: Buffer;
|
|
431
|
+
created_at: Generated<Date>;
|
|
432
|
+
updated_at: Generated<Date>;
|
|
373
433
|
}
|
|
374
434
|
type Block = Selectable<BlocksTable>;
|
|
375
435
|
type InsertBlock = Insertable<BlocksTable>;
|
|
@@ -422,6 +482,12 @@ type WorkflowSchedule = Selectable<WorkflowSchedulesTable>;
|
|
|
422
482
|
type InsertWorkflowSchedule = Insertable<WorkflowSchedulesTable>;
|
|
423
483
|
type UpdateWorkflowSchedule = Updateable<WorkflowSchedulesTable>;
|
|
424
484
|
type WorkflowCursor = Selectable<WorkflowCursorsTable>;
|
|
485
|
+
type WorkflowSignerSecret = Selectable<WorkflowSignerSecretsTable>;
|
|
486
|
+
type InsertWorkflowSignerSecret = Insertable<WorkflowSignerSecretsTable>;
|
|
487
|
+
type UpdateWorkflowSignerSecret = Updateable<WorkflowSignerSecretsTable>;
|
|
488
|
+
type WorkflowBudget = Selectable<WorkflowBudgetsTable>;
|
|
489
|
+
type InsertWorkflowBudget = Insertable<WorkflowBudgetsTable>;
|
|
490
|
+
type UpdateWorkflowBudget = Updateable<WorkflowBudgetsTable>;
|
|
425
491
|
type Project = Selectable<ProjectsTable>;
|
|
426
492
|
type InsertProject = Insertable<ProjectsTable>;
|
|
427
493
|
type UpdateProject = Updateable<ProjectsTable>;
|
|
@@ -435,9 +501,28 @@ type UpdateChatSession = Updateable<ChatSessionsTable>;
|
|
|
435
501
|
type ChatMessage = Selectable<ChatMessagesTable>;
|
|
436
502
|
type InsertChatMessage = Insertable<ChatMessagesTable>;
|
|
437
503
|
import { sql } from "kysely";
|
|
504
|
+
/**
|
|
505
|
+
* Kysely instance for the SOURCE DB (block/tx/event reads from the shared
|
|
506
|
+
* indexer). Resolution: `SOURCE_DATABASE_URL || DATABASE_URL`.
|
|
507
|
+
*/
|
|
508
|
+
declare function getSourceDb(): Kysely<Database>;
|
|
509
|
+
/**
|
|
510
|
+
* Kysely instance for the TARGET DB (subgraph schemas, subgraphs table,
|
|
511
|
+
* account-scoped data — tenant-side writes). Resolution:
|
|
512
|
+
* `TARGET_DATABASE_URL || DATABASE_URL`.
|
|
513
|
+
*/
|
|
514
|
+
declare function getTargetDb(): Kysely<Database>;
|
|
515
|
+
/**
|
|
516
|
+
* Backward-compat alias for `getTargetDb()`. Accepts an optional
|
|
517
|
+
* `connectionString` override used by seed/test helpers — when supplied,
|
|
518
|
+
* bypasses env resolution and uses the provided URL directly (still cached).
|
|
519
|
+
*/
|
|
438
520
|
declare function getDb(connectionString?: string): Kysely<Database>;
|
|
439
|
-
/**
|
|
440
|
-
|
|
441
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.).
|
|
523
|
+
* Defaults to the target role (tenant schemas live in the target DB).
|
|
524
|
+
*/
|
|
525
|
+
declare function getRawClient(role?: "source" | "target"): ReturnType<typeof postgres>;
|
|
526
|
+
/** Close all DB connection pools. Call in CLI commands to allow process exit. */
|
|
442
527
|
declare function closeDb(): Promise<void>;
|
|
443
|
-
export { sql, parseJsonb, jsonb, getRawClient, getDb, closeDb, WorkflowStepsTable, WorkflowStep, WorkflowSchedulesTable, WorkflowSchedule, WorkflowRunsTable, WorkflowRun, WorkflowQueueTable, WorkflowQueueItem, WorkflowDefinitionsTable, WorkflowDefinition, WorkflowCursorsTable, WorkflowCursor, WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateWorkflowStep, UpdateWorkflowSchedule, UpdateWorkflowRun, UpdateWorkflowDefinition, UpdateTransaction, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ProjectsTable, Project, MagicLinksTable, MagicLink, InsertWorkflowStep, InsertWorkflowSchedule, InsertWorkflowRun, InsertWorkflowQueueItem, InsertWorkflowDefinition, InsertTransaction, InsertTeamMember, InsertTeamInvitation, InsertSubgraphUsageDaily, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
|
|
528
|
+
export { sql, parseJsonb, jsonb, getTargetDb, getSourceDb, getRawClient, getDb, closeDb, WorkflowStepsTable, WorkflowStep, WorkflowSignerSecretsTable, WorkflowSignerSecret, WorkflowSchedulesTable, WorkflowSchedule, WorkflowRunsTable, WorkflowRun, WorkflowQueueTable, WorkflowQueueItem, WorkflowDefinitionsTable, WorkflowDefinition, WorkflowCursorsTable, WorkflowCursor, WorkflowBudgetsTable, WorkflowBudget, WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateWorkflowStep, UpdateWorkflowSignerSecret, UpdateWorkflowSchedule, UpdateWorkflowRun, UpdateWorkflowDefinition, UpdateWorkflowBudget, UpdateTransaction, UpdateTenant, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, TenantsTable, TenantStatus, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ProjectsTable, Project, MagicLinksTable, MagicLink, InsertWorkflowStep, InsertWorkflowSignerSecret, InsertWorkflowSchedule, InsertWorkflowRun, InsertWorkflowQueueItem, InsertWorkflowDefinition, InsertWorkflowBudget, InsertTransaction, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubgraphUsageDaily, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
|
package/dist/src/db/index.js
CHANGED
|
@@ -36,48 +36,72 @@ import { Kysely } from "kysely";
|
|
|
36
36
|
import { PostgresJSDialect } from "kysely-postgres-js";
|
|
37
37
|
import postgres from "postgres";
|
|
38
38
|
import { sql as sql2 } from "kysely";
|
|
39
|
-
var
|
|
40
|
-
var
|
|
39
|
+
var DEFAULT_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
40
|
+
var pools = new Map;
|
|
41
|
+
function resolveSourceUrl() {
|
|
42
|
+
return process.env.SOURCE_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
|
|
43
|
+
}
|
|
44
|
+
function resolveTargetUrl() {
|
|
45
|
+
return process.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
|
|
46
|
+
}
|
|
47
|
+
function getOrCreatePool(url) {
|
|
48
|
+
const existing = pools.get(url);
|
|
49
|
+
if (existing)
|
|
50
|
+
return existing;
|
|
51
|
+
const host = (() => {
|
|
52
|
+
try {
|
|
53
|
+
return new URL(url).hostname;
|
|
54
|
+
} catch {
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
const isLocal = host === "localhost" || host === "127.0.0.1" || !host.includes(".");
|
|
59
|
+
const poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
|
|
60
|
+
const rawClient = postgres(url, {
|
|
61
|
+
max: poolMax,
|
|
62
|
+
ssl: isLocal ? undefined : {
|
|
63
|
+
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0"
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const db = new Kysely({
|
|
67
|
+
dialect: new PostgresJSDialect({ postgres: rawClient })
|
|
68
|
+
});
|
|
69
|
+
const entry = { db, rawClient };
|
|
70
|
+
pools.set(url, entry);
|
|
71
|
+
return entry;
|
|
72
|
+
}
|
|
73
|
+
function getSourceDb() {
|
|
74
|
+
return getOrCreatePool(resolveSourceUrl()).db;
|
|
75
|
+
}
|
|
76
|
+
function getTargetDb() {
|
|
77
|
+
return getOrCreatePool(resolveTargetUrl()).db;
|
|
78
|
+
}
|
|
41
79
|
function getDb(connectionString) {
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
|
|
46
|
-
rawClient = postgres(url, {
|
|
47
|
-
max: poolMax,
|
|
48
|
-
ssl: isLocal ? undefined : {
|
|
49
|
-
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0"
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
db = new Kysely({
|
|
53
|
-
dialect: new PostgresJSDialect({ postgres: rawClient })
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return db;
|
|
80
|
+
if (connectionString)
|
|
81
|
+
return getOrCreatePool(connectionString).db;
|
|
82
|
+
return getTargetDb();
|
|
57
83
|
}
|
|
58
|
-
function getRawClient() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return rawClient;
|
|
84
|
+
function getRawClient(role = "target") {
|
|
85
|
+
const url = role === "source" ? resolveSourceUrl() : resolveTargetUrl();
|
|
86
|
+
return getOrCreatePool(url).rawClient;
|
|
62
87
|
}
|
|
63
88
|
async function closeDb() {
|
|
64
|
-
|
|
65
|
-
await db.destroy();
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
if (rawClient) {
|
|
69
|
-
await rawClient.end();
|
|
70
|
-
rawClient = null;
|
|
89
|
+
for (const entry of pools.values()) {
|
|
90
|
+
await entry.db.destroy();
|
|
91
|
+
await entry.rawClient.end();
|
|
71
92
|
}
|
|
93
|
+
pools.clear();
|
|
72
94
|
}
|
|
73
95
|
export {
|
|
74
96
|
sql2 as sql,
|
|
75
97
|
parseJsonb,
|
|
76
98
|
jsonb,
|
|
99
|
+
getTargetDb,
|
|
100
|
+
getSourceDb,
|
|
77
101
|
getRawClient,
|
|
78
102
|
getDb,
|
|
79
103
|
closeDb
|
|
80
104
|
};
|
|
81
105
|
|
|
82
|
-
//# debugId=
|
|
106
|
+
//# debugId=C0DD7408E000897364756E2164756E21
|
|
83
107
|
//# sourceMappingURL=index.js.map
|
package/dist/src/db/index.js.map
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/db/jsonb.ts", "../src/db/index.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)
|
|
6
|
-
"import { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport type { Database } from \"./types.ts\";\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 { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport type { Database } from \"./types.ts\";\n\nconst DEFAULT_URL =\n\t\"postgres://postgres:postgres@localhost:5432/secondlayer_dev\";\n\ninterface PoolEntry {\n\tdb: Kysely<Database>;\n\trawClient: ReturnType<typeof postgres>;\n}\n\n/**\n * Cache of Kysely + raw postgres.js pools keyed by resolved URL.\n * Two getters resolving to the same URL share one entry (single pool) —\n * this is the single-DB backward-compat contract: when only `DATABASE_URL`\n * is set, `getSourceDb() === getTargetDb()` (zero regression vs. pre-dual-DB).\n */\nconst pools = new Map<string, PoolEntry>();\n\nfunction resolveSourceUrl(): string {\n\treturn (\n\t\tprocess.env.SOURCE_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL\n\t);\n}\n\nfunction resolveTargetUrl(): string {\n\treturn (\n\t\tprocess.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL\n\t);\n}\n\nfunction getOrCreatePool(url: string): PoolEntry {\n\tconst existing = pools.get(url);\n\tif (existing) return existing;\n\n\t// \"Local\" = we skip TLS. Any Docker service alias (single-label hostname\n\t// with no dots) is on an internal network and won't serve TLS.\n\tconst host = (() => {\n\t\ttry {\n\t\t\treturn new URL(url).hostname;\n\t\t} catch {\n\t\t\treturn \"\";\n\t\t}\n\t})();\n\tconst isLocal =\n\t\thost === \"localhost\" || host === \"127.0.0.1\" || !host.includes(\".\");\n\tconst poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n\tconst rawClient = postgres(url, {\n\t\tmax: poolMax,\n\t\tssl: isLocal\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\trejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== \"0\",\n\t\t\t\t},\n\t});\n\tconst db = new Kysely<Database>({\n\t\tdialect: new PostgresJSDialect({ postgres: rawClient }),\n\t});\n\tconst entry: PoolEntry = { db, rawClient };\n\tpools.set(url, entry);\n\treturn entry;\n}\n\n/**\n * Kysely instance for the SOURCE DB (block/tx/event reads from the shared\n * indexer). Resolution: `SOURCE_DATABASE_URL || DATABASE_URL`.\n */\nexport function getSourceDb(): Kysely<Database> {\n\treturn getOrCreatePool(resolveSourceUrl()).db;\n}\n\n/**\n * Kysely instance for the TARGET DB (subgraph schemas, subgraphs table,\n * account-scoped data — tenant-side writes). Resolution:\n * `TARGET_DATABASE_URL || DATABASE_URL`.\n */\nexport function getTargetDb(): Kysely<Database> {\n\treturn getOrCreatePool(resolveTargetUrl()).db;\n}\n\n/**\n * Backward-compat alias for `getTargetDb()`. Accepts an optional\n * `connectionString` override used by seed/test helpers — when supplied,\n * bypasses env resolution and uses the provided URL directly (still cached).\n */\nexport function getDb(connectionString?: string): Kysely<Database> {\n\tif (connectionString) return getOrCreatePool(connectionString).db;\n\treturn getTargetDb();\n}\n\n/**\n * Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.).\n * Defaults to the target role (tenant schemas live in the target DB).\n */\nexport function getRawClient(\n\trole: \"source\" | \"target\" = \"target\",\n): ReturnType<typeof postgres> {\n\tconst url = role === \"source\" ? resolveSourceUrl() : resolveTargetUrl();\n\treturn getOrCreatePool(url).rawClient;\n}\n\n/** Close all DB connection pools. Call in CLI commands to allow process exit. */\nexport async function closeDb(): Promise<void> {\n\tfor (const entry of pools.values()) {\n\t\tawait entry.db.destroy();\n\t\tawait entry.rawClient.end();\n\t}\n\tpools.clear();\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,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,MAC1C,OAAO,MAAM,WAAW,EAAE,SAAS,IAAI,CACxC,EAAE,QAAQ,MAAM,IAAI;AAAA,EACpB,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQpC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EAC1D,IAAI,OAAO,UAAU,UAAU;AAAA,IAC9B,IAAI;AAAA,MACH,OAAO,KAAK,MAAM,KAAK;AAAA,MACtB,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,EAET;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;;;AC3BnB;AACA;AACA;AA8GA,gBAAS;AA3GT,IAAM,cACL;AAaD,IAAM,QAAQ,IAAI;AAElB,SAAS,gBAAgB,GAAW;AAAA,EACnC,OACC,QAAQ,IAAI,uBAAuB,QAAQ,IAAI,gBAAgB;AAAA;AAIjE,SAAS,gBAAgB,GAAW;AAAA,EACnC,OACC,QAAQ,IAAI,uBAAuB,QAAQ,IAAI,gBAAgB;AAAA;AAIjE,SAAS,eAAe,CAAC,KAAwB;AAAA,EAChD,MAAM,WAAW,MAAM,IAAI,GAAG;AAAA,EAC9B,IAAI;AAAA,IAAU,OAAO;AAAA,EAIrB,MAAM,QAAQ,MAAM;AAAA,IACnB,IAAI;AAAA,MACH,OAAO,IAAI,IAAI,GAAG,EAAE;AAAA,MACnB,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,KAEN;AAAA,EACH,MAAM,UACL,SAAS,eAAe,SAAS,eAAe,CAAC,KAAK,SAAS,GAAG;AAAA,EACnE,MAAM,UAAU,OAAO,SAAS,QAAQ,IAAI,qBAAqB,MAAM,EAAE;AAAA,EACzE,MAAM,YAAY,SAAS,KAAK;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK,UACF,YACA;AAAA,MACA,oBAAoB,QAAQ,IAAI,iCAAiC;AAAA,IAClE;AAAA,EACH,CAAC;AAAA,EACD,MAAM,KAAK,IAAI,OAAiB;AAAA,IAC/B,SAAS,IAAI,kBAAkB,EAAE,UAAU,UAAU,CAAC;AAAA,EACvD,CAAC;AAAA,EACD,MAAM,QAAmB,EAAE,IAAI,UAAU;AAAA,EACzC,MAAM,IAAI,KAAK,KAAK;AAAA,EACpB,OAAO;AAAA;AAOD,SAAS,WAAW,GAAqB;AAAA,EAC/C,OAAO,gBAAgB,iBAAiB,CAAC,EAAE;AAAA;AAQrC,SAAS,WAAW,GAAqB;AAAA,EAC/C,OAAO,gBAAgB,iBAAiB,CAAC,EAAE;AAAA;AAQrC,SAAS,KAAK,CAAC,kBAA6C;AAAA,EAClE,IAAI;AAAA,IAAkB,OAAO,gBAAgB,gBAAgB,EAAE;AAAA,EAC/D,OAAO,YAAY;AAAA;AAOb,SAAS,YAAY,CAC3B,OAA4B,UACE;AAAA,EAC9B,MAAM,MAAM,SAAS,WAAW,iBAAiB,IAAI,iBAAiB;AAAA,EACtE,OAAO,gBAAgB,GAAG,EAAE;AAAA;AAI7B,eAAsB,OAAO,GAAkB;AAAA,EAC9C,WAAW,SAAS,MAAM,OAAO,GAAG;AAAA,IACnC,MAAM,MAAM,GAAG,QAAQ;AAAA,IACvB,MAAM,MAAM,UAAU,IAAI;AAAA,EAC3B;AAAA,EACA,MAAM,MAAM;AAAA;",
|
|
9
|
+
"debugId": "C0DD7408E000897364756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/src/db/jsonb.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/db/jsonb.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)
|
|
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
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,MAC1C,OAAO,MAAM,WAAW,EAAE,SAAS,IAAI,CACxC,EAAE,QAAQ,MAAM,IAAI;AAAA,EACpB,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQpC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EAC1D,IAAI,OAAO,UAAU,UAAU;AAAA,IAC9B,IAAI;AAAA,MACH,OAAO,KAAK,MAAM,KAAK;AAAA,MACtB,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,EAET;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;",
|
|
8
8
|
"debugId": "DA6ABA81E2ABDC7864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Kysely } from "kysely";
|
|
2
2
|
import { Selectable as Selectable2 } from "kysely";
|
|
3
|
-
import { Generated, Selectable } from "kysely";
|
|
3
|
+
import { ColumnType, Generated, Selectable } from "kysely";
|
|
4
4
|
interface BlocksTable {
|
|
5
5
|
height: number;
|
|
6
6
|
hash: string;
|
|
@@ -57,7 +57,6 @@ interface SubgraphsTable {
|
|
|
57
57
|
last_error_at: Date | null;
|
|
58
58
|
total_processed: Generated<number>;
|
|
59
59
|
total_errors: Generated<number>;
|
|
60
|
-
api_key_id: string | null;
|
|
61
60
|
account_id: string;
|
|
62
61
|
handler_code: string | null;
|
|
63
62
|
source_code: string | null;
|
|
@@ -296,6 +295,8 @@ interface WorkflowStepsTable {
|
|
|
296
295
|
started_at: Date | null;
|
|
297
296
|
completed_at: Date | null;
|
|
298
297
|
duration_ms: number | null;
|
|
298
|
+
memo_key: string | null;
|
|
299
|
+
parent_step_id: string | null;
|
|
299
300
|
created_at: Generated<Date>;
|
|
300
301
|
}
|
|
301
302
|
interface WorkflowQueueTable {
|
|
@@ -357,6 +358,62 @@ interface Database {
|
|
|
357
358
|
workflow_queue: WorkflowQueueTable;
|
|
358
359
|
workflow_schedules: WorkflowSchedulesTable;
|
|
359
360
|
workflow_cursors: WorkflowCursorsTable;
|
|
361
|
+
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
362
|
+
workflow_budgets: WorkflowBudgetsTable;
|
|
363
|
+
tenants: TenantsTable;
|
|
364
|
+
}
|
|
365
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
366
|
+
interface TenantsTable {
|
|
367
|
+
id: Generated<string>;
|
|
368
|
+
account_id: string;
|
|
369
|
+
slug: string;
|
|
370
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
371
|
+
plan: string;
|
|
372
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
373
|
+
memory_mb: number;
|
|
374
|
+
storage_limit_mb: number;
|
|
375
|
+
storage_used_mb: number | null;
|
|
376
|
+
pg_container_id: string | null;
|
|
377
|
+
api_container_id: string | null;
|
|
378
|
+
processor_container_id: string | null;
|
|
379
|
+
target_database_url_enc: Buffer;
|
|
380
|
+
tenant_jwt_secret_enc: Buffer;
|
|
381
|
+
anon_key_enc: Buffer;
|
|
382
|
+
service_key_enc: Buffer;
|
|
383
|
+
api_url_internal: string;
|
|
384
|
+
api_url_public: string;
|
|
385
|
+
trial_ends_at: Date;
|
|
386
|
+
suspended_at: Date | null;
|
|
387
|
+
last_health_check_at: Date | null;
|
|
388
|
+
service_gen: Generated<number>;
|
|
389
|
+
anon_gen: Generated<number>;
|
|
390
|
+
project_id: string | null;
|
|
391
|
+
created_at: Generated<Date>;
|
|
392
|
+
updated_at: Generated<Date>;
|
|
393
|
+
}
|
|
394
|
+
interface WorkflowBudgetsTable {
|
|
395
|
+
id: Generated<string>;
|
|
396
|
+
workflow_definition_id: string;
|
|
397
|
+
/** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
|
|
398
|
+
period: string;
|
|
399
|
+
ai_usd_used: Generated<string>;
|
|
400
|
+
ai_tokens_used: Generated<string>;
|
|
401
|
+
chain_microstx_used: Generated<string>;
|
|
402
|
+
chain_tx_count: Generated<number>;
|
|
403
|
+
run_count: Generated<number>;
|
|
404
|
+
step_count: Generated<number>;
|
|
405
|
+
reset_at: Date;
|
|
406
|
+
created_at: Generated<Date>;
|
|
407
|
+
updated_at: Generated<Date>;
|
|
408
|
+
}
|
|
409
|
+
interface WorkflowSignerSecretsTable {
|
|
410
|
+
id: Generated<string>;
|
|
411
|
+
account_id: string;
|
|
412
|
+
name: string;
|
|
413
|
+
/** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
|
|
414
|
+
encrypted_value: Buffer;
|
|
415
|
+
created_at: Generated<Date>;
|
|
416
|
+
updated_at: Generated<Date>;
|
|
360
417
|
}
|
|
361
418
|
type Account = Selectable<AccountsTable>;
|
|
362
419
|
declare function upsertAccount(db: Kysely<Database>, email: string): Promise<Account>;
|
|
@@ -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 Gap {
|
|
361
418
|
gapStart: 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,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 Subgraph = Selectable<SubgraphsTable>;
|
|
361
418
|
/**
|