tinbase 0.2.2 → 0.6.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 (94) hide show
  1. package/README.md +64 -31
  2. package/dist/admin/api.d.ts +8 -1
  3. package/dist/admin/api.js +94 -1
  4. package/dist/admin/api.js.map +1 -1
  5. package/dist/admin/ui.d.ts +1 -1
  6. package/dist/admin/ui.js +16 -16
  7. package/dist/auth/handler.d.ts +13 -1
  8. package/dist/auth/handler.js +173 -6
  9. package/dist/auth/handler.js.map +1 -1
  10. package/dist/auth/inbox.d.ts +31 -0
  11. package/dist/auth/inbox.js +112 -0
  12. package/dist/auth/inbox.js.map +1 -0
  13. package/dist/auth/oauth.d.ts +59 -0
  14. package/dist/auth/oauth.js +209 -0
  15. package/dist/auth/oauth.js.map +1 -0
  16. package/dist/auth/qr.d.ts +8 -0
  17. package/dist/auth/qr.js +376 -0
  18. package/dist/auth/qr.js.map +1 -0
  19. package/dist/auth/totp.d.ts +19 -0
  20. package/dist/auth/totp.js +101 -0
  21. package/dist/auth/totp.js.map +1 -0
  22. package/dist/cli.js +168 -10
  23. package/dist/cli.js.map +1 -1
  24. package/dist/cron/service.d.ts +29 -0
  25. package/dist/cron/service.js +134 -0
  26. package/dist/cron/service.js.map +1 -0
  27. package/dist/db/bootstrap.d.ts +8 -1
  28. package/dist/db/bootstrap.js +240 -1
  29. package/dist/db/bootstrap.js.map +1 -1
  30. package/dist/db/database.d.ts +24 -0
  31. package/dist/db/database.js +61 -2
  32. package/dist/db/database.js.map +1 -1
  33. package/dist/db/emulated.d.ts +12 -0
  34. package/dist/db/emulated.js +156 -0
  35. package/dist/db/emulated.js.map +1 -0
  36. package/dist/db/engine.d.ts +2 -0
  37. package/dist/db/engine.js.map +1 -1
  38. package/dist/db/inspect.d.ts +13 -0
  39. package/dist/db/inspect.js +22 -0
  40. package/dist/db/inspect.js.map +1 -0
  41. package/dist/db/pgmem-engine.d.ts +22 -0
  42. package/dist/db/pgmem-engine.js +135 -0
  43. package/dist/db/pgmem-engine.js.map +1 -0
  44. package/dist/db/schema-diff.d.ts +23 -0
  45. package/dist/db/schema-diff.js +182 -0
  46. package/dist/db/schema-diff.js.map +1 -0
  47. package/dist/functions/deno-shim.d.ts +24 -0
  48. package/dist/functions/deno-shim.js +47 -0
  49. package/dist/functions/deno-shim.js.map +1 -0
  50. package/dist/functions/handler.d.ts +3 -1
  51. package/dist/functions/handler.js.map +1 -1
  52. package/dist/gen-types.d.ts +17 -0
  53. package/dist/gen-types.js +222 -0
  54. package/dist/gen-types.js.map +1 -0
  55. package/dist/index.d.ts +20 -0
  56. package/dist/index.js +83 -15
  57. package/dist/index.js.map +1 -1
  58. package/dist/jwt.d.ts +7 -0
  59. package/dist/jwt.js.map +1 -1
  60. package/dist/log-buffer.d.ts +21 -0
  61. package/dist/log-buffer.js +20 -0
  62. package/dist/log-buffer.js.map +1 -0
  63. package/dist/node/bundle-function.d.ts +7 -0
  64. package/dist/node/bundle-function.js +90 -0
  65. package/dist/node/bundle-function.js.map +1 -0
  66. package/dist/node/db-diff.d.ts +34 -0
  67. package/dist/node/db-diff.js +82 -0
  68. package/dist/node/db-diff.js.map +1 -0
  69. package/dist/node/index.d.ts +4 -1
  70. package/dist/node/index.js +4 -1
  71. package/dist/node/index.js.map +1 -1
  72. package/dist/node/load-functions.d.ts +6 -0
  73. package/dist/node/load-functions.js +60 -8
  74. package/dist/node/load-functions.js.map +1 -1
  75. package/dist/node/load-oauth.d.ts +4 -0
  76. package/dist/node/load-oauth.js +126 -0
  77. package/dist/node/load-oauth.js.map +1 -0
  78. package/dist/node/native/engine.d.ts +1 -1
  79. package/dist/node/native/engine.js +45 -14
  80. package/dist/node/native/engine.js.map +1 -1
  81. package/dist/realtime/engine.d.ts +24 -1
  82. package/dist/realtime/engine.js +154 -2
  83. package/dist/realtime/engine.js.map +1 -1
  84. package/dist/rest/build.d.ts +5 -1
  85. package/dist/rest/build.js +17 -8
  86. package/dist/rest/build.js.map +1 -1
  87. package/dist/rest/handler.js +22 -9
  88. package/dist/rest/handler.js.map +1 -1
  89. package/dist/types.d.ts +10 -0
  90. package/dist/types.js.map +1 -1
  91. package/dist/webhooks/service.d.ts +47 -0
  92. package/dist/webhooks/service.js +86 -0
  93. package/dist/webhooks/service.js.map +1 -0
  94. package/package.json +7 -2
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Pure-SQL emulations of Supabase's queue and cron extensions, so migrations
3
+ * and app code that call pgmq.* / cron.* work with no C extension on either
4
+ * engine. pgmq is fully self-contained SQL. cron records jobs here; the
5
+ * in-process CronService (src/cron/service.ts) executes them.
6
+ *
7
+ * These match the real extensions' function signatures closely enough that
8
+ * `pgmq.send(...)`, `pgmq.read(...)`, `select cron.schedule(...)` etc. behave
9
+ * the same from the client's and a migration's point of view.
10
+ */
11
+ // ── pgmq (message queue) ────────────────────────────────────────────────────
12
+ export const PGMQ_SQL = `
13
+ create schema if not exists pgmq;
14
+ grant usage on schema pgmq to anon, authenticated, service_role;
15
+
16
+ do $$ begin
17
+ if not exists (select 1 from pg_type t join pg_namespace n on n.oid = t.typnamespace
18
+ where t.typname = 'message_record' and n.nspname = 'pgmq') then
19
+ create type pgmq.message_record as (
20
+ msg_id bigint, read_ct integer, enqueued_at timestamptz, vt timestamptz, message jsonb
21
+ );
22
+ end if;
23
+ end $$;
24
+
25
+ create or replace function pgmq.create(queue_name text) returns void language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
26
+ begin
27
+ execute format('create table if not exists pgmq.%I (
28
+ msg_id bigint generated always as identity primary key,
29
+ read_ct integer not null default 0,
30
+ enqueued_at timestamptz not null default now(),
31
+ vt timestamptz not null default now(),
32
+ message jsonb)', 'q_' || queue_name);
33
+ execute format('create table if not exists pgmq.%I (
34
+ msg_id bigint primary key, read_ct integer not null default 0,
35
+ enqueued_at timestamptz not null, archived_at timestamptz not null default now(),
36
+ vt timestamptz, message jsonb)', 'a_' || queue_name);
37
+ end $pgmq$;
38
+
39
+ create or replace function pgmq.send(queue_name text, msg jsonb, delay integer default 0)
40
+ returns bigint language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
41
+ declare id bigint;
42
+ begin
43
+ perform pgmq.create(queue_name);
44
+ execute format('insert into pgmq.%I (vt, message) values (now() + make_interval(secs => $1), $2) returning msg_id', 'q_' || queue_name)
45
+ into id using delay, msg;
46
+ return id;
47
+ end $pgmq$;
48
+
49
+ create or replace function pgmq.read(queue_name text, vt integer, qty integer)
50
+ returns setof pgmq.message_record language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
51
+ begin
52
+ return query execute format($fmt$
53
+ with cte as (
54
+ select msg_id from pgmq.%I where vt <= now() order by msg_id limit $1 for update skip locked
55
+ )
56
+ update pgmq.%I m set vt = now() + make_interval(secs => $2), read_ct = read_ct + 1
57
+ from cte where m.msg_id = cte.msg_id
58
+ returning m.msg_id, m.read_ct, m.enqueued_at, m.vt, m.message
59
+ $fmt$, 'q_' || queue_name, 'q_' || queue_name) using qty, vt;
60
+ end $pgmq$;
61
+
62
+ create or replace function pgmq.pop(queue_name text)
63
+ returns setof pgmq.message_record language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
64
+ begin
65
+ return query execute format($fmt$
66
+ with cte as (select msg_id from pgmq.%I where vt <= now() order by msg_id limit 1 for update skip locked)
67
+ delete from pgmq.%I m using cte where m.msg_id = cte.msg_id
68
+ returning m.msg_id, m.read_ct, m.enqueued_at, m.vt, m.message
69
+ $fmt$, 'q_' || queue_name, 'q_' || queue_name);
70
+ end $pgmq$;
71
+
72
+ create or replace function pgmq.delete(queue_name text, msg_id bigint)
73
+ returns boolean language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
74
+ declare n integer;
75
+ begin
76
+ execute format('delete from pgmq.%I where msg_id = $1', 'q_' || queue_name) using msg_id;
77
+ get diagnostics n = row_count;
78
+ return n > 0;
79
+ end $pgmq$;
80
+
81
+ create or replace function pgmq.archive(queue_name text, msg_id bigint)
82
+ returns boolean language plpgsql security definer set search_path = pgmq, pg_catalog, public as $pgmq$
83
+ declare n integer;
84
+ begin
85
+ execute format($fmt$
86
+ with del as (delete from pgmq.%I where msg_id = $1 returning *)
87
+ insert into pgmq.%I (msg_id, read_ct, enqueued_at, vt, message)
88
+ select msg_id, read_ct, enqueued_at, vt, message from del
89
+ $fmt$, 'q_' || queue_name, 'a_' || queue_name) using msg_id;
90
+ get diagnostics n = row_count;
91
+ return n > 0;
92
+ end $pgmq$;
93
+
94
+ grant execute on all functions in schema pgmq to anon, authenticated, service_role;
95
+ `;
96
+ // ── cron (scheduled jobs) ────────────────────────────────────────────────────
97
+ export const CRON_SQL = `
98
+ create schema if not exists cron;
99
+ grant usage on schema cron to service_role, authenticated;
100
+
101
+ create table if not exists cron.job (
102
+ jobid bigint generated always as identity primary key,
103
+ schedule text not null,
104
+ command text not null,
105
+ jobname text unique,
106
+ active boolean not null default true,
107
+ created_at timestamptz not null default now()
108
+ );
109
+
110
+ create table if not exists cron.job_run_details (
111
+ runid bigint generated always as identity primary key,
112
+ jobid bigint,
113
+ command text,
114
+ status text,
115
+ return_message text,
116
+ start_time timestamptz,
117
+ end_time timestamptz
118
+ );
119
+
120
+ create or replace function cron.schedule(job_name text, schedule text, command text)
121
+ returns bigint language plpgsql security definer set search_path = cron, pg_catalog, public as $cron$
122
+ declare id bigint;
123
+ begin
124
+ insert into cron.job (jobname, schedule, command) values (job_name, schedule, command)
125
+ on conflict (jobname) do update set schedule = excluded.schedule, command = excluded.command, active = true
126
+ returning jobid into id;
127
+ return id;
128
+ end $cron$;
129
+
130
+ create or replace function cron.schedule(schedule text, command text)
131
+ returns bigint language plpgsql security definer set search_path = cron, pg_catalog, public as $cron$
132
+ begin
133
+ return cron.schedule('job_' || floor(extract(epoch from clock_timestamp()) * 1000)::bigint::text, schedule, command);
134
+ end $cron$;
135
+
136
+ create or replace function cron.unschedule(job_name text)
137
+ returns boolean language plpgsql security definer set search_path = cron, pg_catalog, public as $cron$
138
+ declare n integer;
139
+ begin
140
+ delete from cron.job where jobname = job_name;
141
+ get diagnostics n = row_count;
142
+ return n > 0;
143
+ end $cron$;
144
+
145
+ create or replace function cron.unschedule(job_id bigint)
146
+ returns boolean language plpgsql security definer set search_path = cron, pg_catalog, public as $cron$
147
+ declare n integer;
148
+ begin
149
+ delete from cron.job where jobid = job_id;
150
+ get diagnostics n = row_count;
151
+ return n > 0;
152
+ end $cron$;
153
+
154
+ grant execute on function cron.schedule(text,text,text), cron.schedule(text,text), cron.unschedule(text), cron.unschedule(bigint) to service_role, authenticated;
155
+ `;
156
+ //# sourceMappingURL=emulated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emulated.js","sourceRoot":"","sources":["../../src/db/emulated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmFvB,CAAA;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DvB,CAAA"}
@@ -13,6 +13,8 @@ export interface EngineTx {
13
13
  exec(sql: string): Promise<void>;
14
14
  }
