@flightdev/db 0.0.2

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.
@@ -0,0 +1,38 @@
1
+ import { DatabaseConfig, Driver as DatabaseDriver } from './index.js';
2
+
3
+ /**
4
+ * @flightdev/db/postgres - PostgreSQL Driver
5
+ *
6
+ * Uses 'pg' (node-postgres) for maximum compatibility.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { postgres } from '@flightdev/db/postgres';
11
+ * import { createDb } from '@flightdev/db';
12
+ *
13
+ * const db = createDb(postgres({
14
+ * connectionString: process.env.DATABASE_URL,
15
+ * // OR individual options:
16
+ * host: 'localhost',
17
+ * port: 5432,
18
+ * database: 'mydb',
19
+ * user: 'user',
20
+ * password: 'pass',
21
+ * }));
22
+ * ```
23
+ */
24
+
25
+ interface PostgresConfig extends DatabaseConfig {
26
+ host?: string;
27
+ port?: number;
28
+ database?: string;
29
+ user?: string;
30
+ password?: string;
31
+ ssl?: boolean | object;
32
+ }
33
+ /**
34
+ * Create a PostgreSQL driver
35
+ */
36
+ declare function postgres(config: PostgresConfig): DatabaseDriver;
37
+
38
+ export { type PostgresConfig, postgres as default, postgres };
@@ -0,0 +1,99 @@
1
+ // src/postgres.ts
2
+ function postgres(config) {
3
+ let pool = null;
4
+ async function getPool() {
5
+ if (!pool) {
6
+ const { Pool } = await import("pg");
7
+ pool = new Pool({
8
+ connectionString: config.connectionString,
9
+ host: config.host,
10
+ port: config.port,
11
+ database: config.database,
12
+ user: config.user,
13
+ password: config.password,
14
+ ssl: config.ssl,
15
+ max: config.poolSize ?? 10,
16
+ connectionTimeoutMillis: config.timeout ?? 3e4
17
+ });
18
+ }
19
+ return pool;
20
+ }
21
+ return {
22
+ name: "postgres",
23
+ async query(sql, params) {
24
+ const p = await getPool();
25
+ const result = await p.query(sql, params);
26
+ return {
27
+ rows: result.rows,
28
+ rowCount: result.rowCount ?? 0,
29
+ raw: result
30
+ };
31
+ },
32
+ async execute(sql, params) {
33
+ const p = await getPool();
34
+ const result = await p.query(sql, params);
35
+ return {
36
+ rowsAffected: result.rowCount ?? 0,
37
+ raw: result
38
+ };
39
+ },
40
+ async transaction(fn) {
41
+ const p = await getPool();
42
+ const client = await p.connect();
43
+ try {
44
+ await client.query("BEGIN");
45
+ const tx = {
46
+ async query(sql, params) {
47
+ const result2 = await client.query(sql, params);
48
+ return {
49
+ rows: result2.rows,
50
+ rowCount: result2.rowCount ?? 0,
51
+ raw: result2
52
+ };
53
+ },
54
+ async execute(sql, params) {
55
+ const result2 = await client.query(sql, params);
56
+ return {
57
+ rowsAffected: result2.rowCount ?? 0,
58
+ raw: result2
59
+ };
60
+ },
61
+ async commit() {
62
+ await client.query("COMMIT");
63
+ },
64
+ async rollback() {
65
+ await client.query("ROLLBACK");
66
+ }
67
+ };
68
+ const result = await fn(tx);
69
+ await client.query("COMMIT");
70
+ return result;
71
+ } catch (error) {
72
+ await client.query("ROLLBACK");
73
+ throw error;
74
+ } finally {
75
+ client.release();
76
+ }
77
+ },
78
+ async close() {
79
+ if (pool) {
80
+ await pool.end();
81
+ pool = null;
82
+ }
83
+ },
84
+ async ping() {
85
+ try {
86
+ const p = await getPool();
87
+ await p.query("SELECT 1");
88
+ return true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ };
94
+ }
95
+ var postgres_default = postgres;
96
+ export {
97
+ postgres_default as default,
98
+ postgres
99
+ };
@@ -0,0 +1,42 @@
1
+ import { Driver as DatabaseDriver } from './index.js';
2
+
3
+ /**
4
+ * @flightdev/db/supabase - Supabase Database Driver
5
+ *
6
+ * Uses @supabase/supabase-js for Supabase PostgreSQL.
7
+ * Includes RLS (Row Level Security) support out of the box.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { supabase } from '@flightdev/db/supabase';
12
+ * import { createDb } from '@flightdev/db';
13
+ *
14
+ * const db = createDb(supabase({
15
+ * url: process.env.SUPABASE_URL,
16
+ * key: process.env.SUPABASE_ANON_KEY, // or SERVICE_ROLE_KEY for admin
17
+ * }));
18
+ *
19
+ * // Use Supabase's query builder
20
+ * const { data, error } = await db.from('users').select('*');
21
+ * ```
22
+ */
23
+
24
+ interface SupabaseConfig {
25
+ /** Supabase project URL */
26
+ url: string;
27
+ /** Supabase API key (anon or service_role) */
28
+ key: string;
29
+ /** Optional schema (default: public) */
30
+ schema?: string;
31
+ }
32
+ /**
33
+ * Create a Supabase driver
34
+ */
35
+ declare function supabase(config: SupabaseConfig): DatabaseDriver & {
36
+ /** Access Supabase client directly for advanced features */
37
+ readonly client: any;
38
+ /** Query builder (Supabase style) */
39
+ from: (table: string) => any;
40
+ };
41
+
42
+ export { type SupabaseConfig, supabase as default, supabase };
@@ -0,0 +1,76 @@
1
+ // src/supabase.ts
2
+ function supabase(config) {
3
+ let client = null;
4
+ async function getClient() {
5
+ if (!client) {
6
+ const { createClient } = await import("@supabase/supabase-js");
7
+ client = createClient(config.url, config.key, {
8
+ db: { schema: config.schema ?? "public" }
9
+ });
10
+ }
11
+ return client;
12
+ }
13
+ const driver = {
14
+ name: "supabase",
15
+ get client() {
16
+ return client;
17
+ },
18
+ async from(table) {
19
+ const c = await getClient();
20
+ return c.from(table);
21
+ },
22
+ async query(sql, params) {
23
+ const c = await getClient();
24
+ const { data, error } = await c.rpc("flight_raw_query", {
25
+ query_text: sql,
26
+ query_params: params ?? []
27
+ });
28
+ if (error) {
29
+ throw new Error(`Supabase query error: ${error.message}`);
30
+ }
31
+ return {
32
+ rows: data ?? [],
33
+ rowCount: data?.length ?? 0,
34
+ raw: { data, error }
35
+ };
36
+ },
37
+ async execute(sql, params) {
38
+ const c = await getClient();
39
+ const { data, error } = await c.rpc("flight_raw_execute", {
40
+ query_text: sql,
41
+ query_params: params ?? []
42
+ });
43
+ if (error) {
44
+ throw new Error(`Supabase execute error: ${error.message}`);
45
+ }
46
+ return {
47
+ rowsAffected: data?.affected_rows ?? 0,
48
+ insertId: data?.insert_id,
49
+ raw: { data, error }
50
+ };
51
+ },
52
+ async transaction(_fn) {
53
+ throw new Error(
54
+ "Supabase does not support client-side transactions. Use RPC functions with SECURITY DEFINER for transactional operations."
55
+ );
56
+ },
57
+ async close() {
58
+ client = null;
59
+ },
60
+ async ping() {
61
+ try {
62
+ const c = await getClient();
63
+ const { error } = await c.from("_flight_ping").select("1").limit(1);
64
+ return !error || error.code === "PGRST116";
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+ };
70
+ return driver;
71
+ }
72
+ var supabase_default = supabase;
73
+ export {
74
+ supabase_default as default,
75
+ supabase
76
+ };
@@ -0,0 +1,39 @@
1
+ import { Driver as DatabaseDriver } from './index.js';
2
+
3
+ /**
4
+ * @flightdev/db/turso - Turso/SQLite Driver
5
+ *
6
+ * Uses @libsql/client for Turso cloud and local SQLite.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { turso } from '@flightdev/db/turso';
11
+ * import { createDb } from '@flightdev/db';
12
+ *
13
+ * // Turso Cloud
14
+ * const db = createDb(turso({
15
+ * url: 'libsql://your-db.turso.io',
16
+ * authToken: process.env.TURSO_AUTH_TOKEN,
17
+ * }));
18
+ *
19
+ * // Local SQLite
20
+ * const localDb = createDb(turso({
21
+ * url: 'file:local.db',
22
+ * }));
23
+ * ```
24
+ */
25
+
26
+ interface TursoConfig {
27
+ /** Database URL (libsql://... or file:...) */
28
+ url: string;
29
+ /** Auth token for Turso cloud */
30
+ authToken?: string;
31
+ /** Sync URL for embedded replicas */
32
+ syncUrl?: string;
33
+ }
34
+ /**
35
+ * Create a Turso/SQLite driver
36
+ */
37
+ declare function turso(config: TursoConfig): DatabaseDriver;
38
+
39
+ export { type TursoConfig, turso as default, turso };
package/dist/turso.js ADDED
@@ -0,0 +1,102 @@
1
+ // src/turso.ts
2
+ function turso(config) {
3
+ let client = null;
4
+ async function getClient() {
5
+ if (!client) {
6
+ const { createClient } = await import("@libsql/client");
7
+ client = createClient({
8
+ url: config.url,
9
+ authToken: config.authToken,
10
+ syncUrl: config.syncUrl
11
+ });
12
+ }
13
+ return client;
14
+ }
15
+ return {
16
+ name: "turso",
17
+ async query(sql, params) {
18
+ const c = await getClient();
19
+ const result = await c.execute({ sql, args: params ?? [] });
20
+ const rows = result.rows.map((row) => {
21
+ const obj = {};
22
+ for (const [key, value] of Object.entries(row)) {
23
+ obj[key] = value;
24
+ }
25
+ return obj;
26
+ });
27
+ return {
28
+ rows,
29
+ rowCount: result.rows.length,
30
+ raw: result
31
+ };
32
+ },
33
+ async execute(sql, params) {
34
+ const c = await getClient();
35
+ const result = await c.execute({ sql, args: params ?? [] });
36
+ return {
37
+ rowsAffected: result.rowsAffected,
38
+ insertId: result.lastInsertRowid ? Number(result.lastInsertRowid) : void 0,
39
+ raw: result
40
+ };
41
+ },
42
+ async transaction(fn) {
43
+ const c = await getClient();
44
+ const libsqlTx = await c.transaction("write");
45
+ try {
46
+ const tx = {
47
+ async query(sql, params) {
48
+ const result2 = await libsqlTx.execute({ sql, args: params ?? [] });
49
+ const rows = result2.rows.map((row) => {
50
+ const obj = {};
51
+ for (const [key, value] of Object.entries(row)) {
52
+ obj[key] = value;
53
+ }
54
+ return obj;
55
+ });
56
+ return { rows, rowCount: result2.rows.length, raw: result2 };
57
+ },
58
+ async execute(sql, params) {
59
+ const result2 = await libsqlTx.execute({ sql, args: params ?? [] });
60
+ return {
61
+ rowsAffected: result2.rowsAffected,
62
+ insertId: result2.lastInsertRowid ? Number(result2.lastInsertRowid) : void 0,
63
+ raw: result2
64
+ };
65
+ },
66
+ async commit() {
67
+ await libsqlTx.commit();
68
+ },
69
+ async rollback() {
70
+ await libsqlTx.rollback();
71
+ }
72
+ };
73
+ const result = await fn(tx);
74
+ await libsqlTx.commit();
75
+ return result;
76
+ } catch (error) {
77
+ await libsqlTx.rollback();
78
+ throw error;
79
+ }
80
+ },
81
+ async close() {
82
+ if (client) {
83
+ client.close();
84
+ client = null;
85
+ }
86
+ },
87
+ async ping() {
88
+ try {
89
+ const c = await getClient();
90
+ await c.execute("SELECT 1");
91
+ return true;
92
+ } catch {
93
+ return false;
94
+ }
95
+ }
96
+ };
97
+ }
98
+ var turso_default = turso;
99
+ export {
100
+ turso_default as default,
101
+ turso
102
+ };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@flightdev/db",
3
+ "version": "0.0.2",
4
+ "description": "Flight Database Abstraction Layer - Agnostic database adapters",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./postgres": {
15
+ "types": "./dist/postgres.d.ts",
16
+ "import": "./dist/postgres.js"
17
+ },
18
+ "./supabase": {
19
+ "types": "./dist/supabase.d.ts",
20
+ "import": "./dist/supabase.js"
21
+ },
22
+ "./turso": {
23
+ "types": "./dist/turso.d.ts",
24
+ "import": "./dist/turso.js"
25
+ },
26
+ "./neon": {
27
+ "types": "./dist/neon.d.ts",
28
+ "import": "./dist/neon.js"
29
+ },
30
+ "./d1": {
31
+ "types": "./dist/d1.d.ts",
32
+ "import": "./dist/d1.js"
33
+ }
34
+ },
35
+ "keywords": [
36
+ "flight",
37
+ "database",
38
+ "postgres",
39
+ "supabase",
40
+ "turso",
41
+ "neon",
42
+ "d1",
43
+ "agnostic"
44
+ ],
45
+ "author": "Flight Contributors",
46
+ "license": "MIT",
47
+ "devDependencies": {
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.7.0"
50
+ },
51
+ "peerDependencies": {
52
+ "@libsql/client": ">=0.5.0",
53
+ "@neondatabase/serverless": ">=0.9.0",
54
+ "@supabase/supabase-js": ">=2.0.0",
55
+ "pg": ">=8.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "@libsql/client": {
59
+ "optional": true
60
+ },
61
+ "@neondatabase/serverless": {
62
+ "optional": true
63
+ },
64
+ "@supabase/supabase-js": {
65
+ "optional": true
66
+ },
67
+ "pg": {
68
+ "optional": true
69
+ }
70
+ },
71
+ "scripts": {
72
+ "build": "tsup",
73
+ "dev": "tsup --watch",
74
+ "typecheck": "tsc --noEmit"
75
+ }
76
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Type declarations for peer dependencies
3
+ * Following 2025 best practices: specific types instead of any
4
+ */
5
+
6
+ // ============================================================================
7
+ // PostgreSQL (pg)
8
+ // ============================================================================
9
+
10
+ declare module 'pg' {
11
+ export interface PoolConfig {
12
+ connectionString?: string;
13
+ host?: string;
14
+ port?: number;
15
+ database?: string;
16
+ user?: string;
17
+ password?: string;
18
+ ssl?: boolean | object;
19
+ max?: number;
20
+ connectionTimeoutMillis?: number;
21
+ }
22
+
23
+ export interface QueryResult<T = unknown> {
24
+ rows: T[];
25
+ rowCount: number | null;
26
+ command?: string;
27
+ oid?: number;
28
+ fields?: unknown[];
29
+ }
30
+
31
+ export interface PoolClient {
32
+ query<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
33
+ release(): void;
34
+ }
35
+
36
+ export class Pool {
37
+ constructor(config?: PoolConfig);
38
+ query<T = unknown>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
39
+ connect(): Promise<PoolClient>;
40
+ end(): Promise<void>;
41
+ }
42
+
43
+ export default { Pool };
44
+ }
45
+
46
+ // ============================================================================
47
+ // Supabase
48
+ // ============================================================================
49
+
50
+ declare module '@supabase/supabase-js' {
51
+ export interface SupabaseClientOptions {
52
+ db?: { schema?: string };
53
+ }
54
+
55
+ export interface PostgrestResponse<T> {
56
+ data: T | null;
57
+ error: { message: string; code?: string } | null;
58
+ }
59
+
60
+ export interface SupabaseClient {
61
+ from(table: string): {
62
+ select(columns?: string): { limit(n: number): Promise<PostgrestResponse<unknown[]>> };
63
+ };
64
+ rpc(fn: string, params?: unknown): Promise<PostgrestResponse<unknown>>;
65
+ auth: {
66
+ getUser(token: string): Promise<{
67
+ data: { user: SupabaseUser | null };
68
+ error: { message: string } | null;
69
+ }>;
70
+ exchangeCodeForSession(code: string): Promise<{
71
+ data: { session: { access_token: string; expires_in: number } };
72
+ error: { message: string } | null;
73
+ }>;
74
+ };
75
+ }
76
+
77
+ export interface SupabaseUser {
78
+ id: string;
79
+ email?: string;
80
+ user_metadata?: Record<string, unknown>;
81
+ app_metadata?: Record<string, unknown>;
82
+ email_confirmed_at?: string;
83
+ }
84
+
85
+ export function createClient(
86
+ url: string,
87
+ key: string,
88
+ options?: SupabaseClientOptions
89
+ ): SupabaseClient;
90
+ }
91
+
92
+ // ============================================================================
93
+ // libSQL / Turso
94
+ // ============================================================================
95
+
96
+ declare module '@libsql/client' {
97
+ export interface LibsqlConfig {
98
+ url: string;
99
+ authToken?: string;
100
+ syncUrl?: string;
101
+ }
102
+
103
+ export interface LibsqlResult {
104
+ rows: Array<Record<string, unknown>>;
105
+ rowsAffected: number;
106
+ lastInsertRowid?: bigint;
107
+ }
108
+
109
+ export interface LibsqlTransaction {
110
+ execute(query: { sql: string; args: unknown[] }): Promise<LibsqlResult>;
111
+ commit(): Promise<void>;
112
+ rollback(): Promise<void>;
113
+ }
114
+
115
+ export interface LibsqlClient {
116
+ execute(query: { sql: string; args: unknown[] } | string): Promise<LibsqlResult>;
117
+ transaction(mode: 'write' | 'read'): Promise<LibsqlTransaction>;
118
+ close(): void;
119
+ }
120
+
121
+ export function createClient(config: LibsqlConfig): LibsqlClient;
122
+ }
123
+
124
+ // ============================================================================
125
+ // Neon Serverless
126
+ // ============================================================================
127
+
128
+ declare module '@neondatabase/serverless' {
129
+ export interface NeonQueryResult<T = unknown> {
130
+ rows: T[];
131
+ rowCount: number | null;
132
+ }
133
+
134
+ export interface NeonPoolConfig {
135
+ connectionString: string;
136
+ }
137
+
138
+ export interface NeonPoolClient {
139
+ query<T = unknown>(sql: string, params?: unknown[]): Promise<NeonQueryResult<T>>;
140
+ release(): void;
141
+ }
142
+
143
+ export class Pool {
144
+ constructor(config: NeonPoolConfig);
145
+ query<T = unknown>(sql: string, params?: unknown[]): Promise<NeonQueryResult<T>>;
146
+ connect(): Promise<NeonPoolClient>;
147
+ end(): Promise<void>;
148
+ }
149
+
150
+ export function neon(connectionString: string): <T = unknown>(
151
+ sql: string,
152
+ params?: unknown[]
153
+ ) => Promise<T[]>;
154
+ }