Files
CreaBook/node_modules/@prisma/adapter-libsql/dist/index-node.js
2026-04-05 03:08:53 +02:00

436 lines
13 KiB
JavaScript

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index-node.ts
var index_node_exports = {};
__export(index_node_exports, {
PrismaLibSql: () => PrismaLibSqlAdapterFactory
});
module.exports = __toCommonJS(index_node_exports);
// src/libsql-node.ts
var import_client = require("@libsql/client");
// src/libsql.ts
var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
var import_async_mutex = require("async-mutex");
// package.json
var name = "@prisma/adapter-libsql";
// src/conversion.ts
var import_driver_adapter_utils = require("@prisma/driver-adapter-utils");
var debug = (0, import_driver_adapter_utils.Debug)("prisma:driver-adapter:libsql:conversion");
function mapDeclType(declType) {
switch (declType.toUpperCase()) {
case "":
return null;
case "DECIMAL":
return import_driver_adapter_utils.ColumnTypeEnum.Numeric;
case "FLOAT":
return import_driver_adapter_utils.ColumnTypeEnum.Float;
case "DOUBLE":
case "DOUBLE PRECISION":
case "NUMERIC":
case "REAL":
return import_driver_adapter_utils.ColumnTypeEnum.Double;
case "TINYINT":
case "SMALLINT":
case "MEDIUMINT":
case "INT":
case "INTEGER":
case "SERIAL":
case "INT2":
return import_driver_adapter_utils.ColumnTypeEnum.Int32;
case "BIGINT":
case "UNSIGNED BIG INT":
case "INT8":
return import_driver_adapter_utils.ColumnTypeEnum.Int64;
case "DATETIME":
case "TIMESTAMP":
return import_driver_adapter_utils.ColumnTypeEnum.DateTime;
case "TIME":
return import_driver_adapter_utils.ColumnTypeEnum.Time;
case "DATE":
return import_driver_adapter_utils.ColumnTypeEnum.Date;
case "TEXT":
case "CLOB":
case "CHARACTER":
case "VARCHAR":
case "VARYING CHARACTER":
case "NCHAR":
case "NATIVE CHARACTER":
case "NVARCHAR":
return import_driver_adapter_utils.ColumnTypeEnum.Text;
case "BLOB":
return import_driver_adapter_utils.ColumnTypeEnum.Bytes;
case "BOOLEAN":
return import_driver_adapter_utils.ColumnTypeEnum.Boolean;
case "JSONB":
return import_driver_adapter_utils.ColumnTypeEnum.Json;
default:
debug("unknown decltype:", declType);
return null;
}
}
function mapDeclaredColumnTypes(columnTypes) {
const emptyIndices = /* @__PURE__ */ new Set();
const result = columnTypes.map((typeName, index) => {
const mappedType = mapDeclType(typeName);
if (mappedType === null) {
emptyIndices.add(index);
}
return mappedType;
});
return [result, emptyIndices];
}
function getColumnTypes(declaredTypes, rows) {
const [columnTypes, emptyIndices] = mapDeclaredColumnTypes(declaredTypes);
if (emptyIndices.size === 0) {
return columnTypes;
}
columnLoop: for (const columnIndex of emptyIndices) {
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
const candidateValue = rows[rowIndex][columnIndex];
if (candidateValue !== null) {
columnTypes[columnIndex] = inferColumnType(candidateValue);
continue columnLoop;
}
}
columnTypes[columnIndex] = import_driver_adapter_utils.ColumnTypeEnum.Int32;
}
return columnTypes;
}
function inferColumnType(value) {
switch (typeof value) {
case "string":
return import_driver_adapter_utils.ColumnTypeEnum.Text;
case "bigint":
return import_driver_adapter_utils.ColumnTypeEnum.Int64;
case "boolean":
return import_driver_adapter_utils.ColumnTypeEnum.Boolean;
case "number":
return import_driver_adapter_utils.ColumnTypeEnum.UnknownNumber;
case "object":
return inferObjectType(value);
default:
throw new UnexpectedTypeError(value);
}
}
function inferObjectType(value) {
if (value instanceof ArrayBuffer) {
return import_driver_adapter_utils.ColumnTypeEnum.Bytes;
}
throw new UnexpectedTypeError(value);
}
var UnexpectedTypeError = class extends Error {
name = "UnexpectedTypeError";
constructor(value) {
const type = typeof value;
const repr = type === "object" ? JSON.stringify(value) : String(value);
super(`unexpected value of type ${type}: ${repr}`);
}
};
function mapRow(row, columnTypes) {
const result = [];
for (let i = 0; i < row.length; i++) {
const value = row[i];
if (value instanceof ArrayBuffer) {
result[i] = new Uint8Array(value);
continue;
}
if (typeof value === "number" && (columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.Int32 || columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.Int64) && !Number.isInteger(value)) {
result[i] = Math.trunc(value);
continue;
}
if (["number", "bigint"].includes(typeof value) && columnTypes[i] === import_driver_adapter_utils.ColumnTypeEnum.DateTime) {
result[i] = new Date(Number(value)).toISOString();
continue;
}
if (typeof value === "bigint") {
result[i] = value.toString();
continue;
}
result[i] = value;
}
return result;
}
function mapArg(arg, argType, options) {
if (arg === null) {
return null;
}
if (typeof arg === "string" && argType.scalarType === "bigint") {
return BigInt(arg);
}
if (typeof arg === "string" && argType.scalarType === "decimal") {
return Number.parseFloat(arg);
}
if (typeof arg === "string" && argType.scalarType === "datetime") {
arg = new Date(arg);
}
if (arg instanceof Date) {
const format = options?.timestampFormat ?? "iso8601";
switch (format) {
case "unixepoch-ms":
return arg.getTime();
case "iso8601":
return arg.toISOString().replace("Z", "+00:00");
default:
throw new Error(`Unknown timestamp format: ${format}`);
}
}
if (typeof arg === "string" && argType.scalarType === "bytes") {
return Buffer.from(arg, "base64");
}
return arg;
}
// src/errors.ts
var SQLITE_BUSY = 5;
var PRIMARY_ERROR_CODE_MASK = 255;
function convertDriverError(error) {
if (isDriverError(error)) {
return {
originalCode: error.rawCode?.toString(),
originalMessage: error.message,
...mapDriverError(error)
};
}
throw error;
}
function mapDriverError(error) {
const rawCode = error.rawCode ?? error.cause?.["rawCode"] ?? 1;
switch (rawCode) {
case 2067:
case 1555: {
const fields = error.message.split("constraint failed: ").at(1)?.split(", ").map((field) => field.split(".").pop());
return {
kind: "UniqueConstraintViolation",
constraint: fields !== void 0 ? { fields } : void 0
};
}
case 1299: {
const fields = error.message.split("constraint failed: ").at(1)?.split(", ").map((field) => field.split(".").pop());
return {
kind: "NullConstraintViolation",
constraint: fields !== void 0 ? { fields } : void 0
};
}
case 787:
case 1811:
return {
kind: "ForeignKeyConstraintViolation",
constraint: { foreignKey: {} }
};
default:
if (rawCode && (rawCode & PRIMARY_ERROR_CODE_MASK) === SQLITE_BUSY) {
return {
kind: "SocketTimeout"
};
} else if (error.message.startsWith("no such table")) {
return {
kind: "TableDoesNotExist",
table: error.message.split(": ").at(1)
};
} else if (error.message.startsWith("no such column")) {
return {
kind: "ColumnNotFound",
column: error.message.split(": ").at(1)
};
} else if (error.message.includes("has no column named ")) {
return {
kind: "ColumnNotFound",
column: error.message.split("has no column named ").at(1)
};
}
return {
kind: "sqlite",
extendedCode: rawCode,
message: error.message
};
}
}
function isDriverError(error) {
return typeof error.code === "string" && typeof error.message === "string" && (typeof error.rawCode === "number" || error.rawCode === void 0);
}
// src/libsql.ts
var debug2 = (0, import_driver_adapter_utils2.Debug)("prisma:driver-adapter:libsql");
var LOCK_TAG = Symbol();
var LibSqlQueryable = class {
constructor(client, adapterOptions) {
this.client = client;
this.adapterOptions = adapterOptions;
}
provider = "sqlite";
adapterName = name;
[LOCK_TAG] = new import_async_mutex.Mutex();
/**
* Execute a query given as SQL, interpolating the given parameters.
*/
async queryRaw(query) {
const tag = "[js::query_raw]";
debug2(`${tag} %O`, query);
const { columns, rows, columnTypes: declaredColumnTypes } = await this.performIO(query);
const columnTypes = getColumnTypes(declaredColumnTypes, rows);
return {
columnNames: columns,
columnTypes,
rows: rows.map((row) => mapRow(row, columnTypes))
};
}
/**
* Execute a query given as SQL, interpolating the given parameters and
* returning the number of affected rows.
* Note: Queryable expects a u64, but napi.rs only supports u32.
*/
async executeRaw(query) {
const tag = "[js::execute_raw]";
debug2(`${tag} %O`, query);
return (await this.performIO(query)).rowsAffected ?? 0;
}
/**
* Run a query against the database, returning the result set.
* Should the query fail due to a connection error, the connection is
* marked as unhealthy.
*/
async performIO(query) {
const release = await this[LOCK_TAG].acquire();
try {
const result = await this.client.execute({
sql: query.sql,
args: query.args.map((arg, i) => mapArg(arg, query.argTypes[i], this.adapterOptions))
});
return result;
} catch (e) {
this.onError(e);
} finally {
release();
}
}
onError(error) {
debug2("Error in performIO: %O", error);
throw new import_driver_adapter_utils2.DriverAdapterError(convertDriverError(error));
}
};
var LibSqlTransaction = class extends LibSqlQueryable {
constructor(client, options, adapterOptions, unlockParent) {
super(client, adapterOptions);
this.options = options;
this.#unlockParent = unlockParent;
}
#unlockParent;
async commit() {
debug2(`[js::commit]`);
try {
await this.client.commit();
} finally {
this.#unlockParent();
}
}
async rollback() {
debug2(`[js::rollback]`);
try {
await this.client.rollback();
} catch (error) {
debug2("error in rollback:", error);
} finally {
this.#unlockParent();
}
}
async createSavepoint(name2) {
await this.executeRaw({ sql: `SAVEPOINT ${name2}`, args: [], argTypes: [] });
}
async rollbackToSavepoint(name2) {
await this.executeRaw({ sql: `ROLLBACK TO ${name2}`, args: [], argTypes: [] });
}
async releaseSavepoint(name2) {
await this.executeRaw({ sql: `RELEASE SAVEPOINT ${name2}`, args: [], argTypes: [] });
}
};
var PrismaLibSqlAdapter = class extends LibSqlQueryable {
constructor(client, adapterOptions) {
super(client, adapterOptions);
}
async executeScript(script) {
const release = await this[LOCK_TAG].acquire();
try {
await this.client.executeMultiple(script);
} catch (e) {
this.onError(e);
} finally {
release();
}
}
async startTransaction(isolationLevel) {
if (isolationLevel && isolationLevel !== "SERIALIZABLE") {
throw new import_driver_adapter_utils2.DriverAdapterError({
kind: "InvalidIsolationLevel",
level: isolationLevel
});
}
const options = {
usePhantomQuery: true
};
const tag = "[js::startTransaction]";
debug2("%s options: %O", tag, options);
const release = await this[LOCK_TAG].acquire();
try {
const tx = await this.client.transaction("deferred");
return new LibSqlTransaction(tx, options, this.adapterOptions, release);
} catch (e) {
release();
this.onError(e);
}
}
dispose() {
this.client.close();
return Promise.resolve();
}
};
var PrismaLibSqlAdapterFactoryBase = class {
provider = "sqlite";
adapterName = name;
#config;
#options;
constructor(config, options) {
this.#config = config;
this.#options = options;
}
connect() {
return Promise.resolve(new PrismaLibSqlAdapter(this.createClient(this.#config), this.#options));
}
connectToShadowDb() {
return Promise.resolve(
new PrismaLibSqlAdapter(this.createClient({ ...this.#config, url: ":memory:" }), this.#options)
);
}
};
// src/libsql-node.ts
var PrismaLibSqlAdapterFactory = class extends PrismaLibSqlAdapterFactoryBase {
createClient(config) {
return (0, import_client.createClient)(config);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
PrismaLibSql
});