driftsql 1.0.3 → 1.0.5

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c)
3
+ Copyright (c) 2025 Lasse Vestergaard
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/index.d.mts CHANGED
@@ -31,7 +31,6 @@ declare class DriftSQLClient<DT> {
31
31
  private pool?;
32
32
  private mysqlClient?;
33
33
  private libsqlClient?;
34
- private neonClient?;
35
34
  private postgresClient?;
36
35
  private drivers;
37
36
  constructor(options: ClientOptions);
@@ -43,7 +42,10 @@ declare class DriftSQLClient<DT> {
43
42
  ping: number;
44
43
  }>;
45
44
  findFirst<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K] | null>;
46
- findMany<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K][]>;
45
+ findMany<K extends keyof DT>(table: K, options?: {
46
+ where?: Partial<DT[K]>;
47
+ limit?: number;
48
+ }): Promise<DT[K][]>;
47
49
  insert<K extends keyof DT>(table: K, data: Partial<DT[K]>): Promise<DT[K]>;
48
50
  update<K extends keyof DT>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>): Promise<DT[K] | null>;
49
51
  delete<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<boolean>;
package/dist/index.d.ts CHANGED
@@ -31,7 +31,6 @@ declare class DriftSQLClient<DT> {
31
31
  private pool?;
32
32
  private mysqlClient?;
33
33
  private libsqlClient?;
34
- private neonClient?;
35
34
  private postgresClient?;
36
35
  private drivers;
37
36
  constructor(options: ClientOptions);
@@ -43,7 +42,10 @@ declare class DriftSQLClient<DT> {
43
42
  ping: number;
44
43
  }>;
45
44
  findFirst<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K] | null>;
46
- findMany<K extends keyof DT>(table: K, where?: Partial<DT[K]>): Promise<DT[K][]>;
45
+ findMany<K extends keyof DT>(table: K, options?: {
46
+ where?: Partial<DT[K]>;
47
+ limit?: number;
48
+ }): Promise<DT[K][]>;
47
49
  insert<K extends keyof DT>(table: K, data: Partial<DT[K]>): Promise<DT[K]>;
48
50
  update<K extends keyof DT>(table: K, data: Partial<DT[K]>, where: Partial<DT[K]>): Promise<DT[K] | null>;
49
51
  delete<K extends keyof DT>(table: K, where: Partial<DT[K]>): Promise<boolean>;
package/dist/index.mjs CHANGED
@@ -5,10 +5,11 @@ import { createClient } from '@libsql/client';
5
5
  import mysql from 'mysql2/promise';
6
6
  import fs from 'node:fs/promises';
7
7
 
