@parsrun/database 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.
- package/README.md +103 -0
- package/dist/adapters/d1.d.ts +56 -0
- package/dist/adapters/d1.js +115 -0
- package/dist/adapters/d1.js.map +1 -0
- package/dist/adapters/neon.d.ts +49 -0
- package/dist/adapters/neon.js +145 -0
- package/dist/adapters/neon.js.map +1 -0
- package/dist/adapters/postgres.d.ts +59 -0
- package/dist/adapters/postgres.js +165 -0
- package/dist/adapters/postgres.js.map +1 -0
- package/dist/index.d.ts +177 -0
- package/dist/index.js +651 -0
- package/dist/index.js.map +1 -0
- package/dist/types-DgBIyTeZ.d.ts +198 -0
- package/package.json +70 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/types.ts
|
|
12
|
+
var DatabaseError, DatabaseErrorCodes;
|
|
13
|
+
var init_types = __esm({
|
|
14
|
+
"src/types.ts"() {
|
|
15
|
+
"use strict";
|
|
16
|
+
DatabaseError = class extends Error {
|
|
17
|
+
constructor(message, code, cause) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.cause = cause;
|
|
21
|
+
this.name = "DatabaseError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
DatabaseErrorCodes = {
|
|
25
|
+
CONNECTION_FAILED: "CONNECTION_FAILED",
|
|
26
|
+
QUERY_FAILED: "QUERY_FAILED",
|
|
27
|
+
TRANSACTION_FAILED: "TRANSACTION_FAILED",
|
|
28
|
+
MIGRATION_FAILED: "MIGRATION_FAILED",
|
|
29
|
+
INVALID_CONFIG: "INVALID_CONFIG",
|
|
30
|
+
ADAPTER_NOT_AVAILABLE: "ADAPTER_NOT_AVAILABLE",
|
|
31
|
+
TIMEOUT: "TIMEOUT",
|
|
32
|
+
CONSTRAINT_VIOLATION: "CONSTRAINT_VIOLATION",
|
|
33
|
+
NOT_FOUND: "NOT_FOUND"
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// src/adapters/postgres.ts
|
|
39
|
+
var postgres_exports = {};
|
|
40
|
+
__export(postgres_exports, {
|
|
41
|
+
PostgresAdapter: () => PostgresAdapter,
|
|
42
|
+
createPostgresAdapter: () => createPostgresAdapter,
|
|
43
|
+
createPostgresFromUrl: () => createPostgresFromUrl
|
|
44
|
+
});
|
|
45
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
46
|
+
async function createPostgresAdapter(config) {
|
|
47
|
+
const adapter = new PostgresAdapter(config);
|
|
48
|
+
await adapter.connect();
|
|
49
|
+
return adapter;
|
|
50
|
+
}
|
|
51
|
+
async function createPostgresFromUrl(connectionString, options) {
|
|
52
|
+
const url = new URL(connectionString);
|
|
53
|
+
const config = {
|
|
54
|
+
type: "postgres",
|
|
55
|
+
host: url.hostname,
|
|
56
|
+
port: parseInt(url.port || "5432", 10),
|
|
57
|
+
user: url.username,
|
|
58
|
+
password: url.password,
|
|
59
|
+
database: url.pathname.slice(1),
|
|
60
|
+
ssl: url.searchParams.get("sslmode") === "require",
|
|
61
|
+
...options
|
|
62
|
+
};
|
|
63
|
+
return createPostgresAdapter(config);
|
|
64
|
+
}
|
|
65
|
+
var PostgresAdapter;
|
|
66
|
+
var init_postgres = __esm({
|
|
67
|
+
"src/adapters/postgres.ts"() {
|
|
68
|
+
"use strict";
|
|
69
|
+
init_types();
|
|
70
|
+
PostgresAdapter = class {
|
|
71
|
+
type = "postgres";
|
|
72
|
+
client = null;
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
|
+
db = null;
|
|
75
|
+
config;
|
|
76
|
+
constructor(config) {
|
|
77
|
+
this.config = config;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Initialize the connection
|
|
81
|
+
*/
|
|
82
|
+
async connect() {
|
|
83
|
+
if (this.client) return;
|
|
84
|
+
try {
|
|
85
|
+
const postgresModule = await import("postgres");
|
|
86
|
+
const postgres = postgresModule.default;
|
|
87
|
+
let sslConfig = false;
|
|
88
|
+
if (this.config.ssl === true) {
|
|
89
|
+
sslConfig = "require";
|
|
90
|
+
} else if (typeof this.config.ssl === "object") {
|
|
91
|
+
sslConfig = this.config.ssl;
|
|
92
|
+
}
|
|
93
|
+
this.client = postgres({
|
|
94
|
+
host: this.config.host,
|
|
95
|
+
port: this.config.port,
|
|
96
|
+
user: this.config.user,
|
|
97
|
+
password: this.config.password,
|
|
98
|
+
database: this.config.database,
|
|
99
|
+
ssl: sslConfig,
|
|
100
|
+
max: this.config.poolSize ?? 10
|
|
101
|
+
});
|
|
102
|
+
const drizzleOpts = {};
|
|
103
|
+
if (this.config.logging !== void 0) {
|
|
104
|
+
drizzleOpts.logger = this.config.logging;
|
|
105
|
+
}
|
|
106
|
+
this.db = drizzle(this.client, drizzleOpts);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
throw new DatabaseError(
|
|
109
|
+
`Failed to connect to PostgreSQL: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
110
|
+
DatabaseErrorCodes.CONNECTION_FAILED,
|
|
111
|
+
err
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async execute(sql) {
|
|
116
|
+
if (!this.client) {
|
|
117
|
+
await this.connect();
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const client = this.client;
|
|
121
|
+
const result = await client.unsafe(sql);
|
|
122
|
+
return result;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
throw new DatabaseError(
|
|
125
|
+
`Query failed: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
126
|
+
DatabaseErrorCodes.QUERY_FAILED,
|
|
127
|
+
err
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async ping() {
|
|
132
|
+
try {
|
|
133
|
+
await this.execute("SELECT 1");
|
|
134
|
+
return true;
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async health() {
|
|
140
|
+
const start = Date.now();
|
|
141
|
+
try {
|
|
142
|
+
if (!this.client) {
|
|
143
|
+
await this.connect();
|
|
144
|
+
}
|
|
145
|
+
const result = await this.execute("SELECT version()");
|
|
146
|
+
const latencyMs = Date.now() - start;
|
|
147
|
+
return {
|
|
148
|
+
healthy: true,
|
|
149
|
+
latencyMs,
|
|
150
|
+
version: result[0]?.version
|
|
151
|
+
};
|
|
152
|
+
} catch (err) {
|
|
153
|
+
return {
|
|
154
|
+
healthy: false,
|
|
155
|
+
latencyMs: Date.now() - start,
|
|
156
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
|
+
drizzle() {
|
|
162
|
+
if (!this.db) {
|
|
163
|
+
throw new DatabaseError(
|
|
164
|
+
"Database not connected. Call connect() first.",
|
|
165
|
+
DatabaseErrorCodes.CONNECTION_FAILED
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
return this.db;
|
|
169
|
+
}
|
|
170
|
+
async close() {
|
|
171
|
+
if (this.client) {
|
|
172
|
+
const client = this.client;
|
|
173
|
+
await client.end();
|
|
174
|
+
this.client = null;
|
|
175
|
+
this.db = null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the raw postgres client
|
|
180
|
+
*/
|
|
181
|
+
getClient() {
|
|
182
|
+
return this.client;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// src/adapters/neon.ts
|
|
189
|
+
var neon_exports = {};
|
|
190
|
+
__export(neon_exports, {
|
|
191
|
+
NeonAdapter: () => NeonAdapter,
|
|
192
|
+
createNeonAdapter: () => createNeonAdapter,
|
|
193
|
+
createNeonFromUrl: () => createNeonFromUrl
|
|
194
|
+
});
|
|
195
|
+
import { drizzle as drizzle2 } from "drizzle-orm/neon-http";
|
|
196
|
+
async function createNeonAdapter(config) {
|
|
197
|
+
const adapter = new NeonAdapter(config);
|
|
198
|
+
await adapter.connect();
|
|
199
|
+
return adapter;
|
|
200
|
+
}
|
|
201
|
+
async function createNeonFromUrl(connectionString, options) {
|
|
202
|
+
return createNeonAdapter({
|
|
203
|
+
type: "neon",
|
|
204
|
+
connectionString,
|
|
205
|
+
...options
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
var NeonAdapter;
|
|
209
|
+
var init_neon = __esm({
|
|
210
|
+
"src/adapters/neon.ts"() {
|
|
211
|
+
"use strict";
|
|
212
|
+
init_types();
|
|
213
|
+
NeonAdapter = class {
|
|
214
|
+
type = "neon";
|
|
215
|
+
client = null;
|
|
216
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
217
|
+
db = null;
|
|
218
|
+
config;
|
|
219
|
+
constructor(config) {
|
|
220
|
+
this.config = config;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Initialize the connection
|
|
224
|
+
*/
|
|
225
|
+
async connect() {
|
|
226
|
+
if (this.client) return;
|
|
227
|
+
try {
|
|
228
|
+
const { neon } = await import("@neondatabase/serverless");
|
|
229
|
+
this.client = neon(this.config.connectionString, {
|
|
230
|
+
fetchOptions: {
|
|
231
|
+
cache: "no-store"
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
const drizzleOpts = {};
|
|
235
|
+
if (this.config.logging !== void 0) {
|
|
236
|
+
drizzleOpts.logger = this.config.logging;
|
|
237
|
+
}
|
|
238
|
+
this.db = drizzle2(this.client, drizzleOpts);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
throw new DatabaseError(
|
|
241
|
+
`Failed to connect to Neon: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
242
|
+
DatabaseErrorCodes.CONNECTION_FAILED,
|
|
243
|
+
err
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async execute(sql) {
|
|
248
|
+
if (!this.client) {
|
|
249
|
+
await this.connect();
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const result = await this.client(sql);
|
|
253
|
+
if (Array.isArray(result) && result.rows) {
|
|
254
|
+
return result.rows;
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
} catch (err) {
|
|
258
|
+
throw new DatabaseError(
|
|
259
|
+
`Query failed: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
260
|
+
DatabaseErrorCodes.QUERY_FAILED,
|
|
261
|
+
err
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async ping() {
|
|
266
|
+
try {
|
|
267
|
+
await this.execute("SELECT 1");
|
|
268
|
+
return true;
|
|
269
|
+
} catch {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async health() {
|
|
274
|
+
const start = Date.now();
|
|
275
|
+
try {
|
|
276
|
+
if (!this.client) {
|
|
277
|
+
await this.connect();
|
|
278
|
+
}
|
|
279
|
+
const result = await this.execute("SELECT version()");
|
|
280
|
+
const latencyMs = Date.now() - start;
|
|
281
|
+
return {
|
|
282
|
+
healthy: true,
|
|
283
|
+
latencyMs,
|
|
284
|
+
version: result[0]?.version
|
|
285
|
+
};
|
|
286
|
+
} catch (err) {
|
|
287
|
+
return {
|
|
288
|
+
healthy: false,
|
|
289
|
+
latencyMs: Date.now() - start,
|
|
290
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
295
|
+
drizzle() {
|
|
296
|
+
if (!this.db) {
|
|
297
|
+
throw new DatabaseError(
|
|
298
|
+
"Database not connected. Call connect() first.",
|
|
299
|
+
DatabaseErrorCodes.CONNECTION_FAILED
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
return this.db;
|
|
303
|
+
}
|
|
304
|
+
async close() {
|
|
305
|
+
this.client = null;
|
|
306
|
+
this.db = null;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get the raw Neon client
|
|
310
|
+
*/
|
|
311
|
+
getClient() {
|
|
312
|
+
return this.client;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// src/adapters/d1.ts
|
|
319
|
+
var d1_exports = {};
|
|
320
|
+
__export(d1_exports, {
|
|
321
|
+
D1Adapter: () => D1Adapter,
|
|
322
|
+
createD1Adapter: () => createD1Adapter
|
|
323
|
+
});
|
|
324
|
+
import { drizzle as drizzle3 } from "drizzle-orm/d1";
|
|
325
|
+
function createD1Adapter(config) {
|
|
326
|
+
return new D1Adapter(config);
|
|
327
|
+
}
|
|
328
|
+
var D1Adapter;
|
|
329
|
+
var init_d1 = __esm({
|
|
330
|
+
"src/adapters/d1.ts"() {
|
|
331
|
+
"use strict";
|
|
332
|
+
init_types();
|
|
333
|
+
D1Adapter = class {
|
|
334
|
+
type = "d1";
|
|
335
|
+
binding;
|
|
336
|
+
db;
|
|
337
|
+
constructor(config) {
|
|
338
|
+
this.binding = config.binding;
|
|
339
|
+
const drizzleConfig = {};
|
|
340
|
+
if (config.logging !== void 0) {
|
|
341
|
+
drizzleConfig.logger = config.logging;
|
|
342
|
+
}
|
|
343
|
+
this.db = drizzle3(this.binding, drizzleConfig);
|
|
344
|
+
}
|
|
345
|
+
async execute(sql) {
|
|
346
|
+
try {
|
|
347
|
+
const result = await this.binding.exec(sql);
|
|
348
|
+
return result.results ?? [];
|
|
349
|
+
} catch (err) {
|
|
350
|
+
throw new DatabaseError(
|
|
351
|
+
`Query failed: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
352
|
+
DatabaseErrorCodes.QUERY_FAILED,
|
|
353
|
+
err
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async ping() {
|
|
358
|
+
try {
|
|
359
|
+
await this.binding.prepare("SELECT 1").first();
|
|
360
|
+
return true;
|
|
361
|
+
} catch {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
async health() {
|
|
366
|
+
const start = Date.now();
|
|
367
|
+
try {
|
|
368
|
+
await this.binding.prepare("SELECT 1").first();
|
|
369
|
+
const latencyMs = Date.now() - start;
|
|
370
|
+
const versionResult = await this.binding.prepare("SELECT sqlite_version() as version").first();
|
|
371
|
+
return {
|
|
372
|
+
healthy: true,
|
|
373
|
+
latencyMs,
|
|
374
|
+
version: versionResult ? `SQLite ${versionResult.version}` : void 0
|
|
375
|
+
};
|
|
376
|
+
} catch (err) {
|
|
377
|
+
return {
|
|
378
|
+
healthy: false,
|
|
379
|
+
latencyMs: Date.now() - start,
|
|
380
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
drizzle() {
|
|
385
|
+
return this.db;
|
|
386
|
+
}
|
|
387
|
+
async close() {
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get the raw D1 binding
|
|
391
|
+
*/
|
|
392
|
+
getBinding() {
|
|
393
|
+
return this.binding;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Execute a batch of statements
|
|
397
|
+
*/
|
|
398
|
+
async batch(statements) {
|
|
399
|
+
try {
|
|
400
|
+
const prepared = statements.map((stmt) => {
|
|
401
|
+
const p = this.binding.prepare(stmt.sql);
|
|
402
|
+
return stmt.params ? p.bind(...stmt.params) : p;
|
|
403
|
+
});
|
|
404
|
+
const results = await this.binding.batch(prepared);
|
|
405
|
+
return results.map((r) => r.results ?? []);
|
|
406
|
+
} catch (err) {
|
|
407
|
+
throw new DatabaseError(
|
|
408
|
+
`Batch execution failed: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
409
|
+
DatabaseErrorCodes.QUERY_FAILED,
|
|
410
|
+
err
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// src/index.ts
|
|
419
|
+
init_types();
|
|
420
|
+
init_postgres();
|
|
421
|
+
init_neon();
|
|
422
|
+
init_d1();
|
|
423
|
+
|
|
424
|
+
// src/utils.ts
|
|
425
|
+
function sleep(ms) {
|
|
426
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
427
|
+
}
|
|
428
|
+
async function retry(operation, options = {}) {
|
|
429
|
+
const {
|
|
430
|
+
maxAttempts = 3,
|
|
431
|
+
baseDelay = 100,
|
|
432
|
+
maxDelay = 5e3,
|
|
433
|
+
shouldRetry = isRetryableError
|
|
434
|
+
} = options;
|
|
435
|
+
let lastError;
|
|
436
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
437
|
+
try {
|
|
438
|
+
return await operation();
|
|
439
|
+
} catch (error) {
|
|
440
|
+
lastError = error;
|
|
441
|
+
if (attempt === maxAttempts || !shouldRetry(error)) {
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
445
|
+
await sleep(delay);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
throw lastError;
|
|
449
|
+
}
|
|
450
|
+
function isRetryableError(error) {
|
|
451
|
+
if (error instanceof Error) {
|
|
452
|
+
const message = error.message.toLowerCase();
|
|
453
|
+
if (message.includes("connection") || message.includes("econnrefused") || message.includes("econnreset") || message.includes("etimedout")) {
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
if (message.includes("could not serialize") || message.includes("deadlock detected")) {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
if (message.includes("too many clients")) {
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
function parseConnectionString(connectionString) {
|
|
466
|
+
const url = new URL(connectionString);
|
|
467
|
+
const params = {};
|
|
468
|
+
url.searchParams.forEach((value, key) => {
|
|
469
|
+
params[key] = value;
|
|
470
|
+
});
|
|
471
|
+
return {
|
|
472
|
+
host: url.hostname,
|
|
473
|
+
port: parseInt(url.port || "5432", 10),
|
|
474
|
+
user: decodeURIComponent(url.username),
|
|
475
|
+
password: decodeURIComponent(url.password),
|
|
476
|
+
database: url.pathname.slice(1),
|
|
477
|
+
ssl: url.searchParams.get("sslmode") === "require" || url.searchParams.get("ssl") === "true",
|
|
478
|
+
params
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function buildConnectionString(config) {
|
|
482
|
+
const url = new URL(`postgresql://${config.host}`);
|
|
483
|
+
url.port = String(config.port ?? 5432);
|
|
484
|
+
url.username = encodeURIComponent(config.user);
|
|
485
|
+
url.password = encodeURIComponent(config.password);
|
|
486
|
+
url.pathname = `/${config.database}`;
|
|
487
|
+
if (config.ssl) {
|
|
488
|
+
url.searchParams.set("sslmode", "require");
|
|
489
|
+
}
|
|
490
|
+
if (config.params) {
|
|
491
|
+
for (const [key, value] of Object.entries(config.params)) {
|
|
492
|
+
url.searchParams.set(key, value);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return url.toString();
|
|
496
|
+
}
|
|
497
|
+
function snakeToCamel(str) {
|
|
498
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
499
|
+
}
|
|
500
|
+
function camelToSnake(str) {
|
|
501
|
+
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
502
|
+
}
|
|
503
|
+
function transformToCamelCase(obj) {
|
|
504
|
+
const result = {};
|
|
505
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
506
|
+
const newKey = snakeToCamel(key);
|
|
507
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
508
|
+
result[newKey] = transformToCamelCase(value);
|
|
509
|
+
} else if (Array.isArray(value)) {
|
|
510
|
+
result[newKey] = value.map(
|
|
511
|
+
(item) => item && typeof item === "object" ? transformToCamelCase(item) : item
|
|
512
|
+
);
|
|
513
|
+
} else {
|
|
514
|
+
result[newKey] = value;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
function transformToSnakeCase(obj) {
|
|
520
|
+
const result = {};
|
|
521
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
522
|
+
const newKey = camelToSnake(key);
|
|
523
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
524
|
+
result[newKey] = transformToSnakeCase(value);
|
|
525
|
+
} else if (Array.isArray(value)) {
|
|
526
|
+
result[newKey] = value.map(
|
|
527
|
+
(item) => item && typeof item === "object" ? transformToSnakeCase(item) : item
|
|
528
|
+
);
|
|
529
|
+
} else {
|
|
530
|
+
result[newKey] = value;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return result;
|
|
534
|
+
}
|
|
535
|
+
function generateUUID() {
|
|
536
|
+
return crypto.randomUUID();
|
|
537
|
+
}
|
|
538
|
+
function generateShortId() {
|
|
539
|
+
return crypto.randomUUID().slice(0, 8);
|
|
540
|
+
}
|
|
541
|
+
function getPaginationOffset(options) {
|
|
542
|
+
const page = Math.max(1, options.page ?? 1);
|
|
543
|
+
const maxLimit = options.maxLimit ?? 100;
|
|
544
|
+
const limit = Math.min(Math.max(1, options.limit ?? 20), maxLimit);
|
|
545
|
+
const offset = (page - 1) * limit;
|
|
546
|
+
return { offset, limit };
|
|
547
|
+
}
|
|
548
|
+
function createPaginatedResult(data, total, options) {
|
|
549
|
+
const { offset, limit } = getPaginationOffset(options);
|
|
550
|
+
const page = Math.floor(offset / limit) + 1;
|
|
551
|
+
const totalPages = Math.ceil(total / limit);
|
|
552
|
+
return {
|
|
553
|
+
data,
|
|
554
|
+
pagination: {
|
|
555
|
+
page,
|
|
556
|
+
limit,
|
|
557
|
+
total,
|
|
558
|
+
totalPages,
|
|
559
|
+
hasMore: page < totalPages
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function escapeLike(value) {
|
|
564
|
+
return value.replace(/[%_\\]/g, "\\$&");
|
|
565
|
+
}
|
|
566
|
+
function buildSearchPattern(value, mode = "contains") {
|
|
567
|
+
const escaped = escapeLike(value);
|
|
568
|
+
switch (mode) {
|
|
569
|
+
case "startsWith":
|
|
570
|
+
return `${escaped}%`;
|
|
571
|
+
case "endsWith":
|
|
572
|
+
return `%${escaped}`;
|
|
573
|
+
case "contains":
|
|
574
|
+
default:
|
|
575
|
+
return `%${escaped}%`;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/index.ts
|
|
580
|
+
init_types();
|
|
581
|
+
export * from "drizzle-orm";
|
|
582
|
+
async function createDatabase(config) {
|
|
583
|
+
switch (config.type) {
|
|
584
|
+
case "postgres": {
|
|
585
|
+
const { createPostgresAdapter: createPostgresAdapter2 } = await Promise.resolve().then(() => (init_postgres(), postgres_exports));
|
|
586
|
+
return createPostgresAdapter2(config);
|
|
587
|
+
}
|
|
588
|
+
case "neon": {
|
|
589
|
+
const { createNeonAdapter: createNeonAdapter2 } = await Promise.resolve().then(() => (init_neon(), neon_exports));
|
|
590
|
+
return createNeonAdapter2(config);
|
|
591
|
+
}
|
|
592
|
+
case "d1": {
|
|
593
|
+
const { createD1Adapter: createD1Adapter2 } = await Promise.resolve().then(() => (init_d1(), d1_exports));
|
|
594
|
+
return createD1Adapter2(config);
|
|
595
|
+
}
|
|
596
|
+
default:
|
|
597
|
+
throw new DatabaseError(
|
|
598
|
+
`Unknown database type: ${config.type}`,
|
|
599
|
+
DatabaseErrorCodes.INVALID_CONFIG
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
async function createDatabaseFromUrl(connectionString, options) {
|
|
604
|
+
const url = new URL(connectionString);
|
|
605
|
+
switch (url.protocol) {
|
|
606
|
+
case "postgresql:":
|
|
607
|
+
case "postgres:": {
|
|
608
|
+
if (url.hostname.includes("neon.tech")) {
|
|
609
|
+
const { createNeonFromUrl: createNeonFromUrl2 } = await Promise.resolve().then(() => (init_neon(), neon_exports));
|
|
610
|
+
return createNeonFromUrl2(connectionString, options);
|
|
611
|
+
}
|
|
612
|
+
const { createPostgresFromUrl: createPostgresFromUrl2 } = await Promise.resolve().then(() => (init_postgres(), postgres_exports));
|
|
613
|
+
return createPostgresFromUrl2(connectionString, options);
|
|
614
|
+
}
|
|
615
|
+
default:
|
|
616
|
+
throw new DatabaseError(
|
|
617
|
+
`Unsupported database URL scheme: ${url.protocol}`,
|
|
618
|
+
DatabaseErrorCodes.INVALID_CONFIG
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
export {
|
|
623
|
+
D1Adapter,
|
|
624
|
+
DatabaseError,
|
|
625
|
+
DatabaseErrorCodes,
|
|
626
|
+
NeonAdapter,
|
|
627
|
+
PostgresAdapter,
|
|
628
|
+
buildConnectionString,
|
|
629
|
+
buildSearchPattern,
|
|
630
|
+
camelToSnake,
|
|
631
|
+
createD1Adapter,
|
|
632
|
+
createDatabase,
|
|
633
|
+
createDatabaseFromUrl,
|
|
634
|
+
createNeonAdapter,
|
|
635
|
+
createNeonFromUrl,
|
|
636
|
+
createPaginatedResult,
|
|
637
|
+
createPostgresAdapter,
|
|
638
|
+
createPostgresFromUrl,
|
|
639
|
+
escapeLike,
|
|
640
|
+
generateShortId,
|
|
641
|
+
generateUUID,
|
|
642
|
+
getPaginationOffset,
|
|
643
|
+
isRetryableError,
|
|
644
|
+
parseConnectionString,
|
|
645
|
+
retry,
|
|
646
|
+
sleep,
|
|
647
|
+
snakeToCamel,
|
|
648
|
+
transformToCamelCase,
|
|
649
|
+
transformToSnakeCase
|
|
650
|
+
};
|
|
651
|
+
//# sourceMappingURL=index.js.map
|