driftsql 1.0.0 → 1.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.
- package/README.md +4 -60
- package/dist/index.d.mts +10 -5
- package/dist/index.d.ts +10 -5
- package/dist/index.mjs +176 -3
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -23,7 +23,6 @@ A lightweight SQL client for TypeScript, supporting multiple databases like Post
|
|
|
23
23
|
- **PostgreSQL** - Native PostgreSQL driver via `pg`
|
|
24
24
|
- **LibSQL** - SQLite-compatible databases via `@libsql/client`
|
|
25
25
|
- **HTTP** - HTTP-based database services
|
|
26
|
-
- **Neon** - Neon serverless PostgreSQL (experimental)
|
|
27
26
|
|
|
28
27
|
## Usage
|
|
29
28
|
|
|
@@ -44,12 +43,6 @@ Import and use:
|
|
|
44
43
|
import { DriftSQLClient } from 'driftsql'
|
|
45
44
|
```
|
|
46
45
|
|
|
47
|
-
**CDN** (Deno, Bun and Browsers)
|
|
48
|
-
|
|
49
|
-
```js
|
|
50
|
-
import { DriftSQLClient } from 'https://esm.sh/driftsql'
|
|
51
|
-
```
|
|
52
|
-
|
|
53
46
|
<!-- /automd -->
|
|
54
47
|
|
|
55
48
|
## Quick Start
|
|
@@ -160,8 +153,6 @@ console.log(`Database OK: ${status.ok}, Ping: ${status.ping}ms`)
|
|
|
160
153
|
await db.close()
|
|
161
154
|
```
|
|
162
155
|
|
|
163
|
-
## API Reference
|
|
164
|
-
|
|
165
156
|
### Constructor Options
|
|
166
157
|
|
|
167
158
|
```typescript
|
|
@@ -182,62 +173,15 @@ interface ClientOptions {
|
|
|
182
173
|
}
|
|
183
174
|
```
|
|
184
175
|
|
|
185
|
-
### Methods
|
|
186
|
-
|
|
187
|
-
- `query<T>(sql: string, args?: (string | number | boolean | null)[])` - Execute raw SQL with parameters
|
|
188
|
-
- `findFirst<K>(table: K, where?: Partial<DT[K]>)` - Find first matching record
|
|
189
|
-
- `findMany<K>(table: K, where?: Partial<DT[K]>)` - Find all matching records
|
|
190
|
-
- `insert<K>(table: K, data: Partial<DT[K]>)` - Insert new record
|
|
191
|
-
- `update<K>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>)` - Update records
|
|
192
|
-
- `delete<K>(table: K, where: Partial<DT[K]>)` - Delete records
|
|
193
|
-
- `deleteFirst<K>(table: K, where: Partial<DT[K]>)` - Delete first matching record
|
|
194
|
-
- `status()` - Get server status and ping (HTTP driver only)
|
|
195
|
-
- `close()` - Close database connections
|
|
196
|
-
|
|
197
|
-
### Return Types
|
|
198
|
-
|
|
199
|
-
All query methods return a unified result format:
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
type UnifiedQueryResult<T> = {
|
|
203
|
-
rows: T[]
|
|
204
|
-
rowCount: number
|
|
205
|
-
command?: string
|
|
206
|
-
fields?: Array<{ name: string; dataTypeID: number }>
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## Development
|
|
211
|
-
|
|
212
|
-
<details>
|
|
213
|
-
|
|
214
|
-
<summary>local development</summary>
|
|
215
|
-
|
|
216
|
-
- Clone this repository
|
|
217
|
-
- Install latest LTS version of [Node.js](https://nodejs.org/en/)
|
|
218
|
-
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
|
|
219
|
-
- Install dependencies using `pnpm install`
|
|
220
|
-
- Run interactive tests using `pnpm dev`
|
|
221
|
-
|
|
222
176
|
</details>
|
|
223
177
|
|
|
224
178
|
## License
|
|
225
179
|
|
|
226
180
|
<!-- automd:contributors license=MIT -->
|
|
227
181
|
|
|
228
|
-
Published under the [MIT](https://github.com/lassejlv/
|
|
229
|
-
Made by [community](https://github.com/lassejlv/
|
|
182
|
+
Published under the [MIT](https://github.com/lassejlv/driftsql/blob/main/LICENSE) license.
|
|
183
|
+
Made by [community](https://github.com/lassejlv/driftsql/graphs/contributors) 💛
|
|
230
184
|
<br><br>
|
|
231
|
-
<a href="https://github.com/lassejlv/
|
|
232
|
-
<img src="https://contrib.rocks/image?repo=lassejlv/
|
|
185
|
+
<a href="https://github.com/lassejlv/driftsql/graphs/contributors">
|
|
186
|
+
<img src="https://contrib.rocks/image?repo=lassejlv/driftsql" />
|
|
233
187
|
</a>
|
|
234
|
-
|
|
235
|
-
<!-- /automd -->
|
|
236
|
-
|
|
237
|
-
<!-- automd:with-automd -->
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
_🤖 auto updated with [automd](https://automd.unjs.io)_
|
|
242
|
-
|
|
243
|
-
<!-- /automd -->
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { PoolConfig } from 'pg';
|
|
2
2
|
import { Config } from '@libsql/client';
|
|
3
|
+
import mysql from 'mysql2/promise';
|
|
4
|
+
|
|
5
|
+
type Drivers = ClientOptions['drivers'];
|
|
6
|
+
declare const inspectDB: (drivers: Drivers) => Promise<never>;
|
|
3
7
|
|
|
4
8
|
type UnifiedQueryResult<T extends Record<string, any>> = {
|
|
5
9
|
rows: T[];
|
|
@@ -16,10 +20,7 @@ interface ClientOptions {
|
|
|
16
20
|
drivers?: {
|
|
17
21
|
libsql?: Config;
|
|
18
22
|
postgres?: PoolConfig;
|
|
19
|
-
|
|
20
|
-
postgresNeonHTTP?: {
|
|
21
|
-
connectionString: string;
|
|
22
|
-
};
|
|
23
|
+
mysql?: mysql.ConnectionOptions;
|
|
23
24
|
};
|
|
24
25
|
options?: {
|
|
25
26
|
defaultTimeout?: number;
|
|
@@ -28,10 +29,14 @@ interface ClientOptions {
|
|
|
28
29
|
declare class DriftSQLClient<DT> {
|
|
29
30
|
private client;
|
|
30
31
|
private pool?;
|
|
32
|
+
private mysqlClient?;
|
|
31
33
|
private libsqlClient?;
|
|
32
34
|
private neonClient?;
|
|
35
|
+
private postgresClient?;
|
|
36
|
+
private drivers;
|
|
33
37
|
constructor(options: ClientOptions);
|
|
34
38
|
private convertLibsqlResult;
|
|
39
|
+
readonly inspect: () => Promise<void>;
|
|
35
40
|
query<T extends Record<string, any>>(query: string, args?: (string | number | boolean | null)[]): Promise<UnifiedQueryResult<T>>;
|
|
36
41
|
status(): Promise<{
|
|
37
42
|
ok: boolean;
|
|
@@ -46,5 +51,5 @@ declare class DriftSQLClient<DT> {
|
|
|
46
51
|
close(): Promise<void>;
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
export { DriftSQLClient };
|
|
54
|
+
export { DriftSQLClient, inspectDB };
|
|
50
55
|
export type { ClientOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { PoolConfig } from 'pg';
|
|
2
2
|
import { Config } from '@libsql/client';
|
|
3
|
+
import mysql from 'mysql2/promise';
|
|
4
|
+
|
|
5
|
+
type Drivers = ClientOptions['drivers'];
|
|
6
|
+
declare const inspectDB: (drivers: Drivers) => Promise<never>;
|
|
3
7
|
|
|
4
8
|
type UnifiedQueryResult<T extends Record<string, any>> = {
|
|
5
9
|
rows: T[];
|
|
@@ -16,10 +20,7 @@ interface ClientOptions {
|
|
|
16
20
|
drivers?: {
|
|
17
21
|
libsql?: Config;
|
|
18
22
|
postgres?: PoolConfig;
|
|
19
|
-
|
|
20
|
-
postgresNeonHTTP?: {
|
|
21
|
-
connectionString: string;
|
|
22
|
-
};
|
|
23
|
+
mysql?: mysql.ConnectionOptions;
|
|
23
24
|
};
|
|
24
25
|
options?: {
|
|
25
26
|
defaultTimeout?: number;
|
|
@@ -28,10 +29,14 @@ interface ClientOptions {
|
|
|
28
29
|
declare class DriftSQLClient<DT> {
|
|
29
30
|
private client;
|
|
30
31
|
private pool?;
|
|
32
|
+
private mysqlClient?;
|
|
31
33
|
private libsqlClient?;
|
|
32
34
|
private neonClient?;
|
|
35
|
+
private postgresClient?;
|
|
36
|
+
private drivers;
|
|
33
37
|
constructor(options: ClientOptions);
|
|
34
38
|
private convertLibsqlResult;
|
|
39
|
+
readonly inspect: () => Promise<void>;
|
|
35
40
|
query<T extends Record<string, any>>(query: string, args?: (string | number | boolean | null)[]): Promise<UnifiedQueryResult<T>>;
|
|
36
41
|
status(): Promise<{
|
|
37
42
|
ok: boolean;
|
|
@@ -46,5 +51,5 @@ declare class DriftSQLClient<DT> {
|
|
|
46
51
|
close(): Promise<void>;
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
export { DriftSQLClient };
|
|
54
|
+
export { DriftSQLClient, inspectDB };
|
|
50
55
|
export type { ClientOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -2,13 +2,150 @@ import consola from 'consola';
|
|
|
2
2
|
import ky from 'ky';
|
|
3
3
|
import { Pool } from 'pg';
|
|
4
4
|
import { createClient } from '@libsql/client';
|
|
5
|
-
import
|
|
5
|
+
import mysql from 'mysql2/promise';
|
|
6
|
+
import fs from 'node:fs/promises';
|
|
7
|
+
|
|
8
|
+
const supportedDrivers = ["postgres"];
|
|
9
|
+
const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
|
|
10
|
+
const nullable = isNullable ? " | null" : "";
|
|
11
|
+
switch (postgresType.toLowerCase()) {
|
|
12
|
+
case "uuid": {
|
|
13
|
+
return `string${nullable}`;
|
|
14
|
+
}
|
|
15
|
+
case "character varying":
|
|
16
|
+
case "varchar":
|
|
17
|
+
case "text":
|
|
18
|
+
case "char":
|
|
19
|
+
case "character": {
|
|
20
|
+
return `string${nullable}`;
|
|
21
|
+
}
|
|
22
|
+
case "integer":
|
|
23
|
+
case "int":
|
|
24
|
+
case "int4":
|
|
25
|
+
case "smallint":
|
|
26
|
+
case "int2":
|
|
27
|
+
case "bigint":
|
|
28
|
+
case "int8":
|
|
29
|
+
case "serial":
|
|
30
|
+
case "bigserial":
|
|
31
|
+
case "numeric":
|
|
32
|
+
case "decimal":
|
|
33
|
+
case "real":
|
|
34
|
+
case "float4":
|
|
35
|
+
case "double precision":
|
|
36
|
+
case "float8": {
|
|
37
|
+
return `number${nullable}`;
|
|
38
|
+
}
|
|
39
|
+
case "boolean":
|
|
40
|
+
case "bool": {
|
|
41
|
+
return `boolean${nullable}`;
|
|
42
|
+
}
|
|
43
|
+
case "timestamp":
|
|
44
|
+
case "timestamp with time zone":
|
|
45
|
+
case "timestamp without time zone":
|
|
46
|
+
case "timestamptz":
|
|
47
|
+
case "date":
|
|
48
|
+
case "time":
|
|
49
|
+
case "time with time zone":
|
|
50
|
+
case "time without time zone":
|
|
51
|
+
case "timetz":
|
|
52
|
+
case "interval": {
|
|
53
|
+
return `Date${nullable}`;
|
|
54
|
+
}
|
|
55
|
+
case "json":
|
|
56
|
+
case "jsonb": {
|
|
57
|
+
return `any${nullable}`;
|
|
58
|
+
}
|
|
59
|
+
case "array": {
|
|
60
|
+
return `any[]${nullable}`;
|
|
61
|
+
}
|
|
62
|
+
case "bytea": {
|
|
63
|
+
return `Buffer${nullable}`;
|
|
64
|
+
}
|
|
65
|
+
default: {
|
|
66
|
+
console.warn(`Unknown PostgreSQL type: ${postgresType}, defaulting to 'any'`);
|
|
67
|
+
return `any${nullable}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const inspectDB = async (drivers) => {
|
|
72
|
+
if (!drivers) throw new Error("No drivers provided for inspection");
|
|
73
|
+
const configuredDrivers = Object.keys(drivers).filter((key) => drivers[key] !== void 0);
|
|
74
|
+
if (configuredDrivers.length === 0) {
|
|
75
|
+
throw new Error("No drivers are configured");
|
|
76
|
+
}
|
|
77
|
+
const supportedConfiguredDrivers = configuredDrivers.filter((driver) => supportedDrivers.includes(driver));
|
|
78
|
+
if (supportedConfiguredDrivers.length === 0) {
|
|
79
|
+
throw new Error(`No supported drivers found. Configured: ${configuredDrivers.join(", ")}. Supported: ${supportedDrivers.join(", ")}`);
|
|
80
|
+
}
|
|
81
|
+
console.log(`Found supported drivers: ${supportedConfiguredDrivers.join(", ")}`);
|
|
82
|
+
let generatedTypes = "";
|
|
83
|
+
const client = new DriftSQLClient({ drivers });
|
|
84
|
+
const tables = await client.query(
|
|
85
|
+
`SELECT table_name
|
|
86
|
+
FROM information_schema.tables
|
|
87
|
+
WHERE table_schema = 'public'
|
|
88
|
+
AND table_type = 'BASE TABLE'
|
|
89
|
+
ORDER BY table_name`
|
|
90
|
+
);
|
|
91
|
+
console.log("Tables in the database:", tables.rows.map((t) => t.table_name).join(", "));
|
|
92
|
+
for (const table of tables.rows) {
|
|
93
|
+
const tableName = table.table_name;
|
|
94
|
+
console.log(`Inspecting table: ${tableName}`);
|
|
95
|
+
const columns = await client.query(
|
|
96
|
+
`
|
|
97
|
+
SELECT
|
|
98
|
+
column_name,
|
|
99
|
+
data_type,
|
|
100
|
+
is_nullable,
|
|
101
|
+
column_default
|
|
102
|
+
FROM information_schema.columns
|
|
103
|
+
WHERE table_name = $1
|
|
104
|
+
AND table_schema = 'public'
|
|
105
|
+
ORDER BY ordinal_position
|
|
106
|
+
`,
|
|
107
|
+
[tableName]
|
|
108
|
+
);
|
|
109
|
+
if (columns.rows.length === 0) {
|
|
110
|
+
console.log(`No columns found for table: ${tableName}`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
console.log(`Columns in ${tableName}:`, columns.rows.map((c) => `${c.column_name} (${c.data_type}${c.is_nullable === "YES" ? ", nullable" : ""})`).join(", "));
|
|
114
|
+
const uniqueColumns = /* @__PURE__ */ new Map();
|
|
115
|
+
columns.rows.forEach((col) => {
|
|
116
|
+
if (!uniqueColumns.has(col.column_name)) {
|
|
117
|
+
uniqueColumns.set(col.column_name, col);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
generatedTypes += `export interface ${tableName.charAt(0).toUpperCase() + tableName.slice(1)} {
|
|
121
|
+
`;
|
|
122
|
+
for (const col of uniqueColumns.values()) {
|
|
123
|
+
const tsType = mapPostgresToTypeScript(col.data_type, col.is_nullable === "YES");
|
|
124
|
+
generatedTypes += ` ${col.column_name}: ${tsType};
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
generatedTypes += "}\n\n";
|
|
128
|
+
}
|
|
129
|
+
generatedTypes += "export interface Database {\n";
|
|
130
|
+
for (const table of tables.rows) {
|
|
131
|
+
const tableName = table.table_name.charAt(0).toUpperCase() + table.table_name.slice(1);
|
|
132
|
+
generatedTypes += ` ${tableName}: ${tableName};
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
generatedTypes += "}\n\n";
|
|
136
|
+
await fs.writeFile("db-types.ts", generatedTypes, "utf8");
|
|
137
|
+
console.log("TypeScript types written to db-types.ts");
|
|
138
|
+
process.exit(0);
|
|
139
|
+
};
|
|
6
140
|
|
|
7
141
|
class DriftSQLClient {
|
|
8
142
|
client;
|
|
9
143
|
pool;
|
|
144
|
+
mysqlClient;
|
|
10
145
|
libsqlClient;
|
|
11
146
|
neonClient;
|
|
147
|
+
postgresClient;
|
|
148
|
+
drivers;
|
|
12
149
|
constructor(options) {
|
|
13
150
|
this.client = ky.create({
|
|
14
151
|
prefixUrl: options.url,
|
|
@@ -30,7 +167,8 @@ class DriftSQLClient {
|
|
|
30
167
|
});
|
|
31
168
|
this.pool = options.drivers?.postgres ? new Pool(options.drivers.postgres) : void 0;
|
|
32
169
|
this.libsqlClient = options.drivers?.libsql ? createClient(options.drivers.libsql) : void 0;
|
|
33
|
-
this.
|
|
170
|
+
this.mysqlClient = options.drivers?.mysql ? mysql.createConnection(options.drivers.mysql) : void 0;
|
|
171
|
+
this.drivers = options.drivers || {};
|
|
34
172
|
}
|
|
35
173
|
convertLibsqlResult(result) {
|
|
36
174
|
const rows = result.rows.map((row) => {
|
|
@@ -47,6 +185,9 @@ class DriftSQLClient {
|
|
|
47
185
|
fields: result.columns.map((col) => ({ name: col, dataTypeID: 0 }))
|
|
48
186
|
};
|
|
49
187
|
}
|
|
188
|
+
inspect = async () => {
|
|
189
|
+
return inspectDB(this.drivers);
|
|
190
|
+
};
|
|
50
191
|
async query(query, args) {
|
|
51
192
|
if (this.pool) {
|
|
52
193
|
try {
|
|
@@ -62,6 +203,38 @@ class DriftSQLClient {
|
|
|
62
203
|
consola.error("Failed to connect to PostgreSQL pool:", error);
|
|
63
204
|
}
|
|
64
205
|
}
|
|
206
|
+
if (this.mysqlClient) {
|
|
207
|
+
try {
|
|
208
|
+
consola.warn("MySQL client is experimental and may not be compatible with the helper functions, since they originally designed for PostgreSQL and libsql. But .query() method should work.");
|
|
209
|
+
const [rows, fields] = await (await this.mysqlClient).execute(query, args || []);
|
|
210
|
+
return {
|
|
211
|
+
rows,
|
|
212
|
+
rowCount: Array.isArray(rows) ? rows.length : 0,
|
|
213
|
+
command: void 0,
|
|
214
|
+
// MySQL does not return command info
|
|
215
|
+
fields: fields.map((field) => ({ name: field.name, dataTypeID: field.columnType }))
|
|
216
|
+
};
|
|
217
|
+
} catch (error) {
|
|
218
|
+
consola.error("Failed to execute query with MySQL:", error);
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (this.postgresClient) {
|
|
223
|
+
try {
|
|
224
|
+
const result = await this.postgresClient.unsafe(query, args || []);
|
|
225
|
+
return {
|
|
226
|
+
// @ts-ignore - postgres library returns rows directly
|
|
227
|
+
rows: result,
|
|
228
|
+
rowCount: result.length,
|
|
229
|
+
command: void 0,
|
|
230
|
+
fields: []
|
|
231
|
+
// postgres library does not provide field info
|
|
232
|
+
};
|
|
233
|
+
} catch (error) {
|
|
234
|
+
consola.error("Failed to execute query with postgres:", error);
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
65
238
|
if (this.libsqlClient) {
|
|
66
239
|
try {
|
|
67
240
|
const result = await this.libsqlClient.execute({
|
|
@@ -191,4 +364,4 @@ class DriftSQLClient {
|
|
|
191
364
|
}
|
|
192
365
|
}
|
|
193
366
|
|
|
194
|
-
export { DriftSQLClient };
|
|
367
|
+
export { DriftSQLClient, inspectDB };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "driftsql",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"author": "lasse vestergaard",
|
|
5
5
|
"description": "A lightweight SQL client for TypeScript, supporting multiple databases like PostgreSQL, MySQL, and LibSQL.",
|
|
6
6
|
"repository": "lassejlv/driftsql",
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
"driftsql": "^0.0.1",
|
|
48
48
|
"drizzle-orm": "^0.44.2",
|
|
49
49
|
"ky": "^1.8.1",
|
|
50
|
-
"
|
|
50
|
+
"mysql2": "^3.14.1",
|
|
51
|
+
"pg": "^8.16.0",
|
|
52
|
+
"postgres": "^3.4.7"
|
|
51
53
|
}
|
|
52
54
|
}
|