@pgxsinkit/pgwasm
Version:
262 lines (254 loc) • 9.58 kB
JavaScript
// @bun
import {
PgwasmError2
} from "../chunk-cpsnmzrf.js";
import {
DATE,
TIMESTAMP,
TIMESTAMPTZ,
INTERVAL
} from "../chunk-d82gg1hx.js";
// packages/pgwasm/src/drizzle/driver.ts
import { entityKind as entityKind2 } from "drizzle-orm/entity";
import { DefaultLogger } from "drizzle-orm/logger";
import { PgAsyncDatabase } from "drizzle-orm/pg-core/async/db";
import { PgDialect } from "drizzle-orm/pg-core/dialect";
// packages/pgwasm/src/drizzle/codecs.ts
import { makePgArray, parsePgArray } from "drizzle-orm/pg-core/array";
import {
arrayCompatNormalize,
castToText,
castToTextArr,
genericPgCodecs,
parseGeometryTuple,
parseGeometryXY,
parsePgArrayAndNormalize,
refineGenericPgCodecs,
textToDate,
textToDateWithTz
} from "drizzle-orm/pg-core/codecs";
import { base64ToUint8Array } from "drizzle-orm/utils";
var drizzleParsers = {
[TIMESTAMP]: (value) => value,
[TIMESTAMPTZ]: (value) => value,
[INTERVAL]: (value) => value,
[DATE]: (value) => value,
1231: (value) => value,
1115: (value) => value,
1185: (value) => value,
1187: (value) => value,
1182: (value) => value
};
var hasBuffer = typeof Buffer !== "undefined";
var pgwasmCodecs = refineGenericPgCodecs({
bigint: {
cast: castToText,
castArray: castToTextArr,
normalize: BigInt,
normalizeArray: arrayCompatNormalize(BigInt)
},
"bigint:string": { cast: castToText, castArray: castToTextArr },
"bigint:number": { cast: castToText, castArray: castToTextArr },
bigserial: {
normalize: BigInt,
normalizeArray: arrayCompatNormalize(BigInt),
cast: castToText,
castArray: castToTextArr
},
"bigserial:number": { cast: castToText, castArray: castToTextArr },
bytea: hasBuffer ? {
normalizeInJson: genericPgCodecs.bytea?.normalizeInJson,
normalizeArrayInJson: genericPgCodecs.bytea?.normalizeArrayInJson,
normalize: (value) => Buffer.from(value),
normalizeArray: arrayCompatNormalize((value) => Buffer.from(value))
} : {
normalizeInJson: base64ToUint8Array,
normalizeArrayInJson: arrayCompatNormalize(base64ToUint8Array)
},
interval: { castArray: castToTextArr },
date: { castArray: castToTextArr, normalize: textToDate, normalizeArray: arrayCompatNormalize(textToDate) },
"date:string": { castArray: castToTextArr },
timestamp: {
castArray: castToTextArr,
normalize: textToDateWithTz,
normalizeArray: arrayCompatNormalize(textToDateWithTz)
},
timestamptz: { castArray: castToTextArr, normalize: textToDate, normalizeArray: arrayCompatNormalize(textToDate) },
"timestamp:string": { castArray: castToTextArr },
"timestamptz:string": { castArray: castToTextArr },
json: { normalizeParam: (value) => typeof value === "object" ? value : JSON.stringify(value) },
jsonb: { normalizeParam: (value) => typeof value === "object" ? value : JSON.stringify(value) },
"geometry(point)": {
normalizeArray: parsePgArrayAndNormalize(parseGeometryXY),
castParam: (name) => `${name}::geometry`,
castArrayParam: (name, _column, dimensions) => `${name}::geometry${"[]".repeat(dimensions)}`,
normalizeParamArray: makePgArray
},
"geometry(point):tuple": {
normalizeArray: parsePgArrayAndNormalize(parseGeometryTuple),
castParam: (name) => `${name}::geometry`,
castArrayParam: (name, _column, dimensions) => `${name}::geometry${"[]".repeat(dimensions)}`,
normalizeParamArray: makePgArray
},
halfvec: {
castParam: (name) => `${name}::halfvec`,
castArrayParam: (name, _column, dimensions) => `${name}::halfvec${"[]".repeat(dimensions)}`,
normalizeParamArray: makePgArray
},
vector: {
castParam: (name) => `${name}::vector`,
castArrayParam: (name, _column, dimensions) => `${name}::vector${"[]".repeat(dimensions)}`,
normalizeParamArray: makePgArray
},
sparsevec: {
normalizeArray: parsePgArray,
castParam: (name) => `${name}::sparsevec`,
castArrayParam: (name, _column, dimensions) => `${name}::sparsevec${"[]".repeat(dimensions)}`,
normalizeParamArray: makePgArray
}
});
// packages/pgwasm/src/drizzle/session.ts
import { NoopCache } from "drizzle-orm/cache/core/cache";
import { entityKind } from "drizzle-orm/entity";
import { NoopLogger } from "drizzle-orm/logger";
import { PgAsyncPreparedQuery, PgAsyncSession, PgAsyncTransaction } from "drizzle-orm/pg-core/async/session";
import { sql } from "drizzle-orm/sql/sql";
class PgwasmSession extends PgAsyncSession {
static [entityKind] = "PgwasmSession";
#client;
#relations;
#options;
#logger;
#cache;
constructor(client, dialect, relations, options = {}) {
super(dialect);
this.#client = client;
this.#relations = relations;
this.#options = options;
this.#logger = options.logger ?? new NoopLogger;
this.#cache = options.cache ?? new NoopCache;
}
prepareQuery(query, mode, _name, mapper, queryMetadata, cacheConfig) {
const executor = async (params) => {
const result = await this.#client.query(query.sql, params, {
rowMode: mode === "arrays" ? "array" : "object",
parsers: drizzleParsers
});
return mode === "raw" ? result : result.rows;
};
return new PgAsyncPreparedQuery(executor, query, mapper, mode, this.#logger, this.#cache, queryMetadata, cacheConfig);
}
async transaction(transaction, config) {
const client = this.#client;
if (client.transaction === undefined) {
throw new Error("A transaction's session cannot begin another transaction; nest with tx.transaction().");
}
return await client.transaction(async (handle) => {
const session = new PgwasmSession(handle, this.dialect, this.#relations, this.#options);
const tx = new PgwasmTransaction(this.dialect, session, this.#relations, undefined, false);
if (config)
await tx.setTransaction(config);
return await transaction(tx);
});
}
}
class PgwasmTransaction extends PgAsyncTransaction {
static [entityKind] = "PgwasmTransaction";
#dialect;
#session;
constructor(dialect, session, relations, nestedIndex, parseRqbJson) {
super(dialect, session, relations, nestedIndex, parseRqbJson);
this.#dialect = dialect;
this.#session = session;
}
async transaction(transaction) {
const savepointName = `sp${this.nestedIndex + 1}`;
const tx = new PgwasmTransaction(this.#dialect, this.#session, this._.relations, this.nestedIndex + 1, false);
await tx.execute(sql.raw(`savepoint ${savepointName}`));
try {
const result = await transaction(tx);
await tx.execute(sql.raw(`release savepoint ${savepointName}`));
return result;
} catch (error) {
await tx.execute(sql.raw(`rollback to savepoint ${savepointName}`));
throw error;
}
}
}
// packages/pgwasm/src/drizzle/driver.ts
class PgwasmDatabase extends PgAsyncDatabase {
static [entityKind2] = "PgwasmDatabase";
}
function jitMappersUsable(requested) {
if (requested !== true)
return false;
try {
const identity = new Function("input", '"use strict"; return input;');
return identity(true) === true;
} catch {
return false;
}
}
function construct(client, config = {}) {
const dialect = new PgDialect({
useJitMappers: jitMappersUsable(config.jit),
codecs: config.codecs ?? pgwasmCodecs
});
const logger = config.logger === true ? new DefaultLogger : config.logger === false ? undefined : config.logger;
const relations = config.relations ?? {};
const session = new PgwasmSession(client, dialect, relations, {
...logger ? { logger } : {},
...config.cache ? { cache: config.cache } : {}
});
const db = new PgwasmDatabase(dialect, session, relations);
const cache = config.cache;
if (cache)
db.$cache = { invalidate: (params) => cache.onMutate(params) };
return Object.assign(db, { $client: client });
}
class UnsupportedDrizzleConfigError extends PgwasmError2 {
name = "UnsupportedDrizzleConfigError";
form;
constructor(form) {
const given = form === "connection" ? "drizzle({ connection })" : form === "connection string" ? "drizzle(connectionString)" : "a drizzle() call without a pgwasm database";
super(`@pgxsinkit/pgwasm/drizzle does not open its own database, so ${given} is not supported: create the ` + "database with createPgwasm() and pass it as drizzle(pg, config) or drizzle({ client: pg, ...config }).");
this.form = form;
}
}
function isPgwasm(value) {
return typeof value === "object" && value !== null && typeof value.query === "function";
}
function drizzle(clientOrConfig, config) {
const given = clientOrConfig;
if (isPgwasm(given))
return construct(given, config);
if (typeof given === "string")
throw new UnsupportedDrizzleConfigError("connection string");
if (typeof given === "object" && given !== null) {
const { client, ...rest } = given;
if (isPgwasm(client))
return construct(client, rest);
if (client === undefined && "connection" in given)
throw new UnsupportedDrizzleConfigError("connection");
}
throw new UnsupportedDrizzleConfigError("no client");
}
var unavailable = {
query: () => {
throw new Error("drizzle.mock() has no database: build queries with it, run them elsewhere.");
}
};
drizzle.mock = function mock(config) {
const db = construct(unavailable, config);
return Object.assign(db, { $client: "$client is not available on drizzle.mock()" });
};
export {
PgwasmDatabase,
PgwasmSession,
PgwasmTransaction,
UnsupportedDrizzleConfigError,
drizzle,
drizzleParsers,
pgwasmCodecs
};
//# debugId=8E6C560DBCD746D464756E2164756E21