@secondlayer/shared 6.3.4 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/src/crypto/secrets.js +2 -5
  2. package/dist/src/crypto/secrets.js.map +3 -3
  3. package/dist/src/db/index.d.ts +6 -1
  4. package/dist/src/db/queries/account-spend-caps.d.ts +5 -0
  5. package/dist/src/db/queries/account-usage.d.ts +5 -0
  6. package/dist/src/db/queries/accounts.d.ts +5 -0
  7. package/dist/src/db/queries/chain-reorgs.d.ts +5 -0
  8. package/dist/src/db/queries/integrity.d.ts +5 -0
  9. package/dist/src/db/queries/projects.d.ts +5 -0
  10. package/dist/src/db/queries/provisioning-audit.d.ts +5 -0
  11. package/dist/src/db/queries/subgraph-gaps.d.ts +5 -0
  12. package/dist/src/db/queries/subgraph-operations.d.ts +5 -0
  13. package/dist/src/db/queries/subgraphs.d.ts +5 -0
  14. package/dist/src/db/queries/subscriptions.d.ts +5 -0
  15. package/dist/src/db/queries/subscriptions.js +2 -5
  16. package/dist/src/db/queries/subscriptions.js.map +3 -3
  17. package/dist/src/db/queries/tenant-compute-addons.d.ts +5 -0
  18. package/dist/src/db/queries/usage.d.ts +5 -0
  19. package/dist/src/db/schema.d.ts +6 -1
  20. package/dist/src/index.d.ts +6 -1
  21. package/dist/src/mode.d.ts +6 -12
  22. package/dist/src/mode.js +2 -6
  23. package/dist/src/mode.js.map +3 -3
  24. package/dist/src/node/local-client.d.ts +5 -0
  25. package/migrations/0074_service_heartbeats.ts +23 -0
  26. package/migrations/0075_restore_subgraphs_on_platform.ts +166 -0
  27. package/migrations/0076_deprecate_tenants.ts +19 -0
  28. package/package.json +1 -1
  29. package/dist/src/db/queries/tenants.d.ts +0 -795
  30. package/dist/src/db/queries/tenants.js +0 -308
  31. package/dist/src/db/queries/tenants.js.map +0 -12
