tinbase 0.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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -0
  3. package/assets/logo.svg +18 -0
  4. package/dist/auth/handler.d.ts +43 -0
  5. package/dist/auth/handler.js +291 -0
  6. package/dist/auth/handler.js.map +1 -0
  7. package/dist/auth/password.d.ts +3 -0
  8. package/dist/auth/password.js +40 -0
  9. package/dist/auth/password.js.map +1 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +181 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/db/bootstrap.d.ts +6 -0
  14. package/dist/db/bootstrap.js +213 -0
  15. package/dist/db/bootstrap.js.map +1 -0
  16. package/dist/db/database.d.ts +83 -0
  17. package/dist/db/database.js +270 -0
  18. package/dist/db/database.js.map +1 -0
  19. package/dist/db/engine.d.ts +30 -0
  20. package/dist/db/engine.js +28 -0
  21. package/dist/db/engine.js.map +1 -0
  22. package/dist/db/pglite-engine.d.ts +3 -0
  23. package/dist/db/pglite-engine.js +39 -0
  24. package/dist/db/pglite-engine.js.map +1 -0
  25. package/dist/index.d.ts +23 -0
  26. package/dist/index.js +145 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/jwt.d.ts +20 -0
  29. package/dist/jwt.js +72 -0
  30. package/dist/jwt.js.map +1 -0
  31. package/dist/node/bun-server.d.ts +8 -0
  32. package/dist/node/bun-server.js +41 -0
  33. package/dist/node/bun-server.js.map +1 -0
  34. package/dist/node/fs-driver.d.ts +11 -0
  35. package/dist/node/fs-driver.js +39 -0
  36. package/dist/node/fs-driver.js.map +1 -0
  37. package/dist/node/index.d.ts +7 -0
  38. package/dist/node/index.js +8 -0
  39. package/dist/node/index.js.map +1 -0
  40. package/dist/node/native/engine.d.ts +13 -0
  41. package/dist/node/native/engine.js +186 -0
  42. package/dist/node/native/engine.js.map +1 -0
  43. package/dist/node/native/wire.d.ts +38 -0
  44. package/dist/node/native/wire.js +345 -0
  45. package/dist/node/native/wire.js.map +1 -0
  46. package/dist/node/project.d.ts +6 -0
  47. package/dist/node/project.js +29 -0
  48. package/dist/node/project.js.map +1 -0
  49. package/dist/node/server-shared.d.ts +6 -0
  50. package/dist/node/server-shared.js +2 -0
  51. package/dist/node/server-shared.js.map +1 -0
  52. package/dist/node/server.d.ts +14 -0
  53. package/dist/node/server.js +83 -0
  54. package/dist/node/server.js.map +1 -0
  55. package/dist/node/ws.d.ts +8 -0
  56. package/dist/node/ws.js +165 -0
  57. package/dist/node/ws.js.map +1 -0
  58. package/dist/realtime/engine.d.ts +53 -0
  59. package/dist/realtime/engine.js +437 -0
  60. package/dist/realtime/engine.js.map +1 -0
  61. package/dist/rest/build.d.ts +53 -0
  62. package/dist/rest/build.js +505 -0
  63. package/dist/rest/build.js.map +1 -0
  64. package/dist/rest/errors.d.ts +2 -0
  65. package/dist/rest/errors.js +48 -0
  66. package/dist/rest/errors.js.map +1 -0
  67. package/dist/rest/handler.d.ts +11 -0
  68. package/dist/rest/handler.js +332 -0
  69. package/dist/rest/handler.js.map +1 -0
  70. package/dist/rest/parse.d.ts +69 -0
  71. package/dist/rest/parse.js +261 -0
  72. package/dist/rest/parse.js.map +1 -0
  73. package/dist/storage/driver.d.ts +9 -0
  74. package/dist/storage/driver.js +18 -0
  75. package/dist/storage/driver.js.map +1 -0
  76. package/dist/storage/handler.d.ts +49 -0
  77. package/dist/storage/handler.js +534 -0
  78. package/dist/storage/handler.js.map +1 -0
  79. package/dist/types.d.ts +51 -0
  80. package/dist/types.js +11 -0
  81. package/dist/types.js.map +1 -0
  82. package/package.json +59 -0
