@prisma/adapter-better-sqlite3 6.7.0-dev.6

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/dist/index.js ADDED
@@ -0,0 +1,619 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name2 in all)
10
+ __defProp(target, name2, { get: all[name2], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ PrismaBetterSQLite3: () => PrismaBetterSQLite3AdapterFactory
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/better-sqlite3.ts
38
+ var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
39
+
40
+ // ../../node_modules/.pnpm/async-mutex@0.5.0/node_modules/async-mutex/index.mjs
41
+ var E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
42
+ var E_ALREADY_LOCKED = new Error("mutex already locked");
43
+ var E_CANCELED = new Error("request for lock canceled");
44
+ var __awaiter$2 = function(thisArg, _arguments, P, generator) {
45
+ function adopt(value) {
46
+ return value instanceof P ? value : new P(function(resolve) {
47
+ resolve(value);
48
+ });
49
+ }
50
+ return new (P || (P = Promise))(function(resolve, reject) {
51
+ function fulfilled(value) {
52
+ try {
53
+ step(generator.next(value));
54
+ } catch (e) {
55
+ reject(e);
56
+ }
57
+ }
58
+ function rejected(value) {
59
+ try {
60
+ step(generator["throw"](value));
61
+ } catch (e) {
62
+ reject(e);
63
+ }
64
+ }
65
+ function step(result) {
66
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
67
+ }
68
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
69
+ });
70
+ };
71
+ var Semaphore = class {
72
+ constructor(_value, _cancelError = E_CANCELED) {
73
+ this._value = _value;
74
+ this._cancelError = _cancelError;
75
+ this._queue = [];
76
+ this._weightedWaiters = [];
77
+ }
78
+ acquire(weight = 1, priority = 0) {
79
+ if (weight <= 0)
80
+ throw new Error(`invalid weight ${weight}: must be positive`);
81
+ return new Promise((resolve, reject) => {
82
+ const task = { resolve, reject, weight, priority };
83
+ const i = findIndexFromEnd(this._queue, (other) => priority <= other.priority);
84
+ if (i === -1 && weight <= this._value) {
85
+ this._dispatchItem(task);
86
+ } else {
87
+ this._queue.splice(i + 1, 0, task);
88
+ }
89
+ });
90
+ }
91
+ runExclusive(callback_1) {
92
+ return __awaiter$2(this, arguments, void 0, function* (callback, weight = 1, priority = 0) {
93
+ const [value, release] = yield this.acquire(weight, priority);
94
+ try {
95
+ return yield callback(value);
96
+ } finally {
97
+ release();
98
+ }
99
+ });
100
+ }
101
+ waitForUnlock(weight = 1, priority = 0) {
102
+ if (weight <= 0)
103
+ throw new Error(`invalid weight ${weight}: must be positive`);
104
+ if (this._couldLockImmediately(weight, priority)) {
105
+ return Promise.resolve();
106
+ } else {
107
+ return new Promise((resolve) => {
108
+ if (!this._weightedWaiters[weight - 1])
109
+ this._weightedWaiters[weight - 1] = [];
110
+ insertSorted(this._weightedWaiters[weight - 1], { resolve, priority });
111
+ });
112
+ }
113
+ }
114
+ isLocked() {
115
+ return this._value <= 0;
116
+ }
117
+ getValue() {
118
+ return this._value;
119
+ }
120
+ setValue(value) {
121
+ this._value = value;
122
+ this._dispatchQueue();
123
+ }
124
+ release(weight = 1) {
125
+ if (weight <= 0)
126
+ throw new Error(`invalid weight ${weight}: must be positive`);
127
+ this._value += weight;
128
+ this._dispatchQueue();
129
+ }
130
+ cancel() {
131
+ this._queue.forEach((entry) => entry.reject(this._cancelError));
132
+ this._queue = [];
133
+ }
134
+ _dispatchQueue() {
135
+ this._drainUnlockWaiters();
136
+ while (this._queue.length > 0 && this._queue[0].weight <= this._value) {
137
+ this._dispatchItem(this._queue.shift());
138
+ this._drainUnlockWaiters();
139
+ }
140
+ }
141
+ _dispatchItem(item) {
142
+ const previousValue = this._value;
143
+ this._value -= item.weight;
144
+ item.resolve([previousValue, this._newReleaser(item.weight)]);
145
+ }
146
+ _newReleaser(weight) {
147
+ let called = false;
148
+ return () => {
149
+ if (called)
150
+ return;
151
+ called = true;
152
+ this.release(weight);
153
+ };
154
+ }
155
+ _drainUnlockWaiters() {
156
+ if (this._queue.length === 0) {
157
+ for (let weight = this._value; weight > 0; weight--) {
158
+ const waiters = this._weightedWaiters[weight - 1];
159
+ if (!waiters)
160
+ continue;
161
+ waiters.forEach((waiter) => waiter.resolve());
162
+ this._weightedWaiters[weight - 1] = [];
163
+ }
164
+ } else {
165
+ const queuedPriority = this._queue[0].priority;
166
+ for (let weight = this._value; weight > 0; weight--) {
167
+ const waiters = this._weightedWaiters[weight - 1];
168
+ if (!waiters)
169
+ continue;
170
+ const i = waiters.findIndex((waiter) => waiter.priority <= queuedPriority);
171
+ (i === -1 ? waiters : waiters.splice(0, i)).forEach((waiter) => waiter.resolve());
172
+ }
173
+ }
174
+ }
175
+ _couldLockImmediately(weight, priority) {
176
+ return (this._queue.length === 0 || this._queue[0].priority < priority) && weight <= this._value;
177
+ }
178
+ };
179
+ function insertSorted(a, v) {
180
+ const i = findIndexFromEnd(a, (other) => v.priority <= other.priority);
181
+ a.splice(i + 1, 0, v);
182
+ }
183
+ function findIndexFromEnd(a, predicate) {
184
+ for (let i = a.length - 1; i >= 0; i--) {
185
+ if (predicate(a[i])) {
186
+ return i;
187
+ }
188
+ }
189
+ return -1;
190
+ }
191
+ var __awaiter$1 = function(thisArg, _arguments, P, generator) {
192
+ function adopt(value) {
193
+ return value instanceof P ? value : new P(function(resolve) {
194
+ resolve(value);
195
+ });
196
+ }
197
+ return new (P || (P = Promise))(function(resolve, reject) {
198
+ function fulfilled(value) {
199
+ try {
200
+ step(generator.next(value));
201
+ } catch (e) {
202
+ reject(e);
203
+ }
204
+ }
205
+ function rejected(value) {
206
+ try {
207
+ step(generator["throw"](value));
208
+ } catch (e) {
209
+ reject(e);
210
+ }
211
+ }
212
+ function step(result) {
213
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
214
+ }
215
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
216
+ });
217
+ };
218
+ var Mutex = class {
219
+ constructor(cancelError) {
220
+ this._semaphore = new Semaphore(1, cancelError);
221
+ }
222
+ acquire() {
223
+ return __awaiter$1(this, arguments, void 0, function* (priority = 0) {
224
+ const [, releaser] = yield this._semaphore.acquire(1, priority);
225
+ return releaser;
226
+ });
227
+ }
228
+ runExclusive(callback, priority = 0) {
229
+ return this._semaphore.runExclusive(() => callback(), 1, priority);
230
+ }
231
+ isLocked() {
232
+ return this._semaphore.isLocked();
233
+ }
234
+ waitForUnlock(priority = 0) {
235
+ return this._semaphore.waitForUnlock(1, priority);
236
+ }
237
+ release() {
238
+ if (this._semaphore.isLocked())
239
+ this._semaphore.release();
240
+ }
241
+ cancel() {
242
+ return this._semaphore.cancel();
243
+ }
244
+ };
245
+
246
+ // src/better-sqlite3.ts
247
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"));
248
+
249
+ // package.json
250
+ var name = "@prisma/adapter-better-sqlite3";
251
+
252
+ // src/conversion.ts
253
+ var import_driver_adapter_utils = require("@prisma/driver-adapter-utils");
254
+ var debug = (0, import_driver_adapter_utils.Debug)("prisma:driver-adapter:better-sqlite3:conversion");
255
+ function mapDeclType(declType) {
256
+ if (declType === null) {
257
+ return null;
258
+ }
259
+ switch (declType.toUpperCase()) {
260
+ case "":
261
+ return null;
262
+ case "DECIMAL":
263
+ return import_driver_adapter_utils.ColumnTypeEnum.Numeric;
264
+ case "FLOAT":
265
+ return import_driver_adapter_utils.ColumnTypeEnum.Float;
266
+ case "DOUBLE":
267
+ case "DOUBLE PRECISION":
268
+ case "NUMERIC":
269
+ case "REAL":
270
+ return import_driver_adapter_utils.ColumnTypeEnum.Double;
271
+ case "TINYINT":
272
+ case "SMALLINT":
273
+ case "MEDIUMINT":
274
+ case "INT":
275
+ case "INTEGER":
276
+ case "SERIAL":
277
+ case "INT2":
278
+ return import_driver_adapter_utils.ColumnTypeEnum.Int32;
279
+ case "BIGINT":
280
+ case "UNSIGNED BIG INT":
281
+ case "INT8":
282
+ return import_driver_adapter_utils.ColumnTypeEnum.Int64;
283
+ case "DATETIME":
284
+ case "TIMESTAMP":
285
+ return import_driver_adapter_utils.ColumnTypeEnum.DateTime;
286
+ case "TIME":
287
+ return import_driver_adapter_utils.ColumnTypeEnum.Time;
288
+ case "DATE":
289
+ return import_driver_adapter_utils.ColumnTypeEnum.Date;
290
+ case "TEXT":
291
+ case "CLOB":
292
+ case "CHARACTER":
293
+ case "VARCHAR":
294
+ case "VARYING CHARACTER":
295
+ case "NCHAR":
296
+ case "NATIVE CHARACTER":
297
+ case "NVARCHAR":
298
+ return import_driver_adapter_utils.ColumnTypeEnum.Text;
299
+ case "BLOB":
300
+ return import_driver_adapter_utils.ColumnTypeEnum.Bytes;
301
+ case "BOOLEAN":
302
+ return import_driver_adapter_utils.ColumnTypeEnum.Boolean;
303
+ case "JSONB":
304
+ return import_driver_adapter_utils.ColumnTypeEnum.Json;
305
+ default:
306
+ debug("unknown decltype:", declType);
307
+ return null;
308
+ }
309
+ }
310
+ function mapDeclaredColumnTypes(columnTypes) {
311
+ const emptyIndices = /* @__PURE__ */ new Set();
312
+ const result = columnTypes.map((typeName, index) => {
313
+ const mappedType = mapDeclType(typeName);
314
+ if (mappedType === null) {
315
+ emptyIndices.add(index);
316
+ }
317
+ return mappedType;
318
+ });
319
+ return [result, emptyIndices];
320
+ }
321
+ function getColumnTypes(declaredTypes, rows) {
322
+ const [columnTypes, emptyIndices] = mapDeclaredColumnTypes(declaredTypes);
323
+ if (emptyIndices.size === 0) {
324
+ return columnTypes;
325
+ }
326
+ columnLoop: for (const columnIndex of emptyIndices) {
327
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
328
+ const candidateValue = rows[rowIndex][columnIndex];
329
+ if (candidateValue !== null) {
330
+ columnTypes[columnIndex] = inferColumnType(candidateValue);
331
+ continue columnLoop;
332
+ }
333
+ }
334
+ columnTypes[columnIndex] = import_driver_adapter_utils.ColumnTypeEnum.Int32;
335
+ }
336
+ return columnTypes;
337
+ }
338
+ function inferColumnType(value) {
339
+ switch (typeof value) {
340
+ case "string":
341
+ return import_driver_adapter_utils.ColumnTypeEnum.Text;
342
+ case "bigint":
343
+ return import_driver_adapter_utils.ColumnTypeEnum.Int64;
344
+ case "boolean":
345
+ return import_driver_adapter_utils.ColumnTypeEnum.Boolean;
346
+ case "number":
347
+ return import_driver_adapter_utils.ColumnTypeEnum.UnknownNumber;
348
+ case "object":
349
+ return inferObjectType(value);
350
+ default:
351
+ throw new UnexpectedTypeError(value);
352
+ }
353
+ }
354
+ function inferObjectType(value) {
355
+ if (value instanceof ArrayBuffer) {
356
+ return import_driver_adapter_utils.ColumnTypeEnum.Bytes;
357
+ }
358
+ throw new UnexpectedTypeError(value);
359
+ }
360
+ var UnexpectedTypeError = class extends Error {
361
+ name = "UnexpectedTypeError";
362
+ constructor(value) {
363
+ const type = typeof value;
364
+ const repr = type === "object" ? JSON.stringify(value) : String(value);
365
+ super(`unexpected value of type ${type}: ${repr}`);
366
+ }
367
+ };
368
+ function mapRow(row, columnTypes) {
369
+ const result = Array.from(row);
370
+ for (let i = 0; i < result.length; i++) {
371
+ const value = result[i];
372
+ if (value instanceof ArrayBuffer || value instanceof Buffer) {
373
+ result[i] = Array.from(new Uint8Array(value));
374
+ continue;
375
+ }
376
+ if (typeof value === "number" && (columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.Int32 || columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.Int64) && !Number.isInteger(value)) {
377
+ result[i] = Math.trunc(value);
378
+ continue;
379
+ }
380
+ if (["number", "bigint"].includes(typeof value) && columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.DateTime) {
381
+ result[i] = new Date(Number(value)).toISOString();
382
+ continue;
383
+ }
384
+ if (typeof value === "bigint") {
385
+ result[i] = value.toString();
386
+ continue;
387
+ }
388
+ }
389
+ return result;
390
+ }
391
+ function mapQueryArgs(args, argTypes) {
392
+ return args.map((arg, i) => {
393
+ const argType = argTypes[i];
394
+ if (argType === "Int32") {
395
+ return Number.parseInt(arg);
396
+ }
397
+ if (argType === "Float" || argType === "Double") {
398
+ return Number.parseFloat(arg);
399
+ }
400
+ if (typeof arg === "boolean") {
401
+ return arg ? 1 : 0;
402
+ }
403
+ if (arg instanceof Date) {
404
+ return arg.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "");
405
+ }
406
+ if (arg instanceof Uint8Array) {
407
+ return Buffer.from(arg);
408
+ }
409
+ return arg;
410
+ });
411
+ }
412
+
413
+ // src/errors.ts
414
+ function convertDriverError(error) {
415
+ if (typeof error.code !== "string" || typeof error.message !== "string") {
416
+ throw error;
417
+ }
418
+ switch (error.code) {
419
+ case "SQLITE_BUSY":
420
+ return {
421
+ kind: "SocketTimeout"
422
+ };
423
+ case "SQLITE_CONSTRAINT_UNIQUE":
424
+ case "SQLITE_CONSTRAINT_PRIMARYKEY":
425
+ return {
426
+ kind: "UniqueConstraintViolation",
427
+ fields: error.message.split("constraint failed: ").at(1)?.split(", ").map((field) => field.split(".").pop()) ?? []
428
+ };
429
+ case "SQLITE_CONSTRAINT_NOTNULL":
430
+ return {
431
+ kind: "NullConstraintViolation",
432
+ fields: error.message.split("constraint failed: ").at(1)?.split(", ").map((field) => field.split(".").pop()) ?? []
433
+ };
434
+ case "SQLITE_CONSTRAINT_FOREIGNKEY":
435
+ case "SQLITE_CONSTRAINT_TRIGGER":
436
+ return {
437
+ kind: "ForeignKeyConstraintViolation",
438
+ constraint: { foreignKey: {} }
439
+ };
440
+ default:
441
+ if (error.message.startsWith("no such table")) {
442
+ return {
443
+ kind: "TableDoesNotExist",
444
+ table: error.message.split(": ").pop()
445
+ };
446
+ } else if (error.message.startsWith("no such column")) {
447
+ return {
448
+ kind: "ColumnNotFound",
449
+ column: error.message.split(": ").pop()
450
+ };
451
+ } else if (error.message.includes("has no column named ")) {
452
+ return {
453
+ kind: "ColumnNotFound",
454
+ column: error.message.split("has no column named ").pop()
455
+ };
456
+ }
457
+ throw error;
458
+ }
459
+ }
460
+
461
+ // src/better-sqlite3.ts
462
+ var debug2 = (0, import_driver_adapter_utils2.Debug)("prisma:driver-adapter:better-sqlite3");
463
+ var LOCK_TAG = Symbol();
464
+ var BetterSQLite3Queryable = class {
465
+ constructor(client) {
466
+ this.client = client;
467
+ }
468
+ provider = "sqlite";
469
+ adapterName = name;
470
+ /**
471
+ * Execute a query given as SQL, interpolating the given parameters.
472
+ */
473
+ async queryRaw(query) {
474
+ const tag = "[js::queryRaw]";
475
+ debug2(`${tag} %O`, query);
476
+ const { columnNames, declaredTypes, values } = await this.performIO(query);
477
+ const rows = values;
478
+ const columnTypes = getColumnTypes(declaredTypes, rows);
479
+ return {
480
+ columnNames,
481
+ columnTypes,
482
+ rows: rows.map((row) => mapRow(row, columnTypes))
483
+ };
484
+ }
485
+ /**
486
+ * Execute a query given as SQL, interpolating the given parameters and
487
+ * returning the number of affected rows.
488
+ * Note: Queryable expects a u64, but napi.rs only supports u32.
489
+ */
490
+ async executeRaw(query) {
491
+ const tag = "[js::executeRaw]";
492
+ debug2(`${tag} %O`, query);
493
+ return (await this.executeIO(query)).changes;
494
+ }
495
+ /**
496
+ * Run a query against the database, returning the result set.
497
+ * Should the query fail due to a connection error, the connection is
498
+ * marked as unhealthy.
499
+ */
500
+ executeIO(query) {
501
+ try {
502
+ const stmt = this.client.prepare(query.sql).bind(mapQueryArgs(query.args, query.argTypes));
503
+ const result = stmt.run();
504
+ return Promise.resolve(result);
505
+ } catch (e) {
506
+ this.onError(e);
507
+ }
508
+ }
509
+ /**
510
+ * Run a query against the database, returning the result set.
511
+ * Should the query fail due to a connection error, the connection is
512
+ * marked as unhealthy.
513
+ */
514
+ performIO(query) {
515
+ try {
516
+ const stmt = this.client.prepare(query.sql).bind(mapQueryArgs(query.args, query.argTypes));
517
+ if (!stmt.reader) {
518
+ stmt.run();
519
+ return Promise.resolve({
520
+ columnNames: [],
521
+ declaredTypes: [],
522
+ values: []
523
+ });
524
+ }
525
+ const columns = stmt.columns();
526
+ const resultSet = {
527
+ declaredTypes: columns.map((column) => column.type),
528
+ columnNames: columns.map((column) => column.name),
529
+ values: stmt.raw().all()
530
+ };
531
+ return Promise.resolve(resultSet);
532
+ } catch (e) {
533
+ this.onError(e);
534
+ }
535
+ }
536
+ onError(error) {
537
+ debug2("Error in performIO: %O", error);
538
+ throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
539
+ }
540
+ };
541
+ var BetterSQLite3Transaction = class extends BetterSQLite3Queryable {
542
+ constructor(client, options, unlockParent) {
543
+ super(client);
544
+ this.options = options;
545
+ this.unlockParent = unlockParent;
546
+ }
547
+ commit() {
548
+ debug2(`[js::commit]`);
549
+ this.unlockParent();
550
+ return Promise.resolve();
551
+ }
552
+ rollback() {
553
+ debug2(`[js::rollback]`);
554
+ this.unlockParent();
555
+ return Promise.resolve();
556
+ }
557
+ };
558
+ var PrismaBetterSQLite3Adapter = class extends BetterSQLite3Queryable {
559
+ [LOCK_TAG] = new Mutex();
560
+ constructor(client) {
561
+ super(client);
562
+ }
563
+ executeScript(script) {
564
+ try {
565
+ this.client.exec(script);
566
+ } catch (e) {
567
+ this.onError(e);
568
+ }
569
+ return Promise.resolve();
570
+ }
571
+ async startTransaction(isolationLevel) {
572
+ if (isolationLevel && isolationLevel !== "SERIALIZABLE") {
573
+ throw new import_driver_adapter_utils2.DriverAdapterError({
574
+ kind: "InvalidIsolationLevel",
575
+ level: isolationLevel
576
+ });
577
+ }
578
+ const options = {
579
+ usePhantomQuery: false
580
+ };
581
+ const tag = "[js::startTransaction]";
582
+ debug2("%s options: %O", tag, options);
583
+ try {
584
+ const release = await this[LOCK_TAG].acquire();
585
+ this.client.prepare("BEGIN").run();
586
+ return new BetterSQLite3Transaction(this.client, options, release);
587
+ } catch (e) {
588
+ this.onError(e);
589
+ }
590
+ }
591
+ dispose() {
592
+ this.client.close();
593
+ return Promise.resolve();
594
+ }
595
+ };
596
+ var PrismaBetterSQLite3AdapterFactory = class {
597
+ constructor(config) {
598
+ this.config = config;
599
+ }
600
+ provider = "sqlite";
601
+ adapterName = name;
602
+ connect() {
603
+ return Promise.resolve(new PrismaBetterSQLite3Adapter(createBetterSQLite3Client(this.config)));
604
+ }
605
+ connectToShadowDb() {
606
+ const url = this.config.shadowDatabaseURL ?? ":memory:";
607
+ return Promise.resolve(new PrismaBetterSQLite3Adapter(createBetterSQLite3Client({ ...this.config, url })));
608
+ }
609
+ };
610
+ function createBetterSQLite3Client(input) {
611
+ const { url, ...config } = input;
612
+ const db = new import_better_sqlite3.default(url, config);
613
+ db.defaultSafeIntegers(true);
614
+ return db;
615
+ }
616
+ // Annotate the CommonJS export names for ESM import in node:
617
+ 0 && (module.exports = {
618
+ PrismaBetterSQLite3
619
+ });