8
- const supportedDrivers = ["postgres"];
9
- const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
8
+ const supportedDrivers = ["postgres", "mysql"];
9
+ const mapDatabaseTypeToTypeScript = (dataType, isNullable = false, driverType = "postgres") => {
10
10
  const nullable = isNullable ? " | null" : "";
11
- switch (postgresType.toLowerCase()) {
11
+ const lowerType = dataType.toLowerCase();
12
+ switch (lowerType) {
12
13
  case "uuid": {
13
14
  return `string${nullable}`;
14
15
  }
@@ -16,7 +17,10 @@ const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
16
17
  case "varchar":
17
18
  case "text":
18
19
  case "char":
19
- case "character": {
20
+ case "character":
21
+ case "longtext":
22
+ case "mediumtext":
23
+ case "tinytext": {
20
24
  return `string${nullable}`;
21
25
  }
22
26
  case "integer":
@@ -33,11 +37,16 @@ const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
33
37
  case "real":
34
38
  case "float4":
35
39
  case "double precision":
36
- case "float8": {
40
+ case "float8":
41
+ case "tinyint":
42
+ case "mediumint":
43
+ case "float":
44
+ case "double": {
37
45
  return `number${nullable}`;
38
46
  }
39
47
  case "boolean":
40
- case "bool": {
48
+ case "bool":
49
+ case "bit": {
41
50
  return `boolean${nullable}`;
42
51
  }
43
52
  case "timestamp":
@@ -49,7 +58,9 @@ const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
49
58
  case "time with time zone":
50
59
  case "time without time zone":
51
60
  case "timetz":
52
- case "interval": {
61
+ case "interval":
62
+ case "datetime":
63
+ case "year": {
53
64
  return `Date${nullable}`;
54
65
  }
55
66
  case "json":
@@ -59,11 +70,21 @@ const mapPostgresToTypeScript = (postgresType, isNullable = false) => {
59
70
  case "array": {
60
71
  return `any[]${nullable}`;
61
72
  }
62
- case "bytea": {
73
+ case "bytea":
74
+ case "binary":
75
+ case "varbinary":
76
+ case "blob":
77
+ case "longblob":
78
+ case "mediumblob":
79
+ case "tinyblob": {
63
80
  return `Buffer${nullable}`;
64
81
  }
82
+ case "enum":
83
+ case "set": {
84
+ return `string${nullable}`;
85
+ }
65
86
  default: {
66
- console.warn(`Unknown PostgreSQL type: ${postgresType}, defaulting to 'any'`);
87
+ console.warn(`Unknown ${driverType} type: ${dataType}, defaulting to 'any'`);
67
88
  return `any${nullable}`;
68
89
  }
69
90
  }
@@ -79,33 +100,67 @@ const inspectDB = async (drivers) => {
79
100
  throw new Error(`No supported drivers found. Configured: ${configuredDrivers.join(", ")}. Supported: ${supportedDrivers.join(", ")}`);
80
101
  }
81
102
  console.log(`Found supported drivers: ${supportedConfiguredDrivers.join(", ")}`);
103
+ const activeDriver = supportedConfiguredDrivers[0];
82
104
  let generatedTypes = "";
83
105
  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
- );
106
+ let tablesQuery;
107
+ let tableSchemaFilter;
108
+ if (activeDriver === "mysql") {
109
+ const dbResult = await client.query("SELECT DATABASE() as `database`", []);
110
+ const currentDatabase = dbResult.rows[0]?.database;
111
+ if (!currentDatabase) {
112
+ throw new Error("Could not determine current MySQL database name");
113
+ }
114
+ console.log(`Using MySQL database: ${currentDatabase}`);
115
+ tablesQuery = `SELECT TABLE_NAME as table_name
116
+ FROM information_schema.tables
117
+ WHERE TABLE_SCHEMA = ?
118
+ AND TABLE_TYPE = 'BASE TABLE'
119
+ ORDER BY TABLE_NAME`;
120
+ tableSchemaFilter = currentDatabase;
121
+ } else {
122
+ tablesQuery = `SELECT table_name
123
+ FROM information_schema.tables
124
+ WHERE table_schema = $1
125
+ AND table_type = 'BASE TABLE'
126
+ ORDER BY table_name`;
127
+ tableSchemaFilter = "public";
128
+ }
129
+ const tables = await client.query(tablesQuery, tableSchemaFilter ? [tableSchemaFilter] : []);
91
130
  console.log("Tables in the database:", tables.rows.map((t) => t.table_name).join(", "));
92
131
  for (const table of tables.rows) {
93
132
  const tableName = table.table_name;
94
133
  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
- );
134
+ let columnsQuery;
135
+ let queryParams;
136
+ if (activeDriver === "mysql") {
137
+ columnsQuery = `
138
+ SELECT
139
+ COLUMN_NAME as column_name,
140
+ DATA_TYPE as data_type,
141
+ IS_NULLABLE as is_nullable,
142
+ COLUMN_DEFAULT as column_default
143
+ FROM information_schema.columns
144
+ WHERE TABLE_NAME = ?
145
+ AND TABLE_SCHEMA = ?
146
+ ORDER BY ORDINAL_POSITION
147
+ `;
148
+ queryParams = [tableName, tableSchemaFilter];
149
+ } else {
150
+ columnsQuery = `
151
+ SELECT
152
+ column_name,
153
+ data_type,
154
+ is_nullable,
155
+ column_default
156
+ FROM information_schema.columns
157
+ WHERE table_name = $1
158
+ AND table_schema = $2
159
+ ORDER BY ordinal_position
160
+ `;
161
+ queryParams = [tableName, tableSchemaFilter];
162
+ }
163
+ const columns = await client.query(columnsQuery, queryParams);
109
164
  if (columns.rows.length === 0) {
110
165
  console.log(`No columns found for table: ${tableName}`);
111
166
  continue;
@@ -120,7 +175,7 @@ const inspectDB = async (drivers) => {
120
175
  generatedTypes += `export interface ${tableName.charAt(0).toUpperCase() + tableName.slice(1)} {
121
176
  `;
122
177
  for (const col of uniqueColumns.values()) {
123
- const tsType = mapPostgresToTypeScript(col.data_type, col.is_nullable === "YES");
178
+ const tsType = mapDatabaseTypeToTypeScript(col.data_type, col.is_nullable === "YES", activeDriver);
124
179
  generatedTypes += ` ${col.column_name}: ${tsType};
125
180
  `;
126
181
  }
@@ -143,7 +198,6 @@ class DriftSQLClient {
143
198
  pool;
144
199
  mysqlClient;
145
200
  libsqlClient;
146
- neonClient;
147
201
  postgresClient;
148
202
  drivers;
149
203
  constructor(options) {
@@ -189,6 +243,12 @@ class DriftSQLClient {
189
243
  return inspectDB(this.drivers);
190
244
  };
191
245
  async query(query, args) {
246
+ const driversCount = Object.keys(this.drivers).filter((key) => this.drivers[key] !== void 0).length;
247
+ if (driversCount > 1) {
248
+ const error = new Error("Multiple drivers are configured. Please use only one driver at a time.");
249
+ consola.error(error);
250
+ throw error;
251
+ }
192
252
  if (this.pool) {
193
253
  try {
194
254
  await this.pool.connect();
@@ -206,7 +266,8 @@ class DriftSQLClient {
206
266
  if (this.mysqlClient) {
207
267
  try {
208
268
  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 || []);
269
+ const filteredArgs = (args || []).map((arg) => arg === void 0 ? null : arg);
270
+ const [rows, fields] = await (await this.mysqlClient).execute(query, filteredArgs);
210
271
  return {
211
272
  rows,
212
273
  rowCount: Array.isArray(rows) ? rows.length : 0,
@@ -247,20 +308,6 @@ class DriftSQLClient {
247
308
  throw error;
248
309
  }
249
310
  }
250
- if (this.neonClient) {
251
- try {
252
- const sql = this.neonClient;
253
- console.log(sql);
254
- throw new Error("Neon client is not implemented yet");
255
- return {
256
- rows: [],
257
- rowCount: 0
258
- };
259
- } catch (error) {
260
- consola.error("Failed to execute query with Neon:", error);
261
- throw error;
262
- }
263
- }
264
311
  try {
265
312
  const response = await this.client.post("query", {
266
313
  json: { query, args: args || [] }
@@ -294,8 +341,9 @@ class DriftSQLClient {
294
341
  const result = await this.query(query, args);
295
342
  return result.rows[0] || null;
296
343
  }
297
- async findMany(table, where) {
344
+ async findMany(table, options) {
298
345
  const tableName = String(table);
346
+ const { where, limit } = options || {};
299
347
  const whereEntries = Object.entries(where || {});
300
348
  let query = `SELECT * FROM ${tableName}`;
301
349
  let args = [];
@@ -304,6 +352,10 @@ class DriftSQLClient {
304
352
  query += ` WHERE ${whereClause}`;
305
353
  args = whereEntries.map(([, value]) => value);
306
354
  }
355
+ if (typeof limit === "number" && limit > 0) {
356
+ query += ` LIMIT $${args.length + 1}`;
357
+ args.push(limit);
358
+ }
307
359
  const result = await this.query(query, args);
308
360
  return result.rows;
309
361
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "driftsql",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
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",