package/dist/cli.js ADDED
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * tinbase CLI — a Docker-free Supabase-compatible backend.
4
+ *
5
+ * tinbase start start the server (applies pending migrations first)
6
+ * tinbase migrate apply pending migrations and exit
7
+ * tinbase status show applied migrations
8
+ * tinbase keys print anon/service_role keys for the JWT secret
9
+ */
10
+ import { mkdir } from 'node:fs/promises';
11
+ import { join, resolve } from 'node:path';
12
+ import { createBackend } from './index.js';
13
+ import { createNativeEngine } from './node/native/engine.js';
14
+ import { FsStorageDriver } from './node/fs-driver.js';
15
+ import { loadSupabaseProject } from './node/project.js';
16
+ import { serve } from './node/server.js';
17
+ import { serveBun } from './node/bun-server.js';
18
+ const IS_BUN = typeof globalThis.Bun !== 'undefined';
19
+ // single-file builds ship without the WASM engine; native is the default there
20
+ const IS_BINARY = process.env.TINBASE_SINGLE_BINARY === '1';
21
+ import { signJwt } from './jwt.js';
22
+ import { DEFAULT_JWT_SECRET } from './types.js';
23
+ function parseArgs(argv) {
24
+ const args = [...argv];
25
+ const command = args[0] && !args[0].startsWith('-') ? args.shift() : 'start';
26
+ const opts = {
27
+ command,
28
+ port: 54321,
29
+ host: '127.0.0.1',
30
+ dir: process.cwd(),
31
+ dataDir: undefined,
32
+ storageDir: '',
33
+ jwtSecret: process.env.TINBASE_JWT_SECRET ?? DEFAULT_JWT_SECRET,
34
+ memory: false,
35
+ engine: process.env.TINBASE_ENGINE ?? (IS_BINARY ? 'native' : 'wasm'),
36
+ };
37
+ for (let i = 0; i < args.length; i++) {
38
+ const a = args[i];
39
+ const next = () => args[++i];
40
+ if (a === '--port' || a === '-p')
41
+ opts.port = parseInt(next(), 10);
42
+ else if (a === '--host')
43
+ opts.host = next();
44
+ else if (a === '--dir')
45
+ opts.dir = resolve(next());
46
+ else if (a === '--data-dir')
47
+ opts.dataDir = resolve(next());
48
+ else if (a === '--storage-dir')
49
+ opts.storageDir = resolve(next());
50
+ else if (a === '--jwt-secret')
51
+ opts.jwtSecret = next();
52
+ else if (a === '--memory')
53
+ opts.memory = true;
54
+ else if (a === '--engine') {
55
+ const v = next();
56
+ if (v !== 'wasm' && v !== 'native') {
57
+ console.error(`--engine must be wasm or native, got: ${v}`);
58
+ process.exit(1);
59
+ }
60
+ opts.engine = v;
61
+ }
62
+ else if (a === '--help' || a === '-h') {
63
+ printHelp();
64
+ process.exit(0);
65
+ }
66
+ else {
67
+ console.error(`unknown option: ${a}`);
68
+ process.exit(1);
69
+ }
70
+ }
71
+ if (!opts.dataDir && !opts.memory)
72
+ opts.dataDir = join(opts.dir, '.tinbase', 'db');
73
+ if (!opts.storageDir)
74
+ opts.storageDir = join(opts.dir, '.tinbase', 'storage');
75
+ return opts;
76
+ }
77
+ function printHelp() {
78
+ console.log(`tinbase — Supabase-compatible backend on PGlite (no Docker)
79
+
80
+ Usage: tinbase [command] [options]
81
+
82
+ Commands:
83
+ start start the server (default)
84
+ migrate apply pending supabase/migrations/*.sql and exit
85
+ status list applied migrations
86
+ keys print anon and service_role keys
87
+
88
+ Options:
89
+ -p, --port <n> port to listen on (default 54321)
90
+ --host <host> host to bind (default 127.0.0.1)
91
+ --dir <path> project directory containing supabase/ (default cwd)
92
+ --data-dir <path> PGlite data directory (default <dir>/.tinbase/db)
93
+ --storage-dir <p> storage files directory (default <dir>/.tinbase/storage)
94
+ --jwt-secret <s> JWT secret (or TINBASE_JWT_SECRET env var)
95
+ --memory in-memory database (no persistence, wasm engine only)
96
+ --engine <e> wasm (PGlite, default) or native (embedded Postgres,
97
+ ~4x lighter memory; downloads binaries on first run)
98
+ `);
99
+ }
100
+ async function main() {
101
+ const opts = parseArgs(process.argv.slice(2));
102
+ if (opts.command === 'keys') {
103
+ const now = Math.floor(Date.now() / 1000);
104
+ const exp = now + 10 * 365 * 24 * 3600;
105
+ console.log('anon key:');
106
+ console.log(await signJwt({ iss: 'supabase', ref: 'tinbase', role: 'anon', iat: now, exp }, opts.jwtSecret));
107
+ console.log('\nservice_role key:');
108
+ console.log(await signJwt({ iss: 'supabase', ref: 'tinbase', role: 'service_role', iat: now, exp }, opts.jwtSecret));
109
+ return;
110
+ }
111
+ const project = await loadSupabaseProject(opts.dir);
112
+ if (opts.dataDir)
113
+ await mkdir(opts.dataDir, { recursive: true });
114
+ await mkdir(opts.storageDir, { recursive: true });
115
+ const engine = opts.engine === 'native'
116
+ ? await createNativeEngine({
117
+ dataDir: join(opts.dir, '.tinbase', 'pgdata'),
118
+ log: (msg) => console.log(` ${msg}`),
119
+ })
120
+ : undefined;
121
+ const backend = await createBackend({
122
+ engine,
123
+ dataDir: opts.memory ? undefined : opts.dataDir,
124
+ jwtSecret: opts.jwtSecret,
125
+ siteUrl: `http://${opts.host}:${opts.port}`,
126
+ migrations: project.migrations,
127
+ seedSql: project.seedSql,
128
+ storageDriver: new FsStorageDriver(opts.storageDir),
129
+ log: (msg) => console.log(` ${msg}`),
130
+ });
131
+ if (opts.command === 'migrate') {
132
+ const applied = await backend.db.listAppliedMigrations();
133
+ console.log(`${applied.length} migration(s) applied.`);
134
+ await backend.close();
135
+ return;
136
+ }
137
+ if (opts.command === 'status') {
138
+ const applied = await backend.db.listAppliedMigrations();
139
+ if (applied.length === 0)
140
+ console.log('no migrations applied');
141
+ for (const m of applied)
142
+ console.log(`${m.version} ${m.name ?? ''}`);
143
+ await backend.close();
144
+ return;
145
+ }
146
+ if (opts.command !== 'start') {
147
+ console.error(`unknown command: ${opts.command}`);
148
+ printHelp();
149
+ process.exit(1);
150
+ }
151
+ const server = IS_BUN
152
+ ? await serveBun(backend, { port: opts.port, host: opts.host })
153
+ : await serve(backend, { port: opts.port, host: opts.host });
154
+ console.log(`
155
+ tinbase running
156
+
157
+ API URL: ${server.url}
158
+ Engine: ${opts.engine === 'native' ? 'native postgres' : `PGlite (${opts.memory ? 'in-memory' : opts.dataDir})`}
159
+ Storage: ${opts.storageDir}
160
+ Migrations: ${project.migrations.length} file(s)
161
+
162
+ anon key: ${backend.anonKey}
163
+ service_role key: ${backend.serviceRoleKey}
164
+
165
+ Use with supabase-js:
166
+ const supabase = createClient('${server.url}', '<anon key>')
167
+ `);
168
+ const shutdown = async () => {
169
+ console.log('\nshutting down…');
170
+ await server.close().catch(() => { });
171
+ await backend.close().catch(() => { });
172
+ process.exit(0);
173
+ };
174
+ process.on('SIGINT', shutdown);
175
+ process.on('SIGTERM', shutdown);
176
+ }
177
+ main().catch((e) => {
178
+ console.error(e);
179
+ process.exit(1);
180
+ });
181
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Idempotent bootstrap SQL that shapes a fresh PGlite database like a
3
+ * Supabase project: roles, auth schema, storage schema, helper functions,
4
+ * migration bookkeeping, and the realtime CDC plumbing.
5
+ */
6
+ export declare const BOOTSTRAP_SQL = "\n-- \u2500\u2500 Roles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndo $$\nbegin\n if not exists (select from pg_roles where rolname = 'anon') then\n create role anon nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'authenticated') then\n create role authenticated nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'service_role') then\n create role service_role nologin noinherit bypassrls;\n end if;\nend $$;\n\ngrant usage on schema public to anon, authenticated, service_role;\ngrant all on all tables in schema public to anon, authenticated, service_role;\ngrant all on all sequences in schema public to anon, authenticated, service_role;\ngrant execute on all functions in schema public to anon, authenticated, service_role;\n\nalter default privileges in schema public\n grant all on tables to anon, authenticated, service_role;\nalter default privileges in schema public\n grant all on sequences to anon, authenticated, service_role;\nalter default privileges in schema public\n grant execute on functions to anon, authenticated, service_role;\n\n-- \u2500\u2500 Auth schema (GoTrue-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists auth;\n\ncreate table if not exists auth.users (\n id uuid primary key default gen_random_uuid(),\n aud text default 'authenticated',\n role text default 'authenticated',\n email text unique,\n encrypted_password text,\n email_confirmed_at timestamptz,\n invited_at timestamptz,\n confirmation_token text,\n recovery_token text,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb default '{}'::jsonb,\n raw_user_meta_data jsonb default '{}'::jsonb,\n is_super_admin boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n phone text unique,\n phone_confirmed_at timestamptz,\n banned_until timestamptz,\n deleted_at timestamptz,\n is_anonymous boolean default false\n);\n\ncreate table if not exists auth.refresh_tokens (\n id bigint generated by default as identity primary key,\n token text unique not null,\n user_id uuid not null references auth.users(id) on delete cascade,\n parent text,\n session_id uuid,\n revoked boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate index if not exists refresh_tokens_user_id_idx on auth.refresh_tokens(user_id);\n\ngrant usage on schema auth to anon, authenticated, service_role;\n\ncreate or replace function auth.jwt() returns jsonb\nlanguage sql stable as $$\n select coalesce(\n nullif(current_setting('request.jwt.claims', true), ''),\n '{}'\n )::jsonb\n$$;\n\ncreate or replace function auth.uid() returns uuid\nlanguage sql stable as $$\n select nullif(auth.jwt() ->> 'sub', '')::uuid\n$$;\n\ncreate or replace function auth.role() returns text\nlanguage sql stable as $$\n select coalesce(auth.jwt() ->> 'role', 'anon')\n$$;\n\ncreate or replace function auth.email() returns text\nlanguage sql stable as $$\n select auth.jwt() ->> 'email'\n$$;\n\ngrant execute on function auth.jwt(), auth.uid(), auth.role(), auth.email()\n to anon, authenticated, service_role;\n\n-- \u2500\u2500 Storage schema (storage-api-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists storage;\n\ncreate table if not exists storage.buckets (\n id text primary key,\n name text not null unique,\n owner uuid,\n public boolean default false,\n file_size_limit bigint,\n allowed_mime_types text[],\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists storage.objects (\n id uuid primary key default gen_random_uuid(),\n bucket_id text not null references storage.buckets(id),\n name text not null,\n owner uuid,\n version text,\n metadata jsonb default '{}'::jsonb,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n last_accessed_at timestamptz default now(),\n unique (bucket_id, name)\n);\n\ncreate index if not exists objects_bucket_name_idx on storage.objects(bucket_id, name);\n\ngrant usage on schema storage to anon, authenticated, service_role;\ngrant select on storage.buckets to anon, authenticated, service_role;\ngrant all on storage.buckets to service_role;\ngrant all on storage.objects to anon, authenticated, service_role;\n\ncreate or replace function storage.foldername(name text) returns text[]\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[1 : array_length(string_to_array(name, '/'), 1) - 1]\n$$;\n\ncreate or replace function storage.filename(name text) returns text\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[array_length(string_to_array(name, '/'), 1)]\n$$;\n\ncreate or replace function storage.extension(name text) returns text\nlanguage sql immutable as $$\n select reverse(split_part(reverse(storage.filename(name)), '.', 1))\n$$;\n\nalter table storage.objects enable row level security;\n\n-- Dev-friendly default policies. Replace them in your migrations to lock down.\ndo $$\nbegin\n if not exists (select from pg_policies where schemaname = 'storage' and tablename = 'objects' and policyname = 'tinbase_authenticated_all') then\n create policy tinbase_authenticated_all on storage.objects\n for all to authenticated using (true) with check (true);\n end if;\n if not exists (select from pg_policies where schemaname = 'storage' and tablename = 'objects' and policyname = 'tinbase_public_read') then\n create policy tinbase_public_read on storage.objects\n for select to anon\n using (bucket_id in (select id from storage.buckets where public));\n end if;\nend $$;\n\n-- \u2500\u2500 Migration bookkeeping (same table the Supabase CLI uses) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists supabase_migrations;\n\ncreate table if not exists supabase_migrations.schema_migrations (\n version text primary key,\n name text,\n statements text[],\n applied_at timestamptz default now()\n);\n\ncreate table if not exists supabase_migrations.seed_files (\n path text primary key,\n hash text,\n applied_at timestamptz default now()\n);\n\n-- \u2500\u2500 Realtime CDC plumbing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists tinbase;\n\ncreate or replace function tinbase.cdc_notify() returns trigger\nlanguage plpgsql security definer as $$\ndeclare\n payload text;\nbegin\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', case when TG_OP in ('INSERT', 'UPDATE') then row_to_json(NEW) else null end,\n 'old_record', case when TG_OP in ('UPDATE', 'DELETE') then row_to_json(OLD) else null end\n )::text;\n -- pg_notify payloads are capped at ~8kB; degrade like Supabase does.\n if octet_length(payload) > 7500 then\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', null,\n 'old_record', null,\n 'errors', json_build_array('Payload too large')\n )::text;\n end if;\n perform pg_notify('tinbase_cdc', payload);\n return coalesce(NEW, OLD);\nend $$;\n";
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Idempotent bootstrap SQL that shapes a fresh PGlite database like a
3
+ * Supabase project: roles, auth schema, storage schema, helper functions,
4
+ * migration bookkeeping, and the realtime CDC plumbing.
5
+ */
6
+ export const BOOTSTRAP_SQL = `
7
+ -- ── Roles ────────────────────────────────────────────────────────────────
8
+ do $$
9
+ begin
10
+ if not exists (select from pg_roles where rolname = 'anon') then
11
+ create role anon nologin noinherit;
12
+ end if;
13
+ if not exists (select from pg_roles where rolname = 'authenticated') then
14
+ create role authenticated nologin noinherit;
15
+ end if;
16
+ if not exists (select from pg_roles where rolname = 'service_role') then
17
+ create role service_role nologin noinherit bypassrls;
18
+ end if;
19
+ end $$;
20
+
21
+ grant usage on schema public to anon, authenticated, service_role;
22
+ grant all on all tables in schema public to anon, authenticated, service_role;
23
+ grant all on all sequences in schema public to anon, authenticated, service_role;
24
+ grant execute on all functions in schema public to anon, authenticated, service_role;
25
+
26
+ alter default privileges in schema public
27
+ grant all on tables to anon, authenticated, service_role;
28
+ alter default privileges in schema public
29
+ grant all on sequences to anon, authenticated, service_role;
30
+ alter default privileges in schema public
31
+ grant execute on functions to anon, authenticated, service_role;
32
+
33
+ -- ── Auth schema (GoTrue-compatible subset) ───────────────────────────────
34
+ create schema if not exists auth;
35
+
36
+ create table if not exists auth.users (
37
+ id uuid primary key default gen_random_uuid(),
38
+ aud text default 'authenticated',
39
+ role text default 'authenticated',
40
+ email text unique,
41
+ encrypted_password text,
42
+ email_confirmed_at timestamptz,
43
+ invited_at timestamptz,
44
+ confirmation_token text,
45
+ recovery_token text,
46
+ last_sign_in_at timestamptz,
47
+ raw_app_meta_data jsonb default '{}'::jsonb,
48
+ raw_user_meta_data jsonb default '{}'::jsonb,
49
+ is_super_admin boolean default false,
50
+ created_at timestamptz default now(),
51
+ updated_at timestamptz default now(),
52
+ phone text unique,
53
+ phone_confirmed_at timestamptz,
54
+ banned_until timestamptz,
55
+ deleted_at timestamptz,
56
+ is_anonymous boolean default false
57
+ );
58
+
59
+ create table if not exists auth.refresh_tokens (
60
+ id bigint generated by default as identity primary key,
61
+ token text unique not null,
62
+ user_id uuid not null references auth.users(id) on delete cascade,
63
+ parent text,
64
+ session_id uuid,
65
+ revoked boolean default false,
66
+ created_at timestamptz default now(),
67
+ updated_at timestamptz default now()
68
+ );
69
+
70
+ create index if not exists refresh_tokens_user_id_idx on auth.refresh_tokens(user_id);
71
+
72
+ grant usage on schema auth to anon, authenticated, service_role;
73
+
74
+ create or replace function auth.jwt() returns jsonb
75
+ language sql stable as $$
76
+ select coalesce(
77
+ nullif(current_setting('request.jwt.claims', true), ''),
78
+ '{}'
79
+ )::jsonb
80
+ $$;
81
+
82
+ create or replace function auth.uid() returns uuid
83
+ language sql stable as $$
84
+ select nullif(auth.jwt() ->> 'sub', '')::uuid
85
+ $$;
86
+
87
+ create or replace function auth.role() returns text
88
+ language sql stable as $$
89
+ select coalesce(auth.jwt() ->> 'role', 'anon')
90
+ $$;
91
+
92
+ create or replace function auth.email() returns text
93
+ language sql stable as $$
94
+ select auth.jwt() ->> 'email'
95
+ $$;
96
+
97
+ grant execute on function auth.jwt(), auth.uid(), auth.role(), auth.email()
98
+ to anon, authenticated, service_role;
99
+
100
+ -- ── Storage schema (storage-api-compatible subset) ───────────────────────
101
+ create schema if not exists storage;
102
+
103
+ create table if not exists storage.buckets (
104
+ id text primary key,
105
+ name text not null unique,
106
+ owner uuid,
107
+ public boolean default false,
108
+ file_size_limit bigint,
109
+ allowed_mime_types text[],
110
+ created_at timestamptz default now(),
111
+ updated_at timestamptz default now()
112
+ );
113
+
114
+ create table if not exists storage.objects (
115
+ id uuid primary key default gen_random_uuid(),
116
+ bucket_id text not null references storage.buckets(id),
117
+ name text not null,
118
+ owner uuid,
119
+ version text,
120
+ metadata jsonb default '{}'::jsonb,
121
+ created_at timestamptz default now(),
122
+ updated_at timestamptz default now(),
123
+ last_accessed_at timestamptz default now(),
124
+ unique (bucket_id, name)
125
+ );
126
+
127
+ create index if not exists objects_bucket_name_idx on storage.objects(bucket_id, name);
128
+
129
+ grant usage on schema storage to anon, authenticated, service_role;
130
+ grant select on storage.buckets to anon, authenticated, service_role;
131
+ grant all on storage.buckets to service_role;
132
+ grant all on storage.objects to anon, authenticated, service_role;
133
+
134
+ create or replace function storage.foldername(name text) returns text[]
135
+ language sql immutable as $$
136
+ select (string_to_array(name, '/'))[1 : array_length(string_to_array(name, '/'), 1) - 1]
137
+ $$;
138
+
139
+ create or replace function storage.filename(name text) returns text
140
+ language sql immutable as $$
141
+ select (string_to_array(name, '/'))[array_length(string_to_array(name, '/'), 1)]
142
+ $$;
143
+
144
+ create or replace function storage.extension(name text) returns text
145
+ language sql immutable as $$
146
+ select reverse(split_part(reverse(storage.filename(name)), '.', 1))
147
+ $$;
148
+
149
+ alter table storage.objects enable row level security;
150
+
151
+ -- Dev-friendly default policies. Replace them in your migrations to lock down.
152
+ do $$
153
+ begin
154
+ if not exists (select from pg_policies where schemaname = 'storage' and tablename = 'objects' and policyname = 'tinbase_authenticated_all') then
155
+ create policy tinbase_authenticated_all on storage.objects
156
+ for all to authenticated using (true) with check (true);
157
+ end if;
158
+ if not exists (select from pg_policies where schemaname = 'storage' and tablename = 'objects' and policyname = 'tinbase_public_read') then
159
+ create policy tinbase_public_read on storage.objects
160
+ for select to anon
161
+ using (bucket_id in (select id from storage.buckets where public));
162
+ end if;
163
+ end $$;
164
+
165
+ -- ── Migration bookkeeping (same table the Supabase CLI uses) ─────────────
166
+ create schema if not exists supabase_migrations;
167
+
168
+ create table if not exists supabase_migrations.schema_migrations (
169
+ version text primary key,
170
+ name text,
171
+ statements text[],
172
+ applied_at timestamptz default now()
173
+ );
174
+
175
+ create table if not exists supabase_migrations.seed_files (
176
+ path text primary key,
177
+ hash text,
178
+ applied_at timestamptz default now()
179
+ );
180
+
181
+ -- ── Realtime CDC plumbing ─────────────────────────────────────────────────
182
+ create schema if not exists tinbase;
183
+
184
+ create or replace function tinbase.cdc_notify() returns trigger
185
+ language plpgsql security definer as $$
186
+ declare
187
+ payload text;
188
+ begin
189
+ payload := json_build_object(
190
+ 'schema', TG_TABLE_SCHEMA,
191
+ 'table', TG_TABLE_NAME,
192
+ 'type', TG_OP,
193
+ 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),
194
+ 'record', case when TG_OP in ('INSERT', 'UPDATE') then row_to_json(NEW) else null end,
195
+ 'old_record', case when TG_OP in ('UPDATE', 'DELETE') then row_to_json(OLD) else null end
196
+ )::text;
197
+ -- pg_notify payloads are capped at ~8kB; degrade like Supabase does.
198
+ if octet_length(payload) > 7500 then
199
+ payload := json_build_object(
200
+ 'schema', TG_TABLE_SCHEMA,
201
+ 'table', TG_TABLE_NAME,
202
+ 'type', TG_OP,
203
+ 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),
204
+ 'record', null,
205
+ 'old_record', null,
206
+ 'errors', json_build_array('Payload too large')
207
+ )::text;
208
+ end if;
209
+ perform pg_notify('tinbase_cdc', payload);
210
+ return coalesce(NEW, OLD);
211
+ end $$;
212
+ `;
213
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/db/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8M5B,CAAA"}
@@ -0,0 +1,83 @@
1
+ import type { DbEngine, EngineResults } from './engine.js';
2
+ import type { MigrationFile, RequestContext } from '../types.js';
3
+ export interface ColumnInfo {
4
+ name: string;
5
+ udtName: string;
6
+ isNullable: boolean;
7
+ hasDefault: boolean;
8
+ isPrimaryKey: boolean;
9
+ }
10
+ export interface ForeignKey {
11
+ constraintName: string;
12
+ srcSchema: string;
13
+ srcTable: string;
14
+ srcColumns: string[];
15
+ tgtSchema: string;
16
+ tgtTable: string;
17
+ tgtColumns: string[];
18
+ }
19
+ export interface TableInfo {
20
+ schema: string;
21
+ name: string;
22
+ columns: ColumnInfo[];
23
+ primaryKey: string[];
24
+ }
25
+ export interface FunctionArg {
26
+ name: string;
27
+ type: string;
28
+ }
29
+ export interface FunctionInfo {
30
+ schema: string;
31
+ name: string;
32
+ returnsSet: boolean;
33
+ returnType: string;
34
+ /** pg_type.typtype: b=base, c=composite, p=pseudo, d=domain, e=enum */
35
+ returnTypType: string;
36
+ args: FunctionArg[];
37
+ }
38
+ export interface SchemaInfo {
39
+ tables: Map<string, TableInfo>;
40
+ foreignKeys: ForeignKey[];
41
+ }
42
+ export type Querier = (sql: string, params?: unknown[]) => Promise<EngineResults>;
43
+ export interface CdcEvent {
44
+ schema: string;
45
+ table: string;
46
+ type: 'INSERT' | 'UPDATE' | 'DELETE';
47
+ commit_timestamp: string;
48
+ record: Record<string, unknown> | null;
49
+ old_record: Record<string, unknown> | null;
50
+ errors?: string[];
51
+ }
52
+ export declare class Database {
53
+ engine: DbEngine;
54
+ private schemaCache;
55
+ private fnCache;
56
+ private cdcListeners;
57
+ private cdcStarted;
58
+ private constructor();
59
+ /** Create a Database on PGlite (default) or any custom DbEngine. */
60
+ static create(dataDirOrEngine?: string | DbEngine): Promise<Database>;
61
+ /** Superuser query — used by auth/storage internals and introspection. */
62
+ query<T = any>(sql: string, params?: unknown[]): Promise<EngineResults<T>>;
63
+ exec(sql: string): Promise<unknown>;
64
+ /**
65
+ * Run `fn` inside a transaction with the request's Postgres role and JWT
66
+ * claims applied via SET LOCAL — this is what makes RLS behave exactly
67
+ * like hosted Supabase.
68
+ */
69
+ withContext<T>(ctx: RequestContext, fn: (q: Querier) => Promise<T>): Promise<T>;
70
+ runMigrations(migrations: MigrationFile[], seedSql?: string): Promise<string[]>;
71
+ listAppliedMigrations(): Promise<{
72
+ version: string;
73
+ name: string | null;
74
+ }[]>;
75
+ invalidateSchemaCache(): void;
76
+ getSchemaInfo(schema: string): Promise<SchemaInfo>;
77
+ getFunctions(schema: string, name: string): Promise<FunctionInfo[]>;
78
+ ensureCdcTrigger(schema: string, table: string): Promise<void>;
79
+ onCdcEvent(cb: (e: CdcEvent) => void): Promise<() => void>;
80
+ close(): Promise<void>;
81
+ }
82
+ export declare function quoteIdent(name: string): string;
83
+ export declare function quoteLiteral(value: string): string;