15
15
  export interface DbEngine {
16
+ /** true for subset engines (pg-mem) that can't run the full plpgsql/RLS bootstrap */
17
+ minimalBootstrap?: boolean;
16
18
  query<T = any>(sql: string, params?: unknown[]): Promise<EngineResults<T>>;
17
19
  /** Run multiple SQL statements (no params). */
18
20
  exec(sql: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/db/engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,yEAAyE;AACzE,MAAM,OAAO,KAAK;IACR,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IAE/C,KAAK,CAAC,IAAI;QACR,IAAI,OAAoB,CAAA;QACxB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QACtC,MAAM,IAAI,CAAA;QACV,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,EAAoB;QAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QACjC,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAA;QACnB,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/db/engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyBH,yEAAyE;AACzE,MAAM,OAAO,KAAK;IACR,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IAE/C,KAAK,CAAC,IAAI;QACR,IAAI,OAAoB,CAAA;QACxB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QACtC,MAAM,IAAI,CAAA;QACV,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,EAAoB;QAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QACjC,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAA;QACnB,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `tinbase inspect` core: a lightweight database report — per-table row counts
3
+ * and on-disk size for a schema. Like a tiny `supabase inspect db`, enough to
4
+ * eyeball what's in a local project. (Uses pg_total_relation_size, so it runs
5
+ * on the real-Postgres engines, not the pg-mem subset.)
6
+ */
7
+ import { type Database } from './database.js';
8
+ export interface TableInfo {
9
+ table: string;
10
+ rows: number;
11
+ size: string;
12
+ }
13
+ export declare function inspectDb(db: Database, schema?: string): Promise<TableInfo[]>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `tinbase inspect` core: a lightweight database report — per-table row counts
3
+ * and on-disk size for a schema. Like a tiny `supabase inspect db`, enough to
4
+ * eyeball what's in a local project. (Uses pg_total_relation_size, so it runs
5
+ * on the real-Postgres engines, not the pg-mem subset.)
6
+ */
7
+ import { quoteIdent } from './database.js';
8
+ export async function inspectDb(db, schema = 'public') {
9
+ const tables = await db.query(`select c.relname as table,
10
+ pg_size_pretty(pg_total_relation_size(c.oid)) as size
11
+ from pg_class c
12
+ join pg_namespace n on n.oid = c.relnamespace
13
+ where n.nspname = $1 and c.relkind = 'r'
14
+ order by pg_total_relation_size(c.oid) desc, c.relname`, [schema]);
15
+ const out = [];
16
+ for (const t of tables.rows) {
17
+ const c = await db.query(`select count(*)::int as n from ${quoteIdent(schema)}.${quoteIdent(t.table)}`);
18
+ out.push({ table: t.table, rows: c.rows[0]?.n ?? 0, size: t.size });
19
+ }
20
+ return out;
21
+ }
22
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/db/inspect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAiB,MAAM,eAAe,CAAA;AAQzD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAY,EAAE,MAAM,GAAG,QAAQ;IAC7D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAC3B;;;;;4DAKwD,EACxD,CAAC,MAAM,CAAC,CACT,CAAA;IACD,MAAM,GAAG,GAAgB,EAAE,CAAA;IAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CACtB,kCAAkC,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAC9E,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * pg-mem engine — an ultralight, pure-JS, in-memory Postgres *subset* for
3
+ * local dev / previews (RapidNative) where footprint matters more than full
4
+ * fidelity. A ~3.6 MB install with no WASM, vs PGlite's ~600 MB heap.
5
+ *
6
+ * What works: the REST CRUD surface (select/insert/update/delete, filters,
7
+ * embeds, count), email/password auth, edge functions, realtime
8
+ * (broadcast/presence + postgres_changes), and database webhooks. Because
9
+ * pg-mem has no triggers/LISTEN/NOTIFY, change events for realtime and webhooks
10
+ * are synthesized in JS by the REST layer (see Database.emitCdc) — every write
11
+ * goes through it in-process.
12
+ *
13
+ * What's explicitly NOT here (it is a subset, not a faithful Postgres):
14
+ * - NO row-level security (policies are skipped; RLS is not enforced) — so
15
+ * realtime/webhook events are delivered UNFILTERED, not per-subscriber
16
+ * - NO PL/pgSQL functions, pgmq, or cron
17
+ * - reduced introspection; UPDATE change events carry no old_record
18
+ *
19
+ * Use it for throwaway local data and previews, never production.
20
+ */
21
+ import type { DbEngine } from './engine.js';
22
+ export declare function createPgmemEngine(): Promise<DbEngine>;
@@ -0,0 +1,135 @@
1
+ import { Mutex } from './engine.js';
2
+ /** Split SQL into statements, respecting $tag$…$tag$ dollar-quoted blocks. */
3
+ function splitStatements(sql) {
4
+ const out = [];
5
+ let cur = '';
6
+ let i = 0;
7
+ let dollarTag = null;
8
+ while (i < sql.length) {
9
+ const ch = sql[i];
10
+ if (dollarTag) {
11
+ if (sql.startsWith(dollarTag, i)) {
12
+ cur += dollarTag;
13
+ i += dollarTag.length;
14
+ dollarTag = null;
15
+ continue;
16
+ }
17
+ cur += ch;
18
+ i++;
19
+ continue;
20
+ }
21
+ const m = ch === '$' ? sql.slice(i).match(/^\$[a-zA-Z_]*\$/) : null;
22
+ if (m) {
23
+ dollarTag = m[0];
24
+ cur += dollarTag;
25
+ i += dollarTag.length;
26
+ continue;
27
+ }
28
+ if (ch === ';') {
29
+ if (cur.trim())
30
+ out.push(cur.trim());
31
+ cur = '';
32
+ i++;
33
+ continue;
34
+ }
35
+ cur += ch;
36
+ i++;
37
+ }
38
+ if (cur.trim())
39
+ out.push(cur.trim());
40
+ return out;
41
+ }
42
+ /** Statements a real Supabase migration may contain that pg-mem can't run. */
43
+ function isSkippable(stmt) {
44
+ const s = stmt.toLowerCase().replace(/\s+/g, ' ').trim();
45
+ return (/^create( or replace)? policy/.test(s) ||
46
+ /^drop policy/.test(s) ||
47
+ /row level security/.test(s) ||
48
+ /^create extension/.test(s) ||
49
+ /^create( or replace)? trigger/.test(s) ||
50
+ /^create( or replace)? function/.test(s) && /language\s+plpgsql/.test(s) ||
51
+ /^do \$/.test(s) ||
52
+ /^grant /.test(s) ||
53
+ /^revoke /.test(s) ||
54
+ /^comment on/.test(s) ||
55
+ /^create publication/.test(s) ||
56
+ /^alter publication/.test(s));
57
+ }
58
+ export async function createPgmemEngine() {
59
+ let newDb, DataType;
60
+ try {
61
+ ;
62
+ ({ newDb, DataType } = await import('pg-mem'));
63
+ }
64
+ catch {
65
+ throw new Error('the pg-mem engine requires the optional `pg-mem` dependency — run `npm install pg-mem`');
66
+ }
67
+ const db = newDb({ autoCreateForeignKeyIndices: true });
68
+ // functions our REST/bootstrap SQL needs that pg-mem lacks
69
+ // impure: true so pg-mem evaluates them per row (not once per statement) —
70
+ // otherwise every row in a multi-row insert gets the same UUID → PK collision
71
+ db.public.registerFunction({ name: 'gen_random_uuid', returns: DataType.uuid, impure: true, implementation: () => crypto.randomUUID() });
72
+ db.public.registerFunction({ name: 'uuid_generate_v4', returns: DataType.uuid, impure: true, implementation: () => crypto.randomUUID() });
73
+ db.public.registerFunction({
74
+ name: 'row_to_json',
75
+ args: [DataType.record],
76
+ returns: DataType.jsonb,
77
+ implementation: ((r) => r),
78
+ });
79
+ // set_config/current_setting exist in pg-mem; RLS context is a harmless no-op here
80
+ const { Client } = db.adapters.createPg();
81
+ const client = new Client();
82
+ await client.connect();
83
+ const mutex = new Mutex();
84
+ const run = async (sql, params) => {
85
+ const res = await client.query(params && params.length ? { text: sql, values: params } : sql);
86
+ return { rows: (res.rows ?? []), affectedRows: res.rowCount ?? undefined };
87
+ };
88
+ /**
89
+ * Tolerant exec: run statements one at a time and skip the ones a real
90
+ * Supabase migration contains that pg-mem can't do — RLS policies, plpgsql
91
+ * functions/triggers, extensions, grants. Genuine errors on supported DDL
92
+ * still throw. Skipped statements are logged so nothing silently vanishes.
93
+ */
94
+ const exec = async (sql) => {
95
+ for (const stmt of splitStatements(sql)) {
96
+ try {
97
+ await client.query(stmt);
98
+ }
99
+ catch (e) {
100
+ if (isSkippable(stmt)) {
101
+ console.warn(` [pgmem] skipped unsupported statement: ${stmt.replace(/\s+/g, ' ').slice(0, 70)}…`);
102
+ continue;
103
+ }
104
+ throw e;
105
+ }
106
+ }
107
+ };
108
+ const tx = {
109
+ query: (sql, params) => run(sql, params),
110
+ exec,
111
+ };
112
+ return {
113
+ minimalBootstrap: true,
114
+ query: (sql, params) => mutex.run(() => run(sql, params)),
115
+ exec: (sql) => mutex.run(() => exec(sql)),
116
+ transaction: (fn) => mutex.run(async () => {
117
+ // pg-mem is single-connection in-memory; serialize and use a snapshot so
118
+ // a thrown fn rolls back
119
+ const restore = db.backup();
120
+ try {
121
+ return await fn(tx);
122
+ }
123
+ catch (e) {
124
+ restore.restore();
125
+ throw e;
126
+ }
127
+ }),
128
+ // no LISTEN/NOTIFY in pg-mem — realtime/webhooks simply don't fire
129
+ listen: async () => () => { },
130
+ close: async () => {
131
+ await client.end();
132
+ },
133
+ };
134
+ }
135
+ //# sourceMappingURL=pgmem-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgmem-engine.js","sourceRoot":"","sources":["../../src/db/pgmem-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Database } from './database.js';
2
+ interface ColumnSnap {
3
+ name: string;
4
+ type: string;
5
+ nullable: boolean;
6
+ default: string | null;
7
+ }
8
+ interface TableSnap {
9
+ name: string;
10
+ columns: Map<string, ColumnSnap>;
11
+ order: string[];
12
+ }
13
+ export interface SchemaSnapshot {
14
+ tables: Map<string, TableSnap>;
15
+ /** constraint/index name → definition, keyed by table */
16
+ constraints: Map<string, Map<string, string>>;
17
+ indexes: Map<string, Map<string, string>>;
18
+ enums: Map<string, string[]>;
19
+ }
20
+ export declare function snapshotSchema(db: Database, schema?: string): Promise<SchemaSnapshot>;
21
+ /** DDL to turn `from` into `to`, scoped to one schema. Empty array = no changes. */
22
+ export declare function diffSchemas(from: SchemaSnapshot, to: SchemaSnapshot, schema?: string): string[];
23
+ export {};
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Schema snapshot + diff — the engine behind `tinbase db diff`.
3
+ *
4
+ * Snapshots a schema (tables, columns, constraints, indexes, enums) into a
5
+ * structured form, then emits the DDL to turn one snapshot into another. Used
6
+ * to capture changes made outside migrations (e.g. in the Studio SQL editor)
7
+ * into a new migration, the way `supabase db diff` (migra) does.
8
+ *
9
+ * Covered: enums (create + add value), tables (create/drop), columns
10
+ * (add/drop/alter type/nullability/default), and named constraints + indexes
11
+ * (add/drop by definition). Not yet diffed: functions, triggers, policies,
12
+ * views — noted so the output never silently claims completeness.
13
+ */
14
+ import { quoteIdent } from './database.js';
15
+ export async function snapshotSchema(db, schema = 'public') {
16
+ const cols = await db.query(`select c.relname as table, a.attname as column,
17
+ format_type(a.atttypid, a.atttypmod) as type,
18
+ not a.attnotnull as nullable,
19
+ pg_get_expr(d.adbin, d.adrelid) as default
20
+ from pg_attribute a
21
+ join pg_class c on c.oid = a.attrelid
22
+ join pg_namespace n on n.oid = c.relnamespace
23
+ left join pg_attrdef d on d.adrelid = c.oid and d.adnum = a.attnum
24
+ where n.nspname = $1 and c.relkind = 'r' and a.attnum > 0 and not a.attisdropped
25
+ order by c.relname, a.attnum`, [schema]);
26
+ const tables = new Map();
27
+ for (const c of cols.rows) {
28
+ let t = tables.get(c.table);
29
+ if (!t) {
30
+ t = { name: c.table, columns: new Map(), order: [] };
31
+ tables.set(c.table, t);
32
+ }
33
+ t.columns.set(c.column, { name: c.column, type: c.type, nullable: c.nullable, default: c.default });
34
+ t.order.push(c.column);
35
+ }
36
+ const cons = await db.query(`select c.relname as table, con.conname as name, pg_get_constraintdef(con.oid) as def, con.conindid::int as conindid
37
+ from pg_constraint con
38
+ join pg_class c on c.oid = con.conrelid
39
+ join pg_namespace n on n.oid = c.relnamespace
40
+ where n.nspname = $1 and con.contype in ('p','u','f','c')`, [schema]);
41
+ const constraints = new Map();
42
+ const constraintIndexOids = new Set();
43
+ for (const c of cons.rows) {
44
+ if (!constraints.has(c.table))
45
+ constraints.set(c.table, new Map());
46
+ constraints.get(c.table).set(c.name, c.def);
47
+ if (c.conindid)
48
+ constraintIndexOids.add(c.conindid);
49
+ }
50
+ // indexes not backing a constraint (those are emitted via the constraint)
51
+ const idx = await db.query(`select c.relname as table, ic.relname as name, pg_get_indexdef(i.indexrelid) as def, i.indexrelid::int as indexrelid
52
+ from pg_index i
53
+ join pg_class ic on ic.oid = i.indexrelid
54
+ join pg_class c on c.oid = i.indrelid
55
+ join pg_namespace n on n.oid = c.relnamespace
56
+ where n.nspname = $1`, [schema]);
57
+ const indexes = new Map();
58
+ for (const r of idx.rows) {
59
+ if (constraintIndexOids.has(r.indexrelid))
60
+ continue;
61
+ if (!indexes.has(r.table))
62
+ indexes.set(r.table, new Map());
63
+ indexes.get(r.table).set(r.name, r.def);
64
+ }
65
+ const en = await db.query(`select t.typname as name, array_agg(e.enumlabel order by e.enumsortorder) as labels
66
+ from pg_type t join pg_enum e on e.enumtypid = t.oid
67
+ join pg_namespace n on n.oid = t.typnamespace
68
+ where n.nspname = $1 group by t.typname`, [schema]);
69
+ const enums = new Map();
70
+ for (const r of en.rows)
71
+ enums.set(r.name, r.labels);
72
+ return { tables, constraints, indexes, enums };
73
+ }
74
+ /** DDL to turn `from` into `to`, scoped to one schema. Empty array = no changes. */
75
+ export function diffSchemas(from, to, schema = 'public') {
76
+ const out = [];
77
+ const q = (n) => quoteIdent(n);
78
+ const tbl = (t) => `${q(schema)}.${q(t)}`;
79
+ // ── enums ──
80
+ for (const [name, labels] of to.enums) {
81
+ if (!from.enums.has(name)) {
82
+ out.push(`create type ${q(schema)}.${q(name)} as enum (${labels.map((l) => `'${l.replace(/'/g, "''")}'`).join(', ')});`);
83
+ }
84
+ else {
85
+ const before = from.enums.get(name);
86
+ for (const label of labels) {
87
+ if (!before.includes(label))
88
+ out.push(`alter type ${q(schema)}.${q(name)} add value '${label.replace(/'/g, "''")}';`);
89
+ }
90
+ }
91
+ }
92
+ // ── new tables ──
93
+ for (const [name, t] of to.tables) {
94
+ if (from.tables.has(name))
95
+ continue;
96
+ const colDefs = t.order.map((cn) => columnClause(t.columns.get(cn), q));
97
+ out.push(`create table ${tbl(name)} (\n${colDefs.map((c) => ` ${c}`).join(',\n')}\n);`);
98
+ }
99
+ // ── column-level diffs on shared tables ──
100
+ for (const [name, toT] of to.tables) {
101
+ const fromT = from.tables.get(name);
102
+ if (!fromT)
103
+ continue;
104
+ for (const cn of toT.order) {
105
+ const toC = toT.columns.get(cn);
106
+ const fromC = fromT.columns.get(cn);
107
+ if (!fromC) {
108
+ out.push(`alter table ${tbl(name)} add column ${columnClause(toC, q)};`);
109
+ continue;
110
+ }
111
+ if (fromC.type !== toC.type)
112
+ out.push(`alter table ${tbl(name)} alter column ${q(cn)} type ${toC.type};`);
113
+ if (fromC.nullable !== toC.nullable)
114
+ out.push(`alter table ${tbl(name)} alter column ${q(cn)} ${toC.nullable ? 'drop not null' : 'set not null'};`);
115
+ if ((fromC.default ?? null) !== (toC.default ?? null)) {
116
+ out.push(toC.default === null
117
+ ? `alter table ${tbl(name)} alter column ${q(cn)} drop default;`
118
+ : `alter table ${tbl(name)} alter column ${q(cn)} set default ${toC.default};`);
119
+ }
120
+ }
121
+ for (const cn of fromT.order) {
122
+ if (!toT.columns.has(cn))
123
+ out.push(`alter table ${tbl(name)} drop column ${q(cn)};`);
124
+ }
125
+ }
126
+ // ── dropped tables ──
127
+ for (const name of from.tables.keys()) {
128
+ if (!to.tables.has(name))
129
+ out.push(`drop table ${tbl(name)};`);
130
+ }
131
+ // ── constraints (drop changed/removed, then add new) ──
132
+ diffNamed(from.constraints, to.constraints, {
133
+ drop: (table, cname) => out.push(`alter table ${tbl(table)} drop constraint ${q(cname)};`),
134
+ add: (table, cname, def) => out.push(`alter table ${tbl(table)} add constraint ${q(cname)} ${def};`),
135
+ });
136
+ // ── indexes (drop changed/removed, then add new) ──
137
+ diffNamed(from.indexes, to.indexes, {
138
+ drop: (_table, iname) => out.push(`drop index ${q(schema)}.${q(iname)};`),
139
+ add: (_table, _iname, def) => out.push(`${def};`),
140
+ });
141
+ return out;
142
+ }
143
+ /**
144
+ * Render a column definition. A `serial`-style column introspects as an integer
145
+ * with a `nextval('..._seq')` default and an owned sequence; re-emit it as
146
+ * serial/bigserial/smallserial so the sequence is recreated with the table
147
+ * (a bare `default nextval(...)` would reference a sequence that doesn't exist yet).
148
+ */
149
+ function columnClause(c, q) {
150
+ const isSerialDefault = c.default !== null && /^nextval\(/i.test(c.default);
151
+ if (isSerialDefault) {
152
+ const serial = c.type === 'bigint' ? 'bigserial' : c.type === 'smallint' ? 'smallserial' : 'serial';
153
+ return `${q(c.name)} ${serial}` + (c.nullable ? '' : ' not null');
154
+ }
155
+ let s = `${q(c.name)} ${c.type}`;
156
+ if (!c.nullable)
157
+ s += ' not null';
158
+ if (c.default !== null)
159
+ s += ` default ${c.default}`;
160
+ return s;
161
+ }
162
+ function diffNamed(from, to, ops) {
163
+ // drops (and changed → drop first)
164
+ for (const [table, defs] of from) {
165
+ const toDefs = to.get(table) ?? new Map();
166
+ for (const [name, def] of defs) {
167
+ const toDef = toDefs.get(name);
168
+ if (toDef === undefined || toDef !== def)
169
+ ops.drop(table, name, def);
170
+ }
171
+ }
172
+ // adds (and changed → re-add)
173
+ for (const [table, defs] of to) {
174
+ const fromDefs = from.get(table) ?? new Map();
175
+ for (const [name, def] of defs) {
176
+ const fromDef = fromDefs.get(name);
177
+ if (fromDef === undefined || fromDef !== def)
178
+ ops.add(table, name, def);
179
+ }
180
+ }
181
+ }
182
+ //# sourceMappingURL=schema-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-diff.js","sourceRoot":"","sources":["../../src/db/schema-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Minimal `Deno` global shim so Supabase-style edge functions run unchanged
3
+ * under Node/Bun. Supabase functions are written for Deno:
4
+ *
5
+ * Deno.serve((req) => new Response(...))
6
+ * const url = Deno.env.get('SUPABASE_URL')
7
+ *
8
+ * Instead of starting a server, our `Deno.serve` captures the handler so the
9
+ * FunctionsHandler can invoke it per request; `Deno.env` reads the injected
10
+ * SUPABASE_* vars, function secrets, and process.env.
11
+ *
12
+ * Not resolved: `npm:` / `jsr:` / URL import specifiers and the Deno std lib —
13
+ * a function using those needs a bundling step. Functions that stick to Web
14
+ * APIs (fetch/Request/Response) + Deno.serve/Deno.env work as-is.
15
+ */
16
+ type DenoHandler = (req: Request) => Response | Promise<Response>;
17
+ /** Merge variables the shim's Deno.env should expose (SUPABASE_* keys, secrets). */
18
+ export declare function setDenoEnv(env: Record<string, string>): void;
19
+ /** Install globalThis.Deno if we're not already running under a Deno-like runtime. */
20
+ export declare function installDenoShim(): void;
21
+ /** Return and clear the handler captured by the most recent Deno.serve() call. */
22
+ export declare function takeCapturedHandler(): DenoHandler | undefined;
23
+ export declare function resetCapturedHandler(): void;
24
+ export {};