@secondlayer/shared 1.1.0 → 2.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/dist/src/db/index.d.ts +89 -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 +58 -2
- package/dist/src/db/queries/integrity.d.ts +58 -2
- package/dist/src/db/queries/projects.d.ts +58 -2
- package/dist/src/db/queries/projects.js.map +2 -2
- package/dist/src/db/queries/{marketplace.d.ts → provisioning-audit.d.ts} +79 -56
- package/dist/src/db/queries/provisioning-audit.js +40 -0
- package/dist/src/db/queries/provisioning-audit.js.map +10 -0
- package/dist/src/db/queries/subgraph-gaps.d.ts +58 -2
- package/dist/src/db/queries/subgraphs.d.ts +62 -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 +527 -0
- package/dist/src/db/queries/tenants.js +220 -0
- package/dist/src/db/queries/tenants.js.map +11 -0
- package/dist/src/db/queries/usage.d.ts +58 -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 +58 -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 +67 -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 +142 -84
- package/dist/src/index.js +146 -99
- package/dist/src/index.js.map +8 -8
- package/dist/src/logger.js +3 -1
- package/dist/src/logger.js.map +3 -3
- package/dist/src/mode.d.ts +29 -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 +58 -2
- 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/schemas/accounts.d.ts +14 -0
- package/dist/src/schemas/{marketplace.js → accounts.js} +4 -14
- package/dist/src/schemas/accounts.js.map +10 -0
- package/dist/src/schemas/index.d.ts +28 -77
- package/dist/src/schemas/index.js +59 -69
- package/dist/src/schemas/index.js.map +4 -4
- package/dist/src/types.d.ts +10 -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/migrations/0043_tenant_usage_monthly.ts +36 -0
- package/migrations/0044_provisioning_audit_log.ts +40 -0
- package/package.json +15 -7
- package/dist/src/db/queries/marketplace.js +0 -142
- package/dist/src/db/queries/marketplace.js.map +0 -10
- package/dist/src/schemas/marketplace.d.ts +0 -63
- package/dist/src/schemas/marketplace.js.map +0 -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;
|
|
@@ -360,7 +359,65 @@ interface Database {
|
|
|
360
359
|
workflow_cursors: WorkflowCursorsTable;
|
|
361
360
|
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
362
361
|
workflow_budgets: WorkflowBudgetsTable;
|
|
362
|
+
tenants: TenantsTable;
|
|
363
|
+
tenant_usage_monthly: TenantUsageMonthlyTable;
|
|
364
|
+
provisioning_audit_log: ProvisioningAuditLogTable;
|
|
365
|
+
}
|
|
366
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
367
|
+
interface TenantsTable {
|
|
368
|
+
id: Generated<string>;
|
|
369
|
+
account_id: string;
|
|
370
|
+
slug: string;
|
|
371
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
372
|
+
plan: string;
|
|
373
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
374
|
+
memory_mb: number;
|
|
375
|
+
storage_limit_mb: number;
|
|
376
|
+
storage_used_mb: number | null;
|
|
377
|
+
pg_container_id: string | null;
|
|
378
|
+
api_container_id: string | null;
|
|
379
|
+
processor_container_id: string | null;
|
|
380
|
+
target_database_url_enc: Buffer;
|
|
381
|
+
tenant_jwt_secret_enc: Buffer;
|
|
382
|
+
anon_key_enc: Buffer;
|
|
383
|
+
service_key_enc: Buffer;
|
|
384
|
+
api_url_internal: string;
|
|
385
|
+
api_url_public: string;
|
|
386
|
+
trial_ends_at: Date;
|
|
387
|
+
suspended_at: Date | null;
|
|
388
|
+
last_health_check_at: Date | null;
|
|
389
|
+
service_gen: Generated<number>;
|
|
390
|
+
anon_gen: Generated<number>;
|
|
391
|
+
project_id: string | null;
|
|
392
|
+
created_at: Generated<Date>;
|
|
393
|
+
updated_at: Generated<Date>;
|
|
363
394
|
}
|
|
395
|
+
interface TenantUsageMonthlyTable {
|
|
396
|
+
id: Generated<string>;
|
|
397
|
+
tenant_id: string;
|
|
398
|
+
period_month: Date;
|
|
399
|
+
storage_peak_mb: Generated<number>;
|
|
400
|
+
storage_avg_mb: Generated<number>;
|
|
401
|
+
storage_last_mb: Generated<number>;
|
|
402
|
+
measurements: Generated<number>;
|
|
403
|
+
first_at: Generated<Date>;
|
|
404
|
+
last_at: Generated<Date>;
|
|
405
|
+
}
|
|
406
|
+
type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
|
|
407
|
+
type ProvisioningAuditStatus = "ok" | "error";
|
|
408
|
+
interface ProvisioningAuditLogTable {
|
|
409
|
+
id: Generated<string>;
|
|
410
|
+
tenant_id: string | null;
|
|
411
|
+
tenant_slug: string | null;
|
|
412
|
+
account_id: string | null;
|
|
413
|
+
actor: string;
|
|
414
|
+
event: ProvisioningAuditEvent;
|
|
415
|
+
status: ProvisioningAuditStatus;
|
|
416
|
+
detail: unknown | null;
|
|
417
|
+
error: string | null;
|
|
418
|
+
created_at: Generated<Date>;
|
|
419
|
+
}
|
|
420
|
+
type ProvisioningAuditLog = Selectable<ProvisioningAuditLogTable>;
|
|
364
421
|
interface WorkflowBudgetsTable {
|
|
365
422
|
id: Generated<string>;
|
|
366
423
|
workflow_definition_id: string;
|
|
@@ -385,59 +442,25 @@ interface WorkflowSignerSecretsTable {
|
|
|
385
442
|
created_at: Generated<Date>;
|
|
386
443
|
updated_at: Generated<Date>;
|
|
387
444
|
}
|
|
388
|
-
type Subgraph = Selectable<SubgraphsTable>;
|
|
389
|
-
/**
|
|
390
|
-
* List public subgraphs with creator info and usage stats.
|
|
391
|
-
*/
|
|
392
|
-
declare function listPublicSubgraphs(db: Kysely<Database>, opts?: {
|
|
393
|
-
limit?: number
|
|
394
|
-
offset?: number
|
|
395
|
-
tags?: string[]
|
|
396
|
-
search?: string
|
|
397
|
-
sort?: "recent" | "popular" | "name"
|
|
398
|
-
}): Promise<{
|
|
399
|
-
data: any[]
|
|
400
|
-
meta: {
|
|
401
|
-
total: number
|
|
402
|
-
limit: number
|
|
403
|
-
offset: number
|
|
404
|
-
}
|
|
405
|
-
}>;
|
|
406
|
-
/**
|
|
407
|
-
* Get a single public subgraph by name with creator info.
|
|
408
|
-
*/
|
|
409
|
-
declare function getPublicSubgraph(db: Kysely<Database>, name: string): Promise<any | undefined>;
|
|
410
|
-
/**
|
|
411
|
-
* Get a creator profile by slug with their public subgraphs.
|
|
412
|
-
*/
|
|
413
|
-
declare function getCreatorProfile(db: Kysely<Database>, slug: string): Promise<{
|
|
414
|
-
account: any
|
|
415
|
-
subgraphs: any[]
|
|
416
|
-
} | null>;
|
|
417
|
-
/**
|
|
418
|
-
* Publish a subgraph (set is_public = true).
|
|
419
|
-
*/
|
|
420
|
-
declare function publishSubgraph(db: Kysely<Database>, subgraphId: string, opts?: {
|
|
421
|
-
tags?: string[]
|
|
422
|
-
description?: string
|
|
423
|
-
}): Promise<Subgraph>;
|
|
424
|
-
/**
|
|
425
|
-
* Unpublish a subgraph (set is_public = false).
|
|
426
|
-
*/
|
|
427
|
-
declare function unpublishSubgraph(db: Kysely<Database>, subgraphId: string): Promise<Subgraph>;
|
|
428
|
-
/**
|
|
429
|
-
* Increment per-subgraph query count for today. Fire-and-forget safe.
|
|
430
|
-
*/
|
|
431
|
-
declare function incrementSubgraphQueryCount(db: Kysely<Database>, subgraphId: string): Promise<void>;
|
|
432
|
-
/**
|
|
433
|
-
* Get daily usage history for a subgraph.
|
|
434
|
-
*/
|
|
435
|
-
declare function getSubgraphUsageHistory(db: Kysely<Database>, subgraphId: string, days: number): Promise<Array<{
|
|
436
|
-
date: string
|
|
437
|
-
query_count: number
|
|
438
|
-
}>>;
|
|
439
445
|
/**
|
|
440
|
-
*
|
|
446
|
+
* Provisioning audit trail — every lifecycle event that mutates a tenant
|
|
447
|
+
* lands here. Write on both happy and sad paths so we can reconstruct
|
|
448
|
+
* what was attempted and what failed.
|
|
449
|
+
*
|
|
450
|
+
* `actor` is the logical source (e.g. `account:<uuid>`, `worker:tenant-health`,
|
|
451
|
+
* `admin:<uuid>`). Keep it grep-able — this is the only breadcrumb when
|
|
452
|
+
* something goes sideways.
|
|
441
453
|
*/
|
|
442
|
-
|
|
443
|
-
|
|
454
|
+
interface AuditInput {
|
|
455
|
+
tenantId?: string | null;
|
|
456
|
+
tenantSlug?: string | null;
|
|
457
|
+
accountId?: string | null;
|
|
458
|
+
actor: string;
|
|
459
|
+
event: ProvisioningAuditEvent;
|
|
460
|
+
status: ProvisioningAuditStatus;
|
|
461
|
+
detail?: unknown;
|
|
462
|
+
error?: string;
|
|
463
|
+
}
|
|
464
|
+
declare function recordProvisioningAudit(db: Kysely<Database>, input: AuditInput): Promise<void>;
|
|
465
|
+
declare function listAuditForTenant(db: Kysely<Database>, tenantId: string, limit?: number): Promise<ProvisioningAuditLog[]>;
|
|
466
|
+
export { recordProvisioningAudit, listAuditForTenant, AuditInput };
|
|
@@ -0,0 +1,40 @@
|
|
|
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/db/queries/provisioning-audit.ts
|
|
18
|
+
async function recordProvisioningAudit(db, input) {
|
|
19
|
+
const row = {
|
|
20
|
+
tenant_id: input.tenantId ?? null,
|
|
21
|
+
tenant_slug: input.tenantSlug ?? null,
|
|
22
|
+
account_id: input.accountId ?? null,
|
|
23
|
+
actor: input.actor,
|
|
24
|
+
event: input.event,
|
|
25
|
+
status: input.status,
|
|
26
|
+
detail: input.detail ?? null,
|
|
27
|
+
error: input.error ?? null
|
|
28
|
+
};
|
|
29
|
+
await db.insertInto("provisioning_audit_log").values(row).execute();
|
|
30
|
+
}
|
|
31
|
+
async function listAuditForTenant(db, tenantId, limit = 50) {
|
|
32
|
+
return db.selectFrom("provisioning_audit_log").selectAll().where("tenant_id", "=", tenantId).orderBy("created_at", "desc").limit(limit).execute();
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
recordProvisioningAudit,
|
|
36
|
+
listAuditForTenant
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
//# debugId=DF2744A82ED5118E64756E2164756E21
|
|
40
|
+
//# sourceMappingURL=provisioning-audit.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/db/queries/provisioning-audit.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Kysely } from \"kysely\";\nimport type {\n\tDatabase,\n\tInsertProvisioningAuditLog,\n\tProvisioningAuditEvent,\n\tProvisioningAuditLog,\n\tProvisioningAuditStatus,\n} from \"../types.ts\";\n\n/**\n * Provisioning audit trail — every lifecycle event that mutates a tenant\n * lands here. Write on both happy and sad paths so we can reconstruct\n * what was attempted and what failed.\n *\n * `actor` is the logical source (e.g. `account:<uuid>`, `worker:tenant-health`,\n * `admin:<uuid>`). Keep it grep-able — this is the only breadcrumb when\n * something goes sideways.\n */\n\nexport interface AuditInput {\n\ttenantId?: string | null;\n\ttenantSlug?: string | null;\n\taccountId?: string | null;\n\tactor: string;\n\tevent: ProvisioningAuditEvent;\n\tstatus: ProvisioningAuditStatus;\n\tdetail?: unknown;\n\terror?: string;\n}\n\nexport async function recordProvisioningAudit(\n\tdb: Kysely<Database>,\n\tinput: AuditInput,\n): Promise<void> {\n\tconst row: InsertProvisioningAuditLog = {\n\t\ttenant_id: input.tenantId ?? null,\n\t\ttenant_slug: input.tenantSlug ?? null,\n\t\taccount_id: input.accountId ?? null,\n\t\tactor: input.actor,\n\t\tevent: input.event,\n\t\tstatus: input.status,\n\t\tdetail: input.detail ?? null,\n\t\terror: input.error ?? null,\n\t};\n\tawait db.insertInto(\"provisioning_audit_log\").values(row).execute();\n}\n\nexport async function listAuditForTenant(\n\tdb: Kysely<Database>,\n\ttenantId: string,\n\tlimit = 50,\n): Promise<ProvisioningAuditLog[]> {\n\treturn db\n\t\t.selectFrom(\"provisioning_audit_log\")\n\t\t.selectAll()\n\t\t.where(\"tenant_id\", \"=\", tenantId)\n\t\t.orderBy(\"created_at\", \"desc\")\n\t\t.limit(limit)\n\t\t.execute();\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AA8BA,eAAsB,uBAAuB,CAC5C,IACA,OACgB;AAAA,EAChB,MAAM,MAAkC;AAAA,IACvC,WAAW,MAAM,YAAY;AAAA,IAC7B,aAAa,MAAM,cAAc;AAAA,IACjC,YAAY,MAAM,aAAa;AAAA,IAC/B,OAAO,MAAM;AAAA,IACb,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,IACd,QAAQ,MAAM,UAAU;AAAA,IACxB,OAAO,MAAM,SAAS;AAAA,EACvB;AAAA,EACA,MAAM,GAAG,WAAW,wBAAwB,EAAE,OAAO,GAAG,EAAE,QAAQ;AAAA;AAGnE,eAAsB,kBAAkB,CACvC,IACA,UACA,QAAQ,IAC0B;AAAA,EAClC,OAAO,GACL,WAAW,wBAAwB,EACnC,UAAU,EACV,MAAM,aAAa,KAAK,QAAQ,EAChC,QAAQ,cAAc,MAAM,EAC5B,MAAM,KAAK,EACX,QAAQ;AAAA;",
|
|
8
|
+
"debugId": "DF2744A82ED5118E64756E2164756E21",
|
|
9
|
+
"names": []
|
|
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;
|
|
@@ -360,6 +359,63 @@ interface Database {
|
|
|
360
359
|
workflow_cursors: WorkflowCursorsTable;
|
|
361
360
|
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
362
361
|
workflow_budgets: WorkflowBudgetsTable;
|
|
362
|
+
tenants: TenantsTable;
|
|
363
|
+
tenant_usage_monthly: TenantUsageMonthlyTable;
|
|
364
|
+
provisioning_audit_log: ProvisioningAuditLogTable;
|
|
365
|
+
}
|
|
366
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
367
|
+
interface TenantsTable {
|
|
368
|
+
id: Generated<string>;
|
|
369
|
+
account_id: string;
|
|
370
|
+
slug: string;
|
|
371
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
372
|
+
plan: string;
|
|
373
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
374
|
+
memory_mb: number;
|
|
375
|
+
storage_limit_mb: number;
|
|
376
|
+
storage_used_mb: number | null;
|
|
377
|
+
pg_container_id: string | null;
|
|
378
|
+
api_container_id: string | null;
|
|
379
|
+
processor_container_id: string | null;
|
|
380
|
+
target_database_url_enc: Buffer;
|
|
381
|
+
tenant_jwt_secret_enc: Buffer;
|
|
382
|
+
anon_key_enc: Buffer;
|
|
383
|
+
service_key_enc: Buffer;
|
|
384
|
+
api_url_internal: string;
|
|
385
|
+
api_url_public: string;
|
|
386
|
+
trial_ends_at: Date;
|
|
387
|
+
suspended_at: Date | null;
|
|
388
|
+
last_health_check_at: Date | null;
|
|
389
|
+
service_gen: Generated<number>;
|
|
390
|
+
anon_gen: Generated<number>;
|
|
391
|
+
project_id: string | null;
|
|
392
|
+
created_at: Generated<Date>;
|
|
393
|
+
updated_at: Generated<Date>;
|
|
394
|
+
}
|
|
395
|
+
interface TenantUsageMonthlyTable {
|
|
396
|
+
id: Generated<string>;
|
|
397
|
+
tenant_id: string;
|
|
398
|
+
period_month: Date;
|
|
399
|
+
storage_peak_mb: Generated<number>;
|
|
400
|
+
storage_avg_mb: Generated<number>;
|
|
401
|
+
storage_last_mb: Generated<number>;
|
|
402
|
+
measurements: Generated<number>;
|
|
403
|
+
first_at: Generated<Date>;
|
|
404
|
+
last_at: Generated<Date>;
|
|
405
|
+
}
|
|
406
|
+
type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
|
|
407
|
+
type ProvisioningAuditStatus = "ok" | "error";
|
|
408
|
+
interface ProvisioningAuditLogTable {
|
|
409
|
+
id: Generated<string>;
|
|
410
|
+
tenant_id: string | null;
|
|
411
|
+
tenant_slug: string | null;
|
|
412
|
+
account_id: string | null;
|
|
413
|
+
actor: string;
|
|
414
|
+
event: ProvisioningAuditEvent;
|
|
415
|
+
status: ProvisioningAuditStatus;
|
|
416
|
+
detail: unknown | null;
|
|
417
|
+
error: string | null;
|
|
418
|
+
created_at: Generated<Date>;
|
|
363
419
|
}
|
|
364
420
|
interface WorkflowBudgetsTable {
|
|
365
421
|
id: Generated<string>;
|
|
@@ -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;
|
|
@@ -360,6 +359,63 @@ interface Database {
|
|
|
360
359
|
workflow_cursors: WorkflowCursorsTable;
|
|
361
360
|
workflow_signer_secrets: WorkflowSignerSecretsTable;
|
|
362
361
|
workflow_budgets: WorkflowBudgetsTable;
|
|
362
|
+
tenants: TenantsTable;
|
|
363
|
+
tenant_usage_monthly: TenantUsageMonthlyTable;
|
|
364
|
+
provisioning_audit_log: ProvisioningAuditLogTable;
|
|
365
|
+
}
|
|
366
|
+
type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
|
|
367
|
+
interface TenantsTable {
|
|
368
|
+
id: Generated<string>;
|
|
369
|
+
account_id: string;
|
|
370
|
+
slug: string;
|
|
371
|
+
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
372
|
+
plan: string;
|
|
373
|
+
cpus: ColumnType<number, number | string, number | string>;
|
|
374
|
+
memory_mb: number;
|
|
375
|
+
storage_limit_mb: number;
|
|
376
|
+
storage_used_mb: number | null;
|
|
377
|
+
pg_container_id: string | null;
|
|
378
|
+
api_container_id: string | null;
|
|
379
|
+
processor_container_id: string | null;
|
|
380
|
+
target_database_url_enc: Buffer;
|
|
381
|
+
tenant_jwt_secret_enc: Buffer;
|
|
382
|
+
anon_key_enc: Buffer;
|
|
383
|
+
service_key_enc: Buffer;
|
|
384
|
+
api_url_internal: string;
|
|
385
|
+
api_url_public: string;
|
|
386
|
+
trial_ends_at: Date;
|
|
387
|
+
suspended_at: Date | null;
|
|
388
|
+
last_health_check_at: Date | null;
|
|
389
|
+
service_gen: Generated<number>;
|
|
390
|
+
anon_gen: Generated<number>;
|
|
391
|
+
project_id: string | null;
|
|
392
|
+
created_at: Generated<Date>;
|
|
393
|
+
updated_at: Generated<Date>;
|
|
394
|
+
}
|
|
395
|
+
interface TenantUsageMonthlyTable {
|
|
396
|
+
id: Generated<string>;
|
|
397
|
+
tenant_id: string;
|
|
398
|
+
period_month: Date;
|
|
399
|
+
storage_peak_mb: Generated<number>;
|
|
400
|
+
storage_avg_mb: Generated<number>;
|
|
401
|
+
storage_last_mb: Generated<number>;
|
|
402
|
+
measurements: Generated<number>;
|
|
403
|
+
first_at: Generated<Date>;
|
|
404
|
+
last_at: Generated<Date>;
|
|
405
|
+
}
|
|
406
|
+
type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
|
|
407
|
+
type ProvisioningAuditStatus = "ok" | "error";
|
|
408
|
+
interface ProvisioningAuditLogTable {
|
|
409
|
+
id: Generated<string>;
|
|
410
|
+
tenant_id: string | null;
|
|
411
|
+
tenant_slug: string | null;
|
|
412
|
+
account_id: string | null;
|
|
413
|
+
actor: string;
|
|
414
|
+
event: ProvisioningAuditEvent;
|
|
415
|
+
status: ProvisioningAuditStatus;
|
|
416
|
+
detail: unknown | null;
|
|
417
|
+
error: string | null;
|
|
418
|
+
created_at: Generated<Date>;
|
|
363
419
|
}
|
|
364
420
|
interface WorkflowBudgetsTable {
|
|
365
421
|
id: Generated<string>;
|
|
@@ -388,10 +444,11 @@ interface WorkflowSignerSecretsTable {
|
|
|
388
444
|
type Subgraph = Selectable<SubgraphsTable>;
|
|
389
445
|
/**
|
|
390
446
|
* Convert a subgraph name to its PostgreSQL schema name.
|
|
391
|
-
*
|
|
392
|
-
*
|
|
447
|
+
* Every tenant DB has its own isolated schema namespace, so there's no
|
|
448
|
+
* account-prefix disambiguation needed — every subgraph within a tenant
|
|
449
|
+
* just maps to `subgraph_{safeName}`.
|
|
393
450
|
*/
|
|
394
|
-
declare function pgSchemaName(subgraphName: string
|
|
451
|
+
declare function pgSchemaName(subgraphName: string): string;
|
|
395
452
|
declare function registerSubgraph(db: Kysely<Database>, data: {
|
|
396
453
|
name: string
|
|
397
454
|
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
|
|
36
|
+
function pgSchemaName(subgraphName) {
|
|
37
37
|
const safeName = subgraphName.replace(/-/g, "_");
|
|
38
|
-
|
|
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=
|
|
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)
|
|
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 *
|
|
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": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "AE963057007E387C64756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|