penambahan web socket

This commit is contained in:
2025-09-18 19:01:22 +07:00
parent 1d053646a9
commit d7bb2eb5bb
15070 changed files with 2402916 additions and 0 deletions

No files matched your search

@@ -0,0 +1,11 @@
import type { Primitive, Statement, PreparedStatement } from "db0";
export declare abstract class BoundableStatement<T> implements Statement {
_statement: T;
constructor(rawStmt: T);
bind(...params: Primitive[]): PreparedStatement;
abstract all(...params: Primitive[]): Promise<unknown[]>;
abstract run(...params: Primitive[]): Promise<{
success: boolean;
}>;
abstract get(...params: Primitive[]): Promise<unknown>;
}
@@ -0,0 +1,29 @@
export class BoundableStatement {
_statement;
constructor(rawStmt) {
this._statement = rawStmt;
}
bind(...params) {
return new BoundStatement(this, params);
}
}
class BoundStatement {
#statement;
#params;
constructor(statement, params) {
this.#statement = statement;
this.#params = params;
}
bind(...params) {
return new BoundStatement(this.#statement, params);
}
all() {
return this.#statement.all(...this.#params);
}
run() {
return this.#statement.run(...this.#params);
}
get() {
return this.#statement.get(...this.#params);
}
}
@@ -0,0 +1,8 @@
import Database from "better-sqlite3";
import type { Connector } from "db0";
export interface ConnectorOptions {
cwd?: string;
path?: string;
name?: string;
}
export default function sqliteConnector(opts: ConnectorOptions): Connector<Database.Database>;
@@ -0,0 +1,42 @@
import { resolve, dirname } from "node:path";
import { mkdirSync } from "node:fs";
import Database from "better-sqlite3";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function sqliteConnector(opts) {
let _db;
const getDB = () => {
if (_db) {
return _db;
}
if (opts.name === ":memory:") {
_db = new Database(":memory:");
return _db;
}
const filePath = resolve(
opts.cwd || ".",
opts.path || `.data/${opts.name || "db"}.sqlite3`
);
mkdirSync(dirname(filePath), { recursive: true });
_db = new Database(filePath);
return _db;
};
return {
name: "sqlite",
dialect: "sqlite",
getInstance: () => getDB(),
exec: (sql) => getDB().exec(sql),
prepare: (sql) => new StatementWrapper(() => getDB().prepare(sql))
};
}
class StatementWrapper extends BoundableStatement {
async all(...params) {
return this._statement().all(...params);
}
async run(...params) {
const res = this._statement().run(...params);
return { success: res.changes > 0, ...res };
}
async get(...params) {
return this._statement().get(...params);
}
}
@@ -0,0 +1,8 @@
import { Database } from "bun:sqlite";
import type { Connector } from "db0";
export interface ConnectorOptions {
cwd?: string;
path?: string;
name?: string;
}
export default function bunSqliteConnector(opts: ConnectorOptions): Connector<Database>;
@@ -0,0 +1,42 @@
import { resolve, dirname } from "node:path";
import { mkdirSync } from "node:fs";
import { Database } from "bun:sqlite";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function bunSqliteConnector(opts) {
let _db;
const getDB = () => {
if (_db) {
return _db;
}
if (opts.name === ":memory:") {
_db = new Database(":memory:");
} else {
const filePath = resolve(
opts.cwd || ".",
opts.path || `.data/${opts.name || "db"}.bun.sqlite`
);
mkdirSync(dirname(filePath), { recursive: true });
_db = new Database(filePath);
}
return _db;
};
return {
name: "sqlite",
dialect: "sqlite",
getInstance: () => getDB(),
exec: (sql) => getDB().exec(sql),
prepare: (sql) => new StatementWrapper(getDB().prepare(sql))
};
}
class StatementWrapper extends BoundableStatement {
all(...params) {
return Promise.resolve(this._statement.all(...params));
}
run(...params) {
const res = this._statement.run(...params);
return Promise.resolve({ success: true, ...res });
}
get(...params) {
return Promise.resolve(this._statement.get(...params));
}
}
@@ -0,0 +1,6 @@
import type { D1Database } from '@cloudflare/workers-types';
import type { Connector } from "db0";
export interface ConnectorOptions {
bindingName?: string;
}
export default function cloudflareD1Connector(options: ConnectorOptions): Connector<D1Database>;
@@ -0,0 +1,31 @@
import { BoundableStatement } from "./_internal/statement.mjs";
export default function cloudflareD1Connector(options) {
const getDB = () => {
const binding = globalThis.__env__?.[options.bindingName] || globalThis.__cf_env__?.[options.bindingName];
if (!binding) {
throw new Error(`[db0] [d1] binding \`${options.bindingName}\` not found`);
}
return binding;
};
return {
name: "cloudflare-d1",
dialect: "sqlite",
getInstance: () => getDB(),
exec: (sql) => getDB().exec(sql),
prepare: (sql) => new StatementWrapper(getDB().prepare(sql))
};
}
class StatementWrapper extends BoundableStatement {
async all(...params) {
const res = await this._statement.bind(...params).all();
return res.results;
}
async run(...params) {
const res = await this._statement.bind(...params).run();
return res;
}
async get(...params) {
const res = await this._statement.bind(...params).first();
return res;
}
}
@@ -0,0 +1,7 @@
import type { Client } from "@libsql/client";
import type { Connector } from "db0";
export type ConnectorOptions = {
getClient: () => Client;
name?: string;
};
export default function libSqlCoreConnector(opts: ConnectorOptions): Connector<Client>;
@@ -0,0 +1,34 @@
import { BoundableStatement } from "../_internal/statement.mjs";
export default function libSqlCoreConnector(opts) {
const query = (sql) => opts.getClient().execute(sql);
return {
name: opts.name || "libsql-core",
dialect: "libsql",
getInstance: async () => opts.getClient(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, query)
};
}
class StatementWrapper extends BoundableStatement {
#query;
#sql;
constructor(sql, query) {
super();
this.#sql = sql;
this.#query = query;
}
async all(...params) {
const res = await this.#query({ sql: this.#sql, args: params });
return res.rows;
}
async run(...params) {
const res = await this.#query({ sql: this.#sql, args: params });
return {
...res
};
}
async get(...params) {
const res = await this.#query({ sql: this.#sql, args: params });
return res.rows[0];
}
}
@@ -0,0 +1,4 @@
import type { Config, Client } from "@libsql/client";
import type { Connector } from "db0";
export type ConnectorOptions = Config;
export default function libSqlConnector(opts: ConnectorOptions): Connector<Client>;
@@ -0,0 +1,15 @@
import { createClient } from "@libsql/client/http";
import libSqlCore from "./core.mjs";
export default function libSqlConnector(opts) {
let _client;
const getClient = () => {
if (!_client) {
_client = createClient(opts);
}
return _client;
};
return libSqlCore({
name: "libsql-http",
getClient
});
}
@@ -0,0 +1,4 @@
import type { Config, Client } from "@libsql/client";
import type { Connector } from "db0";
export type ConnectorOptions = Config;
export default function libSqlConnector(opts: ConnectorOptions): Connector<Client>;
@@ -0,0 +1,15 @@
import { createClient } from "@libsql/client";
import libSqlCore from "./core.mjs";
export default function libSqlConnector(opts) {
let _client;
const getClient = () => {
if (!_client) {
_client = createClient(opts);
}
return _client;
};
return libSqlCore({
name: "libsql-node",
getClient
});
}
@@ -0,0 +1,4 @@
import type { Config, Client } from "@libsql/client";
import type { Connector } from "db0";
export type ConnectorOptions = Config;
export default function libSqlConnector(opts: ConnectorOptions): Connector<Client>;
@@ -0,0 +1,15 @@
import { createClient } from "@libsql/client/http";
import libSqlCore from "./core.mjs";
export default function libSqlConnector(opts) {
let _client;
const getClient = () => {
if (!_client) {
_client = createClient(opts);
}
return _client;
};
return libSqlCore({
name: "libsql-web",
getClient
});
}
@@ -0,0 +1,4 @@
import mysql from "mysql2/promise";
import type { Connector } from "db0";
export type ConnectorOptions = mysql.ConnectionOptions;
export default function mysqlConnector(opts: ConnectorOptions): Connector<mysql.Connection>;
@@ -0,0 +1,46 @@
import mysql from "mysql2/promise";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function mysqlConnector(opts) {
let _connection;
const getConnection = async () => {
if (_connection) {
return _connection;
}
_connection = await mysql.createConnection({
...opts
});
return _connection;
};
const query = (sql, params) => getConnection().then((c) => c.query(sql, params)).then((res) => res[0]);
return {
name: "mysql",
dialect: "mysql",
getInstance: () => getConnection(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, query)
};
}
class StatementWrapper extends BoundableStatement {
#query;
#sql;
constructor(sql, query) {
super();
this.#sql = sql;
this.#query = query;
}
async all(...params) {
const res = await this.#query(this.#sql, params);
return res;
}
async run(...params) {
const res = await this.#query(this.#sql, params);
return {
success: true,
...res
};
}
async get(...params) {
const res = await this.#query(this.#sql, params);
return res[0];
}
}
@@ -0,0 +1,8 @@
import type { Connector } from "db0";
import type { DatabaseSync } from "node:sqlite";
export interface ConnectorOptions {
cwd?: string;
path?: string;
name?: string;
}
export default function nodeSqlite3Connector(opts: ConnectorOptions): Connector<DatabaseSync>;
@@ -0,0 +1,50 @@
import { resolve, dirname } from "node:path";
import { mkdirSync } from "node:fs";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function nodeSqlite3Connector(opts) {
let _db;
const getDB = () => {
if (_db) {
return _db;
}
const nodeSqlite = globalThis.process?.getBuiltinModule?.("node:sqlite");
if (!nodeSqlite) {
throw new Error("`node:sqlite` module is not available. Please ensure you are running in Node.js >= 22.5 or Deno >= 2.2.");
}
if (opts.name === ":memory:") {
_db = new nodeSqlite.DatabaseSync(":memory:");
return _db;
}
const filePath = resolve(
opts.cwd || ".",
opts.path || `.data/${opts.name || "db"}.sqlite`
);
mkdirSync(dirname(filePath), { recursive: true });
_db = new nodeSqlite.DatabaseSync(filePath);
return _db;
};
return {
name: "node-sqlite",
dialect: "sqlite",
getInstance: () => getDB(),
exec(sql) {
getDB().exec(sql);
return { success: true };
},
prepare: (sql) => new StatementWrapper(() => getDB().prepare(sql))
};
}
class StatementWrapper extends BoundableStatement {
async all(...params) {
const raws = this._statement().all(...params);
return raws;
}
async run(...params) {
const res = this._statement().run(...params);
return { success: true, ...res };
}
async get(...params) {
const raw = this._statement().get(...params);
return raw;
}
}
@@ -0,0 +1,5 @@
import type { PGliteOptions, PGliteInterfaceExtensions } from "@electric-sql/pglite";
import { PGlite } from "@electric-sql/pglite";
import type { Connector } from "db0";
export type ConnectorOptions = PGliteOptions;
export default function pgliteConnector<TOptions extends ConnectorOptions>(opts?: TOptions): Connector<PGlite & PGliteInterfaceExtensions<TOptions["extensions"]>>;
@@ -0,0 +1,58 @@
import { PGlite } from "@electric-sql/pglite";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function pgliteConnector(opts) {
let _client;
function getClient() {
return _client ||= PGlite.create(opts).then((res) => _client = res);
}
const query = async (sql, params) => {
const client = await getClient();
const normalizedSql = normalizeParams(sql);
const result = await client.query(normalizedSql, params);
return result;
};
return {
name: "pglite",
dialect: "postgresql",
getInstance: () => getClient(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, query)
};
}
function normalizeParams(sql) {
let i = 0;
return sql.replace(/\?/g, () => `$${++i}`);
}
class StatementWrapper extends BoundableStatement {
#query;
#sql;
constructor(sql, query) {
super();
this.#sql = sql;
this.#query = query;
}
async all(...params) {
const result = await this.#query(
this.#sql,
params
);
return result.rows;
}
async run(...params) {
const result = await this.#query(
this.#sql,
params
);
return {
success: true,
...result
};
}
async get(...params) {
const result = await this.#query(
this.#sql,
params
);
return result.rows[0];
}
}
@@ -0,0 +1,4 @@
import { Client, type Config } from "@planetscale/database";
import type { Connector } from "db0";
export type ConnectorOptions = Config;
export default function planetscaleConnector(opts: ConnectorOptions): Connector<Client>;
@@ -0,0 +1,45 @@
import { Client } from "@planetscale/database";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function planetscaleConnector(opts) {
let _client;
function getClient() {
if (_client) {
return _client;
}
const client = new Client(opts);
_client = client;
return client;
}
const query = (sql, params) => getClient().execute(sql, params);
return {
name: "planetscale",
dialect: "mysql",
getInstance: () => getClient(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, query)
};
}
class StatementWrapper extends BoundableStatement {
#query;
#sql;
constructor(sql, query) {
super();
this.#sql = sql;
this.#query = query;
}
async all(...params) {
const res = await this.#query(this.#sql, params);
return res.rows;
}
async run(...params) {
const res = await this.#query(this.#sql, params);
return {
success: true,
...res
};
}
async get(...params) {
const res = await this.#query(this.#sql, params);
return res.rows[0];
}
}
@@ -0,0 +1,6 @@
import pg from "pg";
import type { Connector } from "db0";
export type ConnectorOptions = {
url: string;
} | pg.ClientConfig;
export default function postgresqlConnector(opts: ConnectorOptions): Connector<pg.Client>;
@@ -0,0 +1,55 @@
import pg from "pg";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function postgresqlConnector(opts) {
let _client;
function getClient() {
if (_client) {
return _client;
}
const client = new pg.Client("url" in opts ? opts.url : opts);
_client = client.connect().then(() => {
_client = client;
return _client;
});
return _client;
}
const query = async (sql, params) => {
const client = await getClient();
return client.query(normalizeParams(sql), params);
};
return {
name: "postgresql",
dialect: "postgresql",
getInstance: () => getClient(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, query)
};
}
function normalizeParams(sql) {
let i = 0;
return sql.replace(/\?/g, () => `$${++i}`);
}
class StatementWrapper extends BoundableStatement {
#query;
#sql;
constructor(sql, query) {
super();
this.#sql = sql;
this.#query = query;
}
async all(...params) {
const res = await this.#query(this.#sql, params);
return res.rows;
}
async run(...params) {
const res = await this.#query(this.#sql, params);
return {
success: true,
...res
};
}
async get(...params) {
const res = await this.#query(this.#sql, params);
return res.rows[0];
}
}
@@ -0,0 +1,8 @@
import sqlite3 from 'sqlite3';
import type { Connector } from 'db0';
export interface ConnectorOptions {
cwd?: string;
path?: string;
name?: string;
}
export default function nodeSqlite3Connector(opts: ConnectorOptions): Connector<sqlite3.Database>;
@@ -0,0 +1,70 @@
import { resolve, dirname } from "node:path";
import { mkdirSync } from "node:fs";
import sqlite3 from "sqlite3";
import { BoundableStatement } from "./_internal/statement.mjs";
export default function nodeSqlite3Connector(opts) {
let _db;
const getDB = () => {
if (_db) {
return _db;
}
if (opts.name === ":memory:") {
_db = new sqlite3.Database(":memory:");
return _db;
}
const filePath = resolve(
opts.cwd || ".",
opts.path || `.data/${opts.name || "db"}.sqlite3`
);
mkdirSync(dirname(filePath), { recursive: true });
_db = new sqlite3.Database(filePath);
return _db;
};
const query = (sql) => new Promise((resolve2, reject) => {
getDB().exec(sql, (err) => {
if (err) {
return reject(err);
}
resolve2({ success: true });
});
});
return {
name: "sqlite3",
dialect: "sqlite",
getInstance: () => getDB(),
exec: (sql) => query(sql),
prepare: (sql) => new StatementWrapper(sql, getDB())
};
}
class StatementWrapper extends BoundableStatement {
#onError;
// #162
constructor(sql, db) {
super(db.prepare(sql, (err) => {
if (err && this.#onError) {
return this.#onError(err);
}
}));
}
async all(...params) {
const rows = await new Promise((resolve2, reject) => {
this.#onError = reject;
this._statement.all(...params, (err, rows2) => err ? reject(err) : resolve2(rows2));
});
return rows;
}
async run(...params) {
await new Promise((resolve2, reject) => {
this.#onError = reject;
this._statement.run(...params, (err) => err ? reject(err) : resolve2());
});
return { success: true };
}
async get(...params) {
const row = await new Promise((resolve2, reject) => {
this.#onError = reject;
this._statement.get(...params, (err, row2) => err ? reject(err) : resolve2(row2));
});
return row;
}
}
+203
View File
@@ -0,0 +1,203 @@
import { ConnectorOptions as ConnectorOptions$1 } from 'db0/connectors/better-sqlite3';
import { ConnectorOptions as ConnectorOptions$2 } from 'db0/connectors/bun-sqlite';
import { ConnectorOptions as ConnectorOptions$3 } from 'db0/connectors/cloudflare-d1';
import { ConnectorOptions as ConnectorOptions$4 } from 'db0/connectors/libsql/core';
import { ConnectorOptions as ConnectorOptions$5 } from 'db0/connectors/libsql/http';
import { ConnectorOptions as ConnectorOptions$6 } from 'db0/connectors/libsql/node';
import { ConnectorOptions as ConnectorOptions$7 } from 'db0/connectors/libsql/web';
import { ConnectorOptions as ConnectorOptions$8 } from 'db0/connectors/mysql2';
import { ConnectorOptions as ConnectorOptions$9 } from 'db0/connectors/node-sqlite';
import { ConnectorOptions as ConnectorOptions$a } from 'db0/connectors/pglite';
import { ConnectorOptions as ConnectorOptions$b } from 'db0/connectors/planetscale';
import { ConnectorOptions as ConnectorOptions$c } from 'db0/connectors/postgresql';
import { ConnectorOptions as ConnectorOptions$d } from 'db0/connectors/sqlite3';
/**
* Represents primitive types that can be used in SQL operations.
*/
type Primitive = string | number | boolean | undefined | null;
type SQLDialect = "mysql" | "postgresql" | "sqlite" | "libsql";
type Statement = {
/**
* Binds parameters to the statement.
* @param {...Primitive[]} params - Parameters to bind to the SQL statement.
* @returns {PreparedStatement} The instance of the statement with bound parameters.
*/
bind(...params: Primitive[]): PreparedStatement;
/**
* Executes the statement and returns all resulting rows as an array.
* @param {...Primitive[]} params - Parameters to bind to the SQL statement.
* @returns {Promise<unknown[]>} A promise that resolves to an array of rows.
*/
all(...params: Primitive[]): Promise<unknown[]>;
/**
* Executes the statement as an action (e.g. insert, update, delete).
* @param {...Primitive[]} params - Parameters to bind to the SQL statement.
* @returns {Promise<{ success: boolean }>} A promise that resolves to the success state of the action.
*/
run(...params: Primitive[]): Promise<{
success: boolean;
}>;
/**
* Executes the statement and returns a single row.
* @param {...Primitive[]} params - Parameters to bind to the SQL statement.
* @returns {Promise<unknown>} A promise that resolves to the first row in the result set.
*/
get(...params: Primitive[]): Promise<unknown>;
};
type PreparedStatement = {
/**
* Binds parameters to the statement.
* @param {...Primitive[]} params - Parameters to bind to the SQL statement.
* @returns {PreparedStatement} The instance of the statement with bound parameters.
*/
bind(...params: Primitive[]): PreparedStatement;
/**
* Executes the statement and returns all resulting rows as an array.
* @returns {Promise<unknown[]>} A promise that resolves to an array of rows.
*/
all(): Promise<unknown[]>;
/**
* Executes the statement as an action (e.g. insert, update, delete).
* @returns {Promise<{ success: boolean }>} A promise that resolves to the success state of the action.
*/
run(): Promise<{
success: boolean;
}>;
/**
* Executes the statement and returns a single row.
* @returns {Promise<unknown>} A promise that resolves to the first row in the result set.
*/
get(): Promise<unknown>;
};
/**
* Represents the result of a database execution.
*/
type ExecResult = unknown;
/**
* Defines a database connector for executing SQL queries and preparing statements.
*/
type Connector<TInstance = unknown> = {
/**
* The name of the connector.
*/
name: string;
/**
* The SQL dialect used by the connector.
*/
dialect: SQLDialect;
/**
* The client instance used internally.
*/
getInstance: () => TInstance | Promise<TInstance>;
/**
* Executes an SQL query directly and returns the result.
* @param {string} sql - The SQL string to execute.
* @returns {ExecResult | Promise<ExecResult>} The result of the execution.
*/
exec: (sql: string) => ExecResult | Promise<ExecResult>;
/**
* Prepares an SQL statement for execution.
* @param {string} sql - The SQL string to prepare.
* @returns {statement} The prepared SQL statement.
*/
prepare: (sql: string) => Statement;
};
/**
* Represents default SQL results, including any error messages, row changes and rows returned.
*/
type DefaultSQLResult = {
lastInsertRowid?: number;
changes?: number;
error?: string;
rows?: {
id?: string | number;
[key: string]: unknown;
}[];
success?: boolean;
};
interface Database<TConnector extends Connector = Connector> {
readonly dialect: SQLDialect;
/**
* The client instance used internally.
* @returns {Promise<TInstance>} A promise that resolves with the client instance.
*/
getInstance: () => Promise<Awaited<ReturnType<TConnector["getInstance"]>>>;
/**
* Executes a raw SQL string.
* @param {string} sql - The SQL string to execute.
* @returns {Promise<ExecResult>} A promise that resolves with the execution result.
*/
exec: (sql: string) => Promise<ExecResult>;
/**
* Prepares an SQL statement from a raw SQL string.
* @param {string} sql - The SQL string to prepare.
* @returns {statement} The prepared SQL statement.
*/
prepare: (sql: string) => Statement;
/**
* Executes SQL queries using tagged template literals.
* @template T The expected type of query result.
* @param {TemplateStringsArray} strings - The segments of the SQL string.
* @param {...Primitive[]} values - The values to interpolate into the SQL string.
* @returns {Promise<T>} A promise that resolves with the typed result of the query.
*/
sql: <T = DefaultSQLResult>(strings: TemplateStringsArray, ...values: Primitive[]) => Promise<T>;
}
/**
* Creates and returns a database interface using the specified connector.
* This interface allows you to execute raw SQL queries, prepare SQL statements,
* and execute SQL queries with parameters using tagged template literals.
*
* @param {Connector} connector - The database connector used to execute and prepare SQL statements. See {@link Connector}.
* @returns {Database} The database interface that allows SQL operations. See {@link Database}.
*/
declare function createDatabase<TConnector extends Connector = Connector>(connector: TConnector): Database<TConnector>;
type ConnectorName = "better-sqlite3" | "bun-sqlite" | "bun" | "cloudflare-d1" | "libsql-core" | "libsql-http" | "libsql-node" | "libsql" | "libsql-web" | "mysql2" | "node-sqlite" | "sqlite" | "pglite" | "planetscale" | "postgresql" | "sqlite3";
type ConnectorOptions = {
"better-sqlite3": ConnectorOptions$1;
"bun-sqlite": ConnectorOptions$2;
/** alias of bun-sqlite */
"bun": ConnectorOptions$2;
"cloudflare-d1": ConnectorOptions$3;
"libsql-core": ConnectorOptions$4;
"libsql-http": ConnectorOptions$5;
"libsql-node": ConnectorOptions$6;
/** alias of libsql-node */
"libsql": ConnectorOptions$6;
"libsql-web": ConnectorOptions$7;
"mysql2": ConnectorOptions$8;
"node-sqlite": ConnectorOptions$9;
/** alias of node-sqlite */
"sqlite": ConnectorOptions$9;
"pglite": ConnectorOptions$a;
"planetscale": ConnectorOptions$b;
"postgresql": ConnectorOptions$c;
"sqlite3": ConnectorOptions$d;
};
declare const connectors: Readonly<{
readonly "better-sqlite3": "db0/connectors/better-sqlite3";
readonly "bun-sqlite": "db0/connectors/bun-sqlite";
/** alias of bun-sqlite */
readonly bun: "db0/connectors/bun-sqlite";
readonly "cloudflare-d1": "db0/connectors/cloudflare-d1";
readonly "libsql-core": "db0/connectors/libsql/core";
readonly "libsql-http": "db0/connectors/libsql/http";
readonly "libsql-node": "db0/connectors/libsql/node";
/** alias of libsql-node */
readonly libsql: "db0/connectors/libsql/node";
readonly "libsql-web": "db0/connectors/libsql/web";
readonly mysql2: "db0/connectors/mysql2";
readonly "node-sqlite": "db0/connectors/node-sqlite";
/** alias of node-sqlite */
readonly sqlite: "db0/connectors/node-sqlite";
readonly pglite: "db0/connectors/pglite";
readonly planetscale: "db0/connectors/planetscale";
readonly postgresql: "db0/connectors/postgresql";
readonly sqlite3: "db0/connectors/sqlite3";
}>;
export { connectors, createDatabase };
export type { Connector, ConnectorName, ConnectorOptions, Database, ExecResult, PreparedStatement, Primitive, SQLDialect, Statement };
+78
View File
@@ -0,0 +1,78 @@
function sqlTemplate(strings, ...values) {
if (!isTemplateStringsArray(strings) || !Array.isArray(values)) {
throw new Error("[db0] invalid template invocation");
}
const staticIndexes = [];
let result = strings[0] || "";
for (let i = 1; i < strings.length; i++) {
if (result.endsWith("{") && strings[i].startsWith("}")) {
result = result.slice(0, -1) + values[i - 1] + strings[i].slice(1);
staticIndexes.push(i - 1);
continue;
}
result += `?${strings[i] ?? ""}`;
}
const dynamicValues = values.filter((_, i) => !staticIndexes.includes(i));
return [result.trim(), dynamicValues];
}
function isTemplateStringsArray(strings) {
return Array.isArray(strings) && "raw" in strings && Array.isArray(strings.raw);
}
const SQL_SELECT_RE = /^select/i;
const SQL_RETURNING_RE = /[\s]returning[\s]/i;
const DIALECTS_WITH_RET = /* @__PURE__ */ new Set(["postgresql", "sqlite"]);
function createDatabase(connector) {
return {
get dialect() {
return connector.dialect;
},
getInstance() {
return connector.getInstance();
},
exec: (sql) => {
return Promise.resolve(connector.exec(sql));
},
prepare: (sql) => {
return connector.prepare(sql);
},
sql: async (strings, ...values) => {
const [sql, params] = sqlTemplate(strings, ...values);
if (SQL_SELECT_RE.test(sql) || // prettier-ignore
DIALECTS_WITH_RET.has(connector.dialect) && SQL_RETURNING_RE.test(sql)) {
const rows = await connector.prepare(sql).all(...params);
return {
rows,
success: true
};
} else {
const res = await connector.prepare(sql).run(...params);
return res;
}
}
};
}
const connectors = Object.freeze({
"better-sqlite3": "db0/connectors/better-sqlite3",
"bun-sqlite": "db0/connectors/bun-sqlite",
/** alias of bun-sqlite */
"bun": "db0/connectors/bun-sqlite",
"cloudflare-d1": "db0/connectors/cloudflare-d1",
"libsql-core": "db0/connectors/libsql/core",
"libsql-http": "db0/connectors/libsql/http",
"libsql-node": "db0/connectors/libsql/node",
/** alias of libsql-node */
"libsql": "db0/connectors/libsql/node",
"libsql-web": "db0/connectors/libsql/web",
"mysql2": "db0/connectors/mysql2",
"node-sqlite": "db0/connectors/node-sqlite",
/** alias of node-sqlite */
"sqlite": "db0/connectors/node-sqlite",
"pglite": "db0/connectors/pglite",
"planetscale": "db0/connectors/planetscale",
"postgresql": "db0/connectors/postgresql",
"sqlite3": "db0/connectors/sqlite3"
});
export { connectors, createDatabase };
@@ -0,0 +1,36 @@
import { entityKind, Logger, RelationalSchemaConfig, type Query, type TablesRelationalConfig } from "drizzle-orm";
import { SQLiteAsyncDialect, SQLiteSession, SQLitePreparedQuery } from "drizzle-orm/sqlite-core";
import type { PreparedQueryConfig, SelectedFieldsOrdered, SQLiteExecuteMethod, SQLiteTransactionConfig } from "drizzle-orm/sqlite-core";
import type { Database, Statement } from "db0";
export interface DB0SessionOptions {
logger?: Logger;
}
export declare class DB0Session<TFullSchema extends Record<string, unknown>, TSchema extends TablesRelationalConfig> extends SQLiteSession<"async", unknown, TFullSchema, TSchema> {
private db;
private schema;
private options;
dialect: SQLiteAsyncDialect;
private logger;
constructor(db: Database, dialect: SQLiteAsyncDialect, schema: RelationalSchemaConfig<TSchema> | undefined, options?: DB0SessionOptions);
prepareQuery(query: Query, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper?: (rows: unknown[][]) => unknown): DB0PreparedQuery;
transaction<T>(transaction: (tx: any) => T | Promise<T>, config?: SQLiteTransactionConfig): Promise<T>;
}
export declare class DB0PreparedQuery<T extends PreparedQueryConfig = PreparedQueryConfig> extends SQLitePreparedQuery<{
type: "async";
run: Awaited<ReturnType<Statement["run"]>>;
all: T["all"];
get: T["get"];
values: T["values"];
execute: T["execute"];
}> {
private stmt;
private logger;
static readonly [entityKind]: string;
constructor(stmt: Statement, query: Query, logger: Logger, fields: SelectedFieldsOrdered | undefined, executeMethod: SQLiteExecuteMethod, customResultMapper?: (rows: unknown[][]) => unknown);
run(): Promise<{
success: boolean;
}>;
all(): Promise<unknown[]>;
get(): Promise<unknown>;
values(): Promise<never>;
}
@@ -0,0 +1,55 @@
import {
entityKind,
NoopLogger
} from "drizzle-orm";
import {
SQLiteSession,
SQLitePreparedQuery
} from "drizzle-orm/sqlite-core";
export class DB0Session extends SQLiteSession {
constructor(db, dialect, schema, options = {}) {
super(dialect);
this.db = db;
this.schema = schema;
this.options = options;
this.logger = options.logger ?? new NoopLogger();
}
dialect;
logger;
prepareQuery(query, fields, executeMethod, customResultMapper) {
const stmt = this.db.prepare(query.sql);
return new DB0PreparedQuery(
stmt,
query,
this.logger,
fields,
executeMethod,
customResultMapper
);
}
// TODO: Implement batch
// TODO: Implement transaction
transaction(transaction, config) {
throw new Error("transaction is not implemented!");
}
}
export class DB0PreparedQuery extends SQLitePreparedQuery {
constructor(stmt, query, logger, fields, executeMethod, customResultMapper) {
super("async", executeMethod, query);
this.stmt = stmt;
this.logger = logger;
}
static [entityKind] = "DB0PreparedQuery";
run() {
return this.stmt.run(...this.query.params);
}
all() {
return this.stmt.all(...this.query.params);
}
get() {
return this.stmt.get(...this.query.params);
}
values() {
return Promise.reject(new Error("values is not implemented!"));
}
}
@@ -0,0 +1,3 @@
import { AnyColumn, SelectedFieldsOrdered } from "drizzle-orm";
/** @internal */
export declare function mapResultRow<TResult>(columns: SelectedFieldsOrdered<AnyColumn>, row: unknown[], joinsNotNullableMap: Record<string, boolean> | undefined): TResult;
@@ -0,0 +1,51 @@
import {
getTableName,
is,
Column,
SQL
} from "drizzle-orm";
export function mapResultRow(columns, row, joinsNotNullableMap) {
const nullifyMap = {};
const result = columns.reduce(
(result2, { path, field }, columnIndex) => {
let decoder;
if (is(field, Column)) {
decoder = field;
} else if (is(field, SQL)) {
decoder = "decoder" in field && field.decoder;
} else {
decoder = "decoder" in field.sql && field.sql.decoder;
}
let node = result2;
for (const [pathChunkIndex, pathChunk] of path.entries()) {
if (pathChunkIndex < path.length - 1) {
if (!(pathChunk in node)) {
node[pathChunk] = {};
}
node = node[pathChunk];
} else {
const rawValue = row[columnIndex];
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
if (joinsNotNullableMap && is(field, Column) && path.length === 2) {
const objectName = path[0];
if (!(objectName in nullifyMap)) {
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
nullifyMap[objectName] = false;
}
}
}
}
return result2;
},
{}
);
if (joinsNotNullableMap && Object.keys(nullifyMap).length > 0) {
for (const [objectName, tableName] of Object.entries(nullifyMap)) {
if (typeof tableName === "string" && !joinsNotNullableMap[tableName]) {
result[objectName] = null;
}
}
}
return result;
}
@@ -0,0 +1,4 @@
import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
import type { Database } from "db0";
export type DrizzleDatabase<TSchema extends Record<string, unknown> = Record<string, never>> = BaseSQLiteDatabase<"async", any, TSchema>;
export declare function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(db: Database): DrizzleDatabase<TSchema>;
@@ -0,0 +1,16 @@
import {
BaseSQLiteDatabase,
SQLiteAsyncDialect
} from "drizzle-orm/sqlite-core";
import { DB0Session } from "./_session.mjs";
export function drizzle(db) {
const schema = void 0;
const dialect = new SQLiteAsyncDialect();
const session = new DB0Session(db, dialect, schema);
return new BaseSQLiteDatabase(
"async",
dialect,
session,
schema
);
}