@@ -0,0 +1,166 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ /**
4
+ * Restore `subgraphs` + `subgraph_operations` on platform DBs that lost them
5
+ * during the shared→dedicated cutover (manual drop after 0041; see note in
6
+ * 0045). After the 2026-05-14 shared-rip pivot, the platform subgraph-processor
7
+ * crashes with `relation "subgraphs" does not exist` because no migration ever
8
+ * recreated the parent table — only the satellite tables (gaps, stats,
9
+ * snapshots, usage_daily) survived.
10
+ *
11
+ * Idempotent: each step is guarded so this is a no-op on DBs that already have
12
+ * the tables (OSS, fresh dev, or any tenant DB).
13
+ */
14
+
15
+ async function tableExists(
16
+ db: Kysely<unknown>,
17
+ tableName: string,
18
+ ): Promise<boolean> {
19
+ const { rows } = await sql<{ exists: boolean }>`
20
+ SELECT to_regclass(${`public.${tableName}`}) IS NOT NULL AS exists
21
+ `.execute(db);
22
+ return rows[0]?.exists === true;
23
+ }
24
+
25
+ export async function up(db: Kysely<unknown>): Promise<void> {
26
+ if (!(await tableExists(db, "subgraphs"))) {
27
+ await sql`
28
+ CREATE TABLE subgraphs (
29
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
30
+ name text NOT NULL,
31
+ version text NOT NULL DEFAULT '1.0.0',
32
+ status text NOT NULL DEFAULT 'active',
33
+ definition jsonb NOT NULL,
34
+ schema_hash text NOT NULL,
35
+ handler_path text NOT NULL,
36
+ schema_name text,
37
+ start_block bigint NOT NULL DEFAULT 0,
38
+ last_processed_block bigint NOT NULL DEFAULT 0,
39
+ reindex_from_block bigint,
40
+ reindex_to_block bigint,
41
+ last_error text,
42
+ last_error_at timestamptz,
43
+ total_processed bigint NOT NULL DEFAULT 0,
44
+ total_errors bigint NOT NULL DEFAULT 0,
45
+ account_id text NOT NULL,
46
+ handler_code text,
47
+ source_code text,
48
+ project_id uuid REFERENCES projects(id) ON DELETE SET NULL,
49
+ created_at timestamptz NOT NULL DEFAULT now(),
50
+ updated_at timestamptz NOT NULL DEFAULT now()
51
+ )
52
+ `.execute(db);
53
+
54
+ await sql`CREATE INDEX subgraphs_name_idx ON subgraphs (name)`.execute(db);
55
+ await sql`CREATE INDEX subgraphs_status_idx ON subgraphs (status)`.execute(
56
+ db,
57
+ );
58
+ await sql`CREATE UNIQUE INDEX subgraphs_name_account_id_unique ON subgraphs (name, account_id)`.execute(
59
+ db,
60
+ );
61
+ await sql`CREATE INDEX subgraphs_account_id_idx ON subgraphs (account_id)`.execute(
62
+ db,
63
+ );
64
+
65
+ await sql`
66
+ CREATE OR REPLACE FUNCTION notify_subgraph_changes() RETURNS trigger AS $$
67
+ BEGIN
68
+ PERFORM pg_notify('subgraph_changes', json_build_object(
69
+ 'operation', TG_OP,
70
+ 'name', COALESCE(NEW.name, OLD.name)
71
+ )::text);
72
+ RETURN COALESCE(NEW, OLD);
73
+ END;
74
+ $$ LANGUAGE plpgsql
75
+ `.execute(db);
76
+
77
+ await sql`DROP TRIGGER IF EXISTS subgraphs_notify_trigger ON subgraphs`.execute(
78
+ db,
79
+ );
80
+ await sql`
81
+ CREATE TRIGGER subgraphs_notify_trigger
82
+ AFTER INSERT OR UPDATE OR DELETE ON subgraphs
83
+ FOR EACH ROW EXECUTE FUNCTION notify_subgraph_changes()
84
+ `.execute(db);
85
+ }
86
+
87
+ if (!(await tableExists(db, "subgraph_operations"))) {
88
+ await sql`
89
+ CREATE TABLE subgraph_operations (
90
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
91
+ subgraph_id uuid NOT NULL REFERENCES subgraphs(id) ON DELETE CASCADE,
92
+ subgraph_name text NOT NULL,
93
+ account_id text,
94
+ kind text NOT NULL CHECK (kind IN ('reindex', 'backfill')),
95
+ status text NOT NULL DEFAULT 'queued' CHECK (status IN ('queued', 'running', 'completed', 'failed', 'cancelled')),
96
+ from_block bigint,
97
+ to_block bigint,
98
+ cancel_requested boolean NOT NULL DEFAULT false,
99
+ locked_by text,
100
+ locked_until timestamptz,
101
+ started_at timestamptz,
102
+ finished_at timestamptz,
103
+ processed_blocks bigint,
104
+ error text,
105
+ created_at timestamptz NOT NULL DEFAULT now(),
106
+ updated_at timestamptz NOT NULL DEFAULT now()
107
+ )
108
+ `.execute(db);
109
+
110
+ await sql`
111
+ CREATE UNIQUE INDEX subgraph_operations_active_unique
112
+ ON subgraph_operations (subgraph_id)
113
+ WHERE status IN ('queued', 'running')
114
+ `.execute(db);
115
+
116
+ await sql`
117
+ CREATE INDEX subgraph_operations_claim_idx
118
+ ON subgraph_operations (created_at)
119
+ WHERE status = 'queued'
120
+ `.execute(db);
121
+
122
+ await sql`
123
+ CREATE INDEX subgraph_operations_stale_running_idx
124
+ ON subgraph_operations (locked_until)
125
+ WHERE status = 'running'
126
+ `.execute(db);
127
+
128
+ await sql`
129
+ CREATE OR REPLACE FUNCTION notify_subgraph_operation_new()
130
+ RETURNS trigger AS $$
131
+ BEGIN
132
+ PERFORM pg_notify('subgraph_operations:new', NEW.id::text);
133
+ RETURN NEW;
134
+ END;
135
+ $$ LANGUAGE plpgsql
136
+ `.execute(db);
137
+
138
+ await sql`DROP TRIGGER IF EXISTS subgraph_operations_insert_notify ON subgraph_operations`.execute(
139
+ db,
140
+ );
141
+ await sql`
142
+ CREATE TRIGGER subgraph_operations_insert_notify
143
+ AFTER INSERT ON subgraph_operations
144
+ FOR EACH ROW
145
+ WHEN (NEW.status = 'queued')
146
+ EXECUTE FUNCTION notify_subgraph_operation_new()
147
+ `.execute(db);
148
+
149
+ await sql`DROP TRIGGER IF EXISTS subgraph_operations_cancel_notify ON subgraph_operations`.execute(
150
+ db,
151
+ );
152
+ await sql`
153
+ CREATE TRIGGER subgraph_operations_cancel_notify
154
+ AFTER UPDATE OF cancel_requested ON subgraph_operations
155
+ FOR EACH ROW
156
+ WHEN (NEW.cancel_requested = true AND OLD.cancel_requested IS DISTINCT FROM NEW.cancel_requested)
157
+ EXECUTE FUNCTION notify_subgraph_operation_new()
158
+ `.execute(db);
159
+ }
160
+ }
161
+
162
+ export async function down(_db: Kysely<unknown>): Promise<void> {
163
+ // No-op. Rolling back would drop tables that existed pre-migration on the
164
+ // dedicated-tenant + OSS code paths and risk data loss on platform once the
165
+ // processor starts writing. If a true rollback is needed, do it manually.
166
+ }
@@ -0,0 +1,19 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ /**
4
+ * Mark the `tenants` table deprecated. The 2026-05-14 shared-rip pivot
5
+ * collapsed the dedicated per-tenant model — no live writers remain. Rows
6
+ * are preserved here for post-pivot reconciliation. A follow-up migration
7
+ * will `DROP TABLE` after a 2-cycle observation window when we're sure no
8
+ * Stripe-dormant reader references `tenants.plan`.
9
+ */
10
+ export async function up(db: Kysely<unknown>): Promise<void> {
11
+ await sql`
12
+ COMMENT ON TABLE tenants IS
13
+ 'DEPRECATED 2026-05-16: post shared-rip, no live writers. Drop after observation window.'
14
+ `.execute(db);
15
+ }
16
+
17
+ export async function down(_db: Kysely<unknown>): Promise<void> {
18
+ // No-op — restoring the comment to nothing on rollback is not useful.
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/shared",
3
- "version": "6.3.4",
3
+ "version": "6.4.0",
4
4
  "type": "module",
5
5
  "main": "./dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",