From bbb7bfb7a187d6c35eaa59ce44e8a5dd22e9a972 Mon Sep 17 00:00:00 2001 From: dswbx Date: Fri, 13 Jun 2025 11:09:47 +0200 Subject: [PATCH] feat: adding env aware endpoint to obtain sqlite connection, remove libsql hard dependency --- app/build.ts | 29 ++++++++++- app/package.json | 19 +++++++- app/src/App.ts | 45 ++++------------- app/src/adapter/bun/bun.adapter.ts | 26 ++++++++-- .../bun/connection/BunSqliteConnection.ts | 25 ++++++---- app/src/adapter/bun/index.ts | 2 + app/src/adapter/cloudflare/modes/durable.ts | 2 +- app/src/adapter/index.ts | 2 + .../node/connection/NodeSqliteConnection.ts | 17 +++++-- app/src/adapter/node/index.ts | 19 +------- app/src/adapter/node/node.adapter.ts | 22 ++++++++- app/src/adapter/node/storage/index.ts | 17 +++++++ app/src/adapter/sqlite/bun.ts | 8 ++++ app/src/adapter/sqlite/edge.ts | 8 ++++ app/src/adapter/sqlite/node.ts | 8 ++++ app/src/adapter/sqlite/types.ts | 3 ++ app/src/core/utils/runtime.ts | 8 ++++ app/src/data/api/DataApi.ts | 29 +++++------ app/src/data/connection/DummyConnection.ts | 2 + app/src/data/connection/index.ts | 4 +- .../connection/sqlite/LibsqlConnection.ts | 42 ++++++++-------- app/src/data/entities/index.ts | 2 + .../data/entities/mutation/MutatorResult.ts | 2 +- app/src/media/api/MediaController.ts | 8 +++- app/src/modules/ModuleManager.ts | 3 +- app/src/ui/client/api/use-entity.ts | 8 ++-- app/vite.dev.ts | 48 +++++++++---------- bun.lock | 39 ++++++++++----- 28 files changed, 288 insertions(+), 159 deletions(-) create mode 100644 app/src/adapter/node/storage/index.ts create mode 100644 app/src/adapter/sqlite/bun.ts create mode 100644 app/src/adapter/sqlite/edge.ts create mode 100644 app/src/adapter/sqlite/node.ts create mode 100644 app/src/adapter/sqlite/types.ts diff --git a/app/build.ts b/app/build.ts index 698778b..f526235 100644 --- a/app/build.ts +++ b/app/build.ts @@ -244,7 +244,11 @@ async function buildAdapters() { // specific adatpers await tsup.build(baseConfig("react-router")); - await tsup.build(baseConfig("bun")); + await tsup.build( + baseConfig("bun", { + external: [/^bun\:.*/], + }), + ); await tsup.build(baseConfig("astro")); await tsup.build(baseConfig("aws")); await tsup.build( @@ -267,6 +271,29 @@ async function buildAdapters() { ...baseConfig("node"), platform: "node", }); + + await tsup.build({ + ...baseConfig("sqlite/edge"), + entry: ["src/adapter/sqlite/edge.ts"], + outDir: "dist/adapter/sqlite", + metafile: false, + }); + + await tsup.build({ + ...baseConfig("sqlite/node"), + entry: ["src/adapter/sqlite/node.ts"], + outDir: "dist/adapter/sqlite", + platform: "node", + metafile: false, + }); + + await tsup.build({ + ...baseConfig("sqlite/bun"), + entry: ["src/adapter/sqlite/bun.ts"], + outDir: "dist/adapter/sqlite", + metafile: false, + external: [/^bun\:.*/], + }); } await buildApi(); diff --git a/app/package.json b/app/package.json index c8d326e..516d1d9 100644 --- a/app/package.json +++ b/app/package.json @@ -50,7 +50,6 @@ "@codemirror/lang-json": "^6.0.1", "@hello-pangea/dnd": "^18.0.1", "@hono/swagger-ui": "^0.5.1", - "@libsql/client": "^0.15.2", "@mantine/core": "^7.17.1", "@mantine/hooks": "^7.17.1", "@sinclair/typebox": "0.34.30", @@ -61,11 +60,11 @@ "bcryptjs": "^3.0.2", "dayjs": "^1.11.13", "fast-xml-parser": "^5.0.8", + "hono": "^4.7.11", "json-schema-form-react": "^0.0.2", "json-schema-library": "10.0.0-rc7", "json-schema-to-ts": "^3.1.1", "kysely": "^0.27.6", - "hono": "^4.7.11", "lodash-es": "^4.17.21", "oauth4webapi": "^2.11.1", "object-path-immutable": "^4.1.2", @@ -74,6 +73,7 @@ "uuid": "^11.1.0" }, "devDependencies": { + "@libsql/client": "^0.15.9", "@aws-sdk/client-s3": "^3.758.0", "@bluwy/giget-core": "^0.1.2", "@cloudflare/workers-types": "^4.20250606.0", @@ -104,6 +104,7 @@ "jsonv-ts": "^0.1.0", "kysely-d1": "^0.3.0", "kysely-generic-sqlite": "^1.2.1", + "libsql-stateless-easy": "^1.8.0", "open": "^10.1.0", "openapi-types": "^12.1.3", "picocolors": "^1.1.1", @@ -184,6 +185,20 @@ "import": "./dist/media/index.js", "require": "./dist/media/index.js" }, + "./adapter/sqlite": { + "types": "./dist/types/adapter/sqlite/edge.d.ts", + "import": { + "workerd": "./dist/adapter/sqlite/edge.js", + "edge-light": "./dist/adapter/sqlite/edge.js", + "netlify": "./dist/adapter/sqlite/edge.js", + "vercel": "./dist/adapter/sqlite/edge.js", + "browser": "./dist/adapter/sqlite/edge.js", + "bun": "./dist/adapter/sqlite/bun.js", + "node": "./dist/adapter/sqlite/node.js", + "default": "./dist/adapter/sqlite/node.js" + }, + "require": "./dist/adapter/sqlite/node.js" + }, "./adapter/cloudflare": { "types": "./dist/types/adapter/cloudflare/index.d.ts", "import": "./dist/adapter/cloudflare/index.js", diff --git a/app/src/App.ts b/app/src/App.ts index 956229c..2ad76df 100644 --- a/app/src/App.ts +++ b/app/src/App.ts @@ -1,7 +1,7 @@ import type { CreateUserPayload } from "auth/AppAuth"; import { $console } from "core"; import { Event } from "core/events"; -import { Connection, type LibSqlCredentials, LibsqlConnection } from "data"; +import { Connection } from "data/connection/Connection"; import type { Hono } from "hono"; import { ModuleManager, @@ -14,10 +14,10 @@ import { import * as SystemPermissions from "modules/permissions"; import { AdminController, type AdminControllerOptions } from "modules/server/AdminController"; import { SystemController } from "modules/server/SystemController"; +import type { ServerEnv } from "modules/Controller"; // biome-ignore format: must be here import { Api, type ApiOptions } from "Api"; -import type { ServerEnv } from "modules/Controller"; export type AppPlugin = (app: App) => Promise | void; @@ -51,15 +51,8 @@ export type AppOptions = { manager?: Omit; asyncEventsMode?: "sync" | "async" | "none"; }; -export type CreateAppConfig = { - connection?: - | Connection - | { - // @deprecated - type: "libsql"; - config: LibSqlCredentials; - } - | LibSqlCredentials; +export type CreateAppConfig = { + connection?: C | { url: string }; initialConfig?: InitialModuleConfigs; options?: AppOptions; }; @@ -67,7 +60,7 @@ export type CreateAppConfig = { export type AppConfig = InitialModuleConfigs; export type LocalApiOptions = Request | ApiOptions; -export class App { +export class App { static readonly Events = AppEvents; modules: ModuleManager; @@ -79,7 +72,7 @@ export class App { private _building: boolean = false; constructor( - private connection: Connection, + public connection: C, _initialConfig?: InitialModuleConfigs, private options?: AppOptions, ) { @@ -262,31 +255,9 @@ export class App { } export function createApp(config: CreateAppConfig = {}) { - let connection: Connection | undefined = undefined; - - try { - if (Connection.isConnection(config.connection)) { - connection = config.connection; - } else if (typeof config.connection === "object") { - if ("type" in config.connection) { - $console.warn( - "Using deprecated connection type 'libsql', use the 'config' object directly.", - ); - connection = new LibsqlConnection(config.connection.config); - } else { - connection = new LibsqlConnection(config.connection); - } - } else { - connection = new LibsqlConnection({ url: ":memory:" }); - $console.warn("No connection provided, using in-memory database"); - } - } catch (e) { - $console.error("Could not create connection", e); - } - - if (!connection) { + if (!config.connection || !Connection.isConnection(config.connection)) { throw new Error("Invalid connection"); } - return new App(connection, config.initialConfig, config.options); + return new App(config.connection, config.initialConfig, config.options); } diff --git a/app/src/adapter/bun/bun.adapter.ts b/app/src/adapter/bun/bun.adapter.ts index 44fb795..07b778a 100644 --- a/app/src/adapter/bun/bun.adapter.ts +++ b/app/src/adapter/bun/bun.adapter.ts @@ -1,11 +1,18 @@ /// import path from "node:path"; -import { type RuntimeBkndConfig, createRuntimeApp, type RuntimeOptions } from "bknd/adapter"; -import { registerLocalMediaAdapter } from "bknd/adapter/node"; +import { + type RuntimeBkndConfig, + createRuntimeApp, + type RuntimeOptions, + Connection, +} from "bknd/adapter"; +import { registerLocalMediaAdapter } from "."; import { config } from "bknd/core"; import type { ServeOptions } from "bun"; import { serveStatic } from "hono/bun"; +import { sqlite } from "bknd/adapter/sqlite"; +import type { App } from "App"; type BunEnv = Bun.Env; export type BunBkndConfig = RuntimeBkndConfig & Omit; @@ -18,9 +25,17 @@ export async function createApp( const root = path.resolve(distPath ?? "./node_modules/bknd/dist", "static"); registerLocalMediaAdapter(); + let connection: Connection | undefined; + if (Connection.isConnection(config.connection)) { + connection = config.connection; + } else { + connection = sqlite(config.connection ?? { url: ":memory:" }); + } + return await createRuntimeApp( { ...config, + connection, serveStatic: serveStatic({ root }), }, args ?? (process.env as Env), @@ -33,8 +48,11 @@ export function createHandler( args: Env = {} as Env, opts?: RuntimeOptions, ) { + let app: App | undefined; return async (req: Request) => { - const app = await createApp(config, args ?? (process.env as Env), opts); + if (!app) { + app = await createApp(config, args ?? (process.env as Env), opts); + } return app.fetch(req); }; } @@ -72,5 +90,5 @@ export function serve( ), }); - console.log(`Server is running on http://localhost:${port}`); + console.info(`Server is running on http://localhost:${port}`); } diff --git a/app/src/adapter/bun/connection/BunSqliteConnection.ts b/app/src/adapter/bun/connection/BunSqliteConnection.ts index dc5638f..7f124d1 100644 --- a/app/src/adapter/bun/connection/BunSqliteConnection.ts +++ b/app/src/adapter/bun/connection/BunSqliteConnection.ts @@ -1,4 +1,4 @@ -import type { Database } from "bun:sqlite"; +import { Database } from "bun:sqlite"; import { buildQueryFn, GenericSqliteConnection, @@ -30,12 +30,19 @@ function bunSqliteExecutor(db: Database, cache: boolean): IGenericSqlite bunSqliteExecutor(config.database, false), - { - name: "bun-sqlite", - }, - ); +export function bunSqlite(config?: BunSqliteConnectionConfig | { url: string }) { + let database: Database; + if (config) { + if ("database" in config) { + database = config.database; + } else { + database = new Database(config.url); + } + } else { + database = new Database(":memory:"); + } + + return new GenericSqliteConnection(database, () => bunSqliteExecutor(database, false), { + name: "bun-sqlite", + }); } diff --git a/app/src/adapter/bun/index.ts b/app/src/adapter/bun/index.ts index c95cfb4..5f85135 100644 --- a/app/src/adapter/bun/index.ts +++ b/app/src/adapter/bun/index.ts @@ -1 +1,3 @@ export * from "./bun.adapter"; +export * from "../node/storage"; +export * from "./connection/BunSqliteConnection"; diff --git a/app/src/adapter/cloudflare/modes/durable.ts b/app/src/adapter/cloudflare/modes/durable.ts index 310fd24..25dd0b4 100644 --- a/app/src/adapter/cloudflare/modes/durable.ts +++ b/app/src/adapter/cloudflare/modes/durable.ts @@ -64,7 +64,7 @@ export class DurableBkndApp extends DurableObject { "type" in config.connection && config.connection.type === "libsql" ) { - config.connection.config.protocol = "wss"; + //config.connection.config.protocol = "wss"; } this.app = await createRuntimeApp({ diff --git a/app/src/adapter/index.ts b/app/src/adapter/index.ts index 84fb8c5..569afd6 100644 --- a/app/src/adapter/index.ts +++ b/app/src/adapter/index.ts @@ -3,6 +3,8 @@ import { config as $config } from "bknd/core"; import type { MiddlewareHandler } from "hono"; import type { AdminControllerOptions } from "modules/server/AdminController"; +export { Connection } from "bknd/data"; + export type BkndConfig = CreateAppConfig & { app?: CreateAppConfig | ((args: Args) => CreateAppConfig); onBuilt?: (app: App) => Promise; diff --git a/app/src/adapter/node/connection/NodeSqliteConnection.ts b/app/src/adapter/node/connection/NodeSqliteConnection.ts index b6faad4..8fdc630 100644 --- a/app/src/adapter/node/connection/NodeSqliteConnection.ts +++ b/app/src/adapter/node/connection/NodeSqliteConnection.ts @@ -4,7 +4,7 @@ import { parseBigInt, type IGenericSqlite, } from "../../../data/connection/sqlite/GenericSqliteConnection"; -import type { DatabaseSync } from "node:sqlite"; +import { DatabaseSync } from "node:sqlite"; export type NodeSqliteConnectionConfig = { database: DatabaseSync; @@ -39,8 +39,19 @@ function nodeSqliteExecutor(db: DatabaseSync): IGenericSqlite { }; } -export function nodeSqlite(config: NodeSqliteConnectionConfig) { - return new GenericSqliteConnection(config.database, () => nodeSqliteExecutor(config.database), { +export function nodeSqlite(config?: NodeSqliteConnectionConfig | { url: string }) { + let database: DatabaseSync; + if (config) { + if ("database" in config) { + database = config.database; + } else { + database = new DatabaseSync(config.url); + } + } else { + database = new DatabaseSync(":memory:"); + } + + return new GenericSqliteConnection(database, () => nodeSqliteExecutor(database), { name: "node-sqlite", }); } diff --git a/app/src/adapter/node/index.ts b/app/src/adapter/node/index.ts index 16a6b2a..b430450 100644 --- a/app/src/adapter/node/index.ts +++ b/app/src/adapter/node/index.ts @@ -1,18 +1,3 @@ -import { registries } from "bknd"; -import { type LocalAdapterConfig, StorageLocalAdapter } from "./storage/StorageLocalAdapter"; - export * from "./node.adapter"; -export { StorageLocalAdapter, type LocalAdapterConfig }; - -let registered = false; -export function registerLocalMediaAdapter() { - if (!registered) { - registries.media.register("local", StorageLocalAdapter); - registered = true; - } - - return (config: Partial = {}) => { - const adapter = new StorageLocalAdapter(config); - return adapter.toJSON(true); - }; -} +export * from "./storage"; +export * from "./connection/NodeSqliteConnection"; diff --git a/app/src/adapter/node/node.adapter.ts b/app/src/adapter/node/node.adapter.ts index ed07800..02aa829 100644 --- a/app/src/adapter/node/node.adapter.ts +++ b/app/src/adapter/node/node.adapter.ts @@ -2,9 +2,16 @@ import path from "node:path"; import { serve as honoServe } from "@hono/node-server"; import { serveStatic } from "@hono/node-server/serve-static"; import { registerLocalMediaAdapter } from "adapter/node/index"; -import { type RuntimeBkndConfig, createRuntimeApp, type RuntimeOptions } from "bknd/adapter"; +import { + type RuntimeBkndConfig, + createRuntimeApp, + type RuntimeOptions, + Connection, +} from "bknd/adapter"; import { config as $config } from "bknd/core"; import { $console } from "core"; +import { sqlite } from "bknd/adapter/sqlite"; +import type { App } from "App"; type NodeEnv = NodeJS.ProcessEnv; export type NodeBkndConfig = RuntimeBkndConfig & { @@ -28,10 +35,18 @@ export async function createApp( console.warn("relativeDistPath is deprecated, please use distPath instead"); } + let connection: Connection | undefined; + if (Connection.isConnection(config.connection)) { + connection = config.connection; + } else { + connection = sqlite(config.connection ?? { url: ":memory:" }); + } + registerLocalMediaAdapter(); return await createRuntimeApp( { ...config, + connection, serveStatic: serveStatic({ root }), }, // @ts-ignore @@ -45,8 +60,11 @@ export function createHandler( args: Env = {} as Env, opts?: RuntimeOptions, ) { + let app: App | undefined; return async (req: Request) => { - const app = await createApp(config, args ?? (process.env as Env), opts); + if (!app) { + app = await createApp(config, args ?? (process.env as Env), opts); + } return app.fetch(req); }; } diff --git a/app/src/adapter/node/storage/index.ts b/app/src/adapter/node/storage/index.ts new file mode 100644 index 0000000..549bf70 --- /dev/null +++ b/app/src/adapter/node/storage/index.ts @@ -0,0 +1,17 @@ +import { registries } from "bknd"; +import { type LocalAdapterConfig, StorageLocalAdapter } from "./StorageLocalAdapter"; + +export * from "./StorageLocalAdapter"; + +let registered = false; +export function registerLocalMediaAdapter() { + if (!registered) { + registries.media.register("local", StorageLocalAdapter); + registered = true; + } + + return (config: Partial = {}) => { + const adapter = new StorageLocalAdapter(config); + return adapter.toJSON(true); + }; +} diff --git a/app/src/adapter/sqlite/bun.ts b/app/src/adapter/sqlite/bun.ts new file mode 100644 index 0000000..328186c --- /dev/null +++ b/app/src/adapter/sqlite/bun.ts @@ -0,0 +1,8 @@ +import type { Connection } from "bknd/data"; +import { $console } from "bknd/core"; +import { bunSqlite } from "../bun/connection/BunSqliteConnection"; + +export function sqlite(config: { url: string }): Connection { + $console.info("Using bun-sqlite", config); + return bunSqlite(config); +} diff --git a/app/src/adapter/sqlite/edge.ts b/app/src/adapter/sqlite/edge.ts new file mode 100644 index 0000000..996d7f5 --- /dev/null +++ b/app/src/adapter/sqlite/edge.ts @@ -0,0 +1,8 @@ +import { $console } from "bknd/core"; +import type { Connection } from "bknd/data"; +import { libsql } from "../../data/connection/sqlite/LibsqlConnection"; + +export function sqlite(config: { url: string }): Connection { + $console.info("Using libsql", config); + return libsql(config); +} diff --git a/app/src/adapter/sqlite/node.ts b/app/src/adapter/sqlite/node.ts new file mode 100644 index 0000000..1643cce --- /dev/null +++ b/app/src/adapter/sqlite/node.ts @@ -0,0 +1,8 @@ +import { $console } from "bknd/core"; +import type { Connection } from "bknd/data"; +import { nodeSqlite } from "../node/connection/NodeSqliteConnection"; + +export function sqlite(config: { url: string }): Connection { + $console.info("Using node-sqlite", config); + return nodeSqlite(config); +} diff --git a/app/src/adapter/sqlite/types.ts b/app/src/adapter/sqlite/types.ts new file mode 100644 index 0000000..2a0a5e5 --- /dev/null +++ b/app/src/adapter/sqlite/types.ts @@ -0,0 +1,3 @@ +import type { Connection } from "bknd/data"; + +export type SqliteConnection = (config: { url: string }) => Connection; diff --git a/app/src/core/utils/runtime.ts b/app/src/core/utils/runtime.ts index b90f670..0772abd 100644 --- a/app/src/core/utils/runtime.ts +++ b/app/src/core/utils/runtime.ts @@ -48,6 +48,14 @@ export function isNode() { } } +export function isBun() { + try { + return typeof Bun !== "undefined"; + } catch (e) { + return false; + } +} + export function invariant(condition: boolean | any, message: string) { if (!condition) { throw new Error(message); diff --git a/app/src/data/api/DataApi.ts b/app/src/data/api/DataApi.ts index 6103220..bd670e8 100644 --- a/app/src/data/api/DataApi.ts +++ b/app/src/data/api/DataApi.ts @@ -1,5 +1,5 @@ import type { DB } from "core"; -import type { EntityData, RepoQueryIn, RepositoryResponse } from "data"; +import type { EntityData, RepoQueryIn, RepositoryResultJSON } from "data"; import type { Insertable, Selectable, Updateable } from "kysely"; import { type BaseModuleApiOptions, ModuleApi, type PrimaryFieldType } from "modules"; import type { FetchPromise, ResponseObject } from "modules/ModuleApi"; @@ -32,10 +32,7 @@ export class DataApi extends ModuleApi { query: Omit = {}, ) { type Data = E extends keyof DB ? Selectable : EntityData; - return this.get, "meta" | "data">>( - ["entity", entity as any, id], - query, - ); + return this.get>(["entity", entity as any, id], query); } readOneBy( @@ -43,7 +40,7 @@ export class DataApi extends ModuleApi { query: Omit = {}, ) { type Data = E extends keyof DB ? Selectable : EntityData; - type T = Pick, "meta" | "data">; + type T = RepositoryResultJSON; return this.readMany(entity, { ...query, limit: 1, @@ -53,7 +50,7 @@ export class DataApi extends ModuleApi { readMany(entity: E, query: RepoQueryIn = {}) { type Data = E extends keyof DB ? Selectable : EntityData; - type T = Pick, "meta" | "data">; + type T = RepositoryResultJSON; const input = query ?? this.options.defaultQuery; const req = this.get(["entity", entity as any], input); @@ -72,7 +69,7 @@ export class DataApi extends ModuleApi { query: RepoQueryIn = {}, ) { type Data = R extends keyof DB ? Selectable : EntityData; - return this.get, "meta" | "data">>( + return this.get>( ["entity", entity as any, id, reference], query ?? this.options.defaultQuery, ); @@ -83,7 +80,7 @@ export class DataApi extends ModuleApi { input: Insertable, ) { type Data = E extends keyof DB ? Selectable : EntityData; - return this.post>(["entity", entity as any], input); + return this.post>(["entity", entity as any], input); } createMany( @@ -94,7 +91,7 @@ export class DataApi extends ModuleApi { throw new Error("input is required"); } type Data = E extends keyof DB ? Selectable : EntityData; - return this.post>(["entity", entity as any], input); + return this.post>(["entity", entity as any], input); } updateOne( @@ -104,7 +101,7 @@ export class DataApi extends ModuleApi { ) { if (!id) throw new Error("ID is required"); type Data = E extends keyof DB ? Selectable : EntityData; - return this.patch>(["entity", entity as any, id], input); + return this.patch>(["entity", entity as any, id], input); } updateMany( @@ -114,7 +111,7 @@ export class DataApi extends ModuleApi { ) { this.requireObjectSet(where); type Data = E extends keyof DB ? Selectable : EntityData; - return this.patch>(["entity", entity as any], { + return this.patch>(["entity", entity as any], { update, where, }); @@ -123,24 +120,24 @@ export class DataApi extends ModuleApi { deleteOne(entity: E, id: PrimaryFieldType) { if (!id) throw new Error("ID is required"); type Data = E extends keyof DB ? Selectable : EntityData; - return this.delete>(["entity", entity as any, id]); + return this.delete>(["entity", entity as any, id]); } deleteMany(entity: E, where: RepoQueryIn["where"]) { this.requireObjectSet(where); type Data = E extends keyof DB ? Selectable : EntityData; - return this.delete>(["entity", entity as any], where); + return this.delete>(["entity", entity as any], where); } count(entity: E, where: RepoQueryIn["where"] = {}) { - return this.post>( + return this.post>( ["entity", entity as any, "fn", "count"], where, ); } exists(entity: E, where: RepoQueryIn["where"] = {}) { - return this.post>( + return this.post>( ["entity", entity as any, "fn", "exists"], where, ); diff --git a/app/src/data/connection/DummyConnection.ts b/app/src/data/connection/DummyConnection.ts index d04d0af..aa7eb9d 100644 --- a/app/src/data/connection/DummyConnection.ts +++ b/app/src/data/connection/DummyConnection.ts @@ -1,6 +1,8 @@ import { Connection, type FieldSpec, type SchemaResponse } from "./Connection"; export class DummyConnection extends Connection { + override name: string = "dummy"; + protected override readonly supported = { batching: true, }; diff --git a/app/src/data/connection/index.ts b/app/src/data/connection/index.ts index ce8c7ff..9bd285e 100644 --- a/app/src/data/connection/index.ts +++ b/app/src/data/connection/index.ts @@ -5,11 +5,13 @@ export { type IndexSpec, type DbFunctions, type SchemaResponse, + type ConnQuery, + type ConnQueryResults, customIntrospector, } from "./Connection"; // sqlite -export { LibsqlConnection, type LibSqlCredentials } from "./sqlite/LibsqlConnection"; +//export { libsql, LibsqlConnection, type LibSqlCredentials } from "./sqlite/LibsqlConnection"; export { SqliteConnection } from "./sqlite/SqliteConnection"; export { SqliteIntrospector } from "./sqlite/SqliteIntrospector"; export { SqliteLocalConnection } from "./sqlite/SqliteLocalConnection"; diff --git a/app/src/data/connection/sqlite/LibsqlConnection.ts b/app/src/data/connection/sqlite/LibsqlConnection.ts index cf0ff58..e6833eb 100644 --- a/app/src/data/connection/sqlite/LibsqlConnection.ts +++ b/app/src/data/connection/sqlite/LibsqlConnection.ts @@ -1,15 +1,29 @@ -import { createClient, type Client, type Config, type InStatement } from "@libsql/client"; +import type { Client, Config, InStatement } from "@libsql/client"; +import { createClient } from "libsql-stateless-easy"; import { LibsqlDialect } from "@libsql/kysely-libsql"; -import { $console } from "core"; import { FilterNumericKeysPlugin } from "data/plugins/FilterNumericKeysPlugin"; -import type { ConnQuery, ConnQueryResults } from "../Connection"; -import { SqliteConnection } from "./SqliteConnection"; +import { type ConnQuery, type ConnQueryResults, SqliteConnection } from "bknd/data"; export const LIBSQL_PROTOCOLS = ["wss", "https", "libsql"] as const; export type LibSqlCredentials = Config & { protocol?: (typeof LIBSQL_PROTOCOLS)[number]; }; +function getClient(clientOrCredentials: Client | LibSqlCredentials): Client { + if (clientOrCredentials && "url" in clientOrCredentials) { + let { url, authToken, protocol } = clientOrCredentials; + if (protocol && LIBSQL_PROTOCOLS.includes(protocol)) { + console.info("changing protocol to", protocol); + const [, rest] = url.split("://"); + url = `${protocol}://${rest}`; + } + + return createClient({ url, authToken }); + } + + return clientOrCredentials as Client; +} + export class LibsqlConnection extends SqliteConnection { override name = "libsql"; protected override readonly supported = { @@ -17,22 +31,8 @@ export class LibsqlConnection extends SqliteConnection { softscans: true, }; - constructor(client: Client); - constructor(credentials: LibSqlCredentials); constructor(clientOrCredentials: Client | LibSqlCredentials) { - let client: Client; - if (clientOrCredentials && "url" in clientOrCredentials) { - let { url, authToken, protocol } = clientOrCredentials; - if (protocol && LIBSQL_PROTOCOLS.includes(protocol)) { - $console.log("changing protocol to", protocol); - const [, rest] = url.split("://"); - url = `${protocol}://${rest}`; - } - - client = createClient({ url, authToken }); - } else { - client = clientOrCredentials; - } + const client = getClient(clientOrCredentials); super({ excludeTables: ["libsql_wasm_func_table"], @@ -56,3 +56,7 @@ export class LibsqlConnection extends SqliteConnection { return this.withTransformedRows(await this.client.batch(stms)) as any; } } + +export function libsql(credentials: LibSqlCredentials): LibsqlConnection { + return new LibsqlConnection(credentials); +} diff --git a/app/src/data/entities/index.ts b/app/src/data/entities/index.ts index eb5f3b2..5beca37 100644 --- a/app/src/data/entities/index.ts +++ b/app/src/data/entities/index.ts @@ -4,3 +4,5 @@ export * from "./mutation/Mutator"; export * from "./query/Repository"; export * from "./query/WhereBuilder"; export * from "./query/WithBuilder"; +export * from "./query/RepositoryResult"; +export * from "./mutation/MutatorResult"; diff --git a/app/src/data/entities/mutation/MutatorResult.ts b/app/src/data/entities/mutation/MutatorResult.ts index 88cf435..25ae7f6 100644 --- a/app/src/data/entities/mutation/MutatorResult.ts +++ b/app/src/data/entities/mutation/MutatorResult.ts @@ -19,7 +19,7 @@ export class MutatorResult extends Result { hydrator: (rows) => em.hydrate(entity.name, rows as any), beforeExecute: (compiled) => { if (!options?.silent) { - $console.debug(`[Mutation]\n${compiled.sql}\n`, compiled.parameters); + $console.debug(`[Mutation]\n${compiled.sql}\n`); } }, onError: (error) => { diff --git a/app/src/media/api/MediaController.ts b/app/src/media/api/MediaController.ts index cdcbe5a..9a70e91 100644 --- a/app/src/media/api/MediaController.ts +++ b/app/src/media/api/MediaController.ts @@ -216,7 +216,9 @@ export class MediaController extends Controller { const paths_to_delete: string[] = []; if (max_items) { const { overwrite } = c.req.valid("query"); - const { count } = await this.media.em.repository(media_entity).count(mediaRef); + const { + data: { count }, + } = await this.media.em.repository(media_entity).count(mediaRef); // if there are more than or equal to max items if (count >= max_items) { @@ -255,7 +257,9 @@ export class MediaController extends Controller { } // check if entity exists in database - const { exists } = await this.media.em.repository(entity).exists({ id: entity_id }); + const { + data: { exists }, + } = await this.media.em.repository(entity).exists({ id: entity_id }); if (!exists) { return c.json( { error: `Entity "${entity_name}" with ID "${entity_id}" doesn't exist found` }, diff --git a/app/src/modules/ModuleManager.ts b/app/src/modules/ModuleManager.ts index 022e314..d933ceb 100644 --- a/app/src/modules/ModuleManager.ts +++ b/app/src/modules/ModuleManager.ts @@ -234,7 +234,8 @@ export class ModuleManager { } private get db() { - return this.connection.kysely as Kysely<{ table: ConfigTable }>; + // @todo: check why this is neccessary + return this.connection.kysely as unknown as Kysely<{ table: ConfigTable }>; } // @todo: add indices for: version, type diff --git a/app/src/ui/client/api/use-entity.ts b/app/src/ui/client/api/use-entity.ts index 3995e56..4219c41 100644 --- a/app/src/ui/client/api/use-entity.ts +++ b/app/src/ui/client/api/use-entity.ts @@ -1,7 +1,7 @@ import type { DB, PrimaryFieldType } from "core"; import { objectTransform } from "core/utils/objects"; import { encodeSearch } from "core/utils/reqres"; -import type { EntityData, RepoQueryIn, RepositoryResponse } from "data"; +import type { EntityData, RepoQueryIn, RepositoryResult } from "data"; import type { Insertable, Selectable, Updateable } from "kysely"; import type { FetchPromise, ModuleApi, ResponseObject } from "modules/ModuleApi"; import useSWR, { type SWRConfiguration, type SWRResponse, mutate } from "swr"; @@ -28,15 +28,13 @@ interface UseEntityReturn< Entity extends keyof DB | string, Id extends PrimaryFieldType | undefined, Data = Entity extends keyof DB ? DB[Entity] : EntityData, - Response = ResponseObject>>, + Response = ResponseObject>>, > { create: (input: Insertable) => Promise; read: ( query?: RepoQueryIn, ) => Promise< - ResponseObject< - RepositoryResponse[] : Selectable> - > + ResponseObject[] : Selectable>> >; update: Id extends undefined ? (input: Updateable, id: Id) => Promise diff --git a/app/vite.dev.ts b/app/vite.dev.ts index 2ce51c1..913d488 100644 --- a/app/vite.dev.ts +++ b/app/vite.dev.ts @@ -3,30 +3,33 @@ import { serveStatic } from "@hono/node-server/serve-static"; import { showRoutes } from "hono/dev"; import { App, registries } from "./src"; import { StorageLocalAdapter } from "./src/adapter/node"; -import { EntityManager, LibsqlConnection } from "data"; +import type { Connection } from "./src/data/connection/Connection"; import { __bknd } from "modules/ModuleManager"; +import { nodeSqlite } from "./src/adapter/node/connection/NodeSqliteConnection"; +import { libsql } from "./src/data/connection/sqlite/LibsqlConnection"; import { $console } from "core"; -//import { DatabaseSync } from "node:sqlite"; -//import { nodeSqlite } from "./src/adapter/node/connection/NodeSqliteConnection"; registries.media.register("local", StorageLocalAdapter); const example = import.meta.env.VITE_EXAMPLE; +const dbUrl = example ? `file:.configs/${example}.db` : import.meta.env.VITE_DB_URL; -const credentials = example - ? { - url: `file:.configs/${example}.db`, - } - : import.meta.env.VITE_DB_URL - ? { - url: import.meta.env.VITE_DB_URL!, - authToken: import.meta.env.VITE_DB_TOKEN!, - } - : { - url: ":memory:", - }; +let connection: Connection; +if (dbUrl) { + connection = nodeSqlite({ url: dbUrl }); + $console.debug("Using node-sqlite connection", dbUrl); +} else if (import.meta.env.VITE_DB_LIBSQL_URL) { + connection = libsql({ + url: import.meta.env.VITE_DB_LIBSQL_URL!, + authToken: import.meta.env.VITE_DB_LIBSQL_TOKEN!, + }); + $console.debug("Using libsql connection", import.meta.env.VITE_DB_URL); +} else { + connection = nodeSqlite(); + $console.debug("No connection provided, using in-memory database"); +} -if (example) { +/* if (example) { const { version, ...config } = JSON.parse(await readFile(`.configs/${example}.json`, "utf-8")); // create db with config @@ -50,7 +53,7 @@ if (example) { json: config, }); } -} +} */ let app: App; const recreate = import.meta.env.VITE_APP_FRESH === "1"; @@ -60,8 +63,7 @@ export default { async fetch(request: Request) { if (!app || recreate) { app = App.create({ - connection: credentials, - //connection: nodeSqlite({ database: new DatabaseSync(":memory:") }), + connection, }); app.emgr.onEvent( App.Events.AppBuiltEvent, @@ -78,15 +80,11 @@ export default { // log routes if (firstStart) { firstStart = false; - // biome-ignore lint/suspicious/noConsoleLog: - console.log("[DB]", credentials); if (import.meta.env.VITE_SHOW_ROUTES === "1") { - // biome-ignore lint/suspicious/noConsoleLog: - console.log("\n[APP ROUTES]"); + console.info("\n[APP ROUTES]"); showRoutes(app.server); - // biome-ignore lint/suspicious/noConsoleLog: - console.log("-------\n"); + console.info("-------\n"); } } } diff --git a/bun.lock b/bun.lock index 7a0bb68..56fe68e 100644 --- a/bun.lock +++ b/bun.lock @@ -34,7 +34,7 @@ "@codemirror/lang-json": "^6.0.1", "@hello-pangea/dnd": "^18.0.1", "@hono/swagger-ui": "^0.5.1", - "@libsql/client": "^0.15.2", + "@libsql/client": "^0.15.9", "@mantine/core": "^7.17.1", "@mantine/hooks": "^7.17.1", "@sinclair/typebox": "0.34.30", @@ -88,6 +88,7 @@ "jsonv-ts": "^0.1.0", "kysely-d1": "^0.3.0", "kysely-generic-sqlite": "^1.2.1", + "libsql-stateless-easy": "^1.8.0", "open": "^10.1.0", "openapi-types": "^12.1.3", "picocolors": "^1.1.1", @@ -755,13 +756,13 @@ "@lezer/lr": ["@lezer/lr@1.4.2", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA=="], - "@libsql/client": ["@libsql/client@0.15.2", "", { "dependencies": { "@libsql/core": "^0.15.2", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.4", "promise-limit": "^2.7.0" } }, "sha512-D0No4jqDj5I+buvEyFajBugohzJXCBt9aRHCEXGrJS/9obnAO2z18Os3xgyPsWX0Yw4NQfSYaayRdowqkssmXA=="], + "@libsql/client": ["@libsql/client@0.15.9", "", { "dependencies": { "@libsql/core": "^0.15.9", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.13", "promise-limit": "^2.7.0" } }, "sha512-VT3do0a0vwYVaNcp/y05ikkKS3OrFR5UeEf5SUuYZVgKVl1Nc1k9ajoYSsOid8AD/vlhLDB5yFQaV4HmT/OB9w=="], - "@libsql/core": ["@libsql/core@0.15.2", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-+UIN0OlzWa54MqnHbtaJ3FEJj6k2VrwrjX1sSSxzYlM+dWuadjMwOVp7gHpSYJGKWw0RQWLGge4fbW4TCvIm3A=="], + "@libsql/core": ["@libsql/core@0.15.9", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-4OVdeAmuaCUq5hYT8NNn0nxlO9AcA/eTjXfUZ+QK8MT3Dz7Z76m73x7KxjU6I64WyXX98dauVH2b9XM+d84npw=="], - "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4PnRdklaQg27vAZxtQgKl+xBHimCH2KRgKId+h63gkAtz5yFTMmX+Q4Ez804T1BgrZuB5ujIvueEEuust2ceSQ=="], + "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ASz/EAMLDLx3oq9PVvZ4zBXXHbz2TxtxUwX2xpTRFR4V4uSHAN07+jpLu3aK5HUBLuv58z7+GjaL5w/cyjR28Q=="], - "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-r+Z3UXQWxluXKA5cPj5KciNsmSXVTnq9/tmDczngJrogyXwdbbSShYkzov5M+YBlUCKv2VCbNnfxxoIqQnV9Gg=="], + "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-kzglniv1difkq8opusSXM7u9H0WoEPeKxw0ixIfcGfvlCVMJ+t9UNtXmyNHW68ljdllje6a4C6c94iPmIYafYA=="], "@libsql/hrana-client": ["@libsql/hrana-client@0.7.0", "", { "dependencies": { "@libsql/isomorphic-fetch": "^0.3.1", "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5", "node-fetch": "^3.3.2" } }, "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw=="], @@ -771,15 +772,19 @@ "@libsql/kysely-libsql": ["@libsql/kysely-libsql@0.4.1", "", { "dependencies": { "@libsql/client": "^0.8.0" }, "peerDependencies": { "kysely": "*" } }, "sha512-mCTa6OWgoME8LNu22COM6XjKBmcMAvNtIO6DYM10jSAFq779fVlrTKQEmXIB8TwJVU65dA5jGCpT8gkDdWS0HQ=="], - "@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-QmGXa3TGM6URe7vCOqdvr4Koay+4h5D6y4gdhnPCvXNYrRHgpq5OwEafP9GFalbO32Y1ppLY4enO2LwY0k63Qw=="], + "@libsql/linux-arm-gnueabihf": ["@libsql/linux-arm-gnueabihf@0.5.13", "", { "os": "linux", "cpu": "arm" }, "sha512-UEW+VZN2r0mFkfztKOS7cqfS8IemuekbjUXbXCwULHtusww2QNCXvM5KU9eJCNE419SZCb0qaEWYytcfka8qeA=="], - "@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-cx4/7/xUjgNbiRsghRHujSvIqaTNFQC7Oo1gkGXGsh8hBwkdXr1QdOpeitq745sl6OlbInRrW2C7B2juxX3hcQ=="], + "@libsql/linux-arm-musleabihf": ["@libsql/linux-arm-musleabihf@0.5.13", "", { "os": "linux", "cpu": "arm" }, "sha512-NMDgLqryYBv4Sr3WoO/m++XDjR5KLlw9r/JK4Ym6A1XBv2bxQQNhH0Lxx3bjLW8qqhBD4+0xfms4d2cOlexPyA=="], - "@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.4", "", { "os": "linux", "cpu": "x64" }, "sha512-oPrE9Zyqd7fElS9uCGW2jn55cautD+gDIflfyF5+W/QYzll5OJ2vyMBZOBgdNopuZHrmHYihbespJn3t0WJDJg=="], + "@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-/wCxVdrwl1ee6D6LEjwl+w4SxuLm5UL9Kb1LD5n0bBGs0q+49ChdPPh7tp175iRgkcrTgl23emymvt1yj3KxVQ=="], - "@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.4", "", { "os": "linux", "cpu": "x64" }, "sha512-XzyVdVe43MexkAaHzUvsi4tpPhfSDn3UndIYFrIu0lYkkiz4oKjTK7Iq96j2bcOeJv0pBGxiv+8Z9I6yp/aI2A=="], + "@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-xnVAbZIanUgX57XqeI5sNaDnVilp0Di5syCLSEo+bRyBobe/1IAeehNZpyVbCy91U2N6rH1C/mZU7jicVI9x+A=="], - "@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xWQyAQEsX+odBrMSXTpm3WOFeoJIX7QncCkaZcsaqdEFueOdNDIdcKAQKMoNlwtj1rCxE72RK4byw/Bflf6Jgg=="], + "@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.13", "", { "os": "linux", "cpu": "x64" }, "sha512-/mfMRxcQAI9f8t7tU3QZyh25lXgXKzgin9B9TOSnchD73PWtsVhlyfA6qOCfjQl5kr4sHscdXD5Yb3KIoUgrpQ=="], + + "@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.13", "", { "os": "linux", "cpu": "x64" }, "sha512-rdefPTpQCVwUjIQYbDLMv3qpd5MdrT0IeD0UZPGqhT9AWU8nJSQoj2lfyIDAWEz7PPOVCY4jHuEn7FS2sw9kRA=="], + + "@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.13", "", { "os": "win32", "cpu": "x64" }, "sha512-aNcmDrD1Ws+dNZIv9ECbxBQumqB9MlSVEykwfXJpqv/593nABb8Ttg5nAGUPtnADyaGDTrGvPPP81d/KsKho4Q=="], "@mantine/core": ["@mantine/core@7.17.1", "", { "dependencies": { "@floating-ui/react": "^0.26.28", "clsx": "^2.1.1", "react-number-format": "^5.4.3", "react-remove-scroll": "^2.6.2", "react-textarea-autosize": "8.5.6", "type-fest": "^4.27.0" }, "peerDependencies": { "@mantine/hooks": "7.17.1", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "sha512-V8O3Ftq4la4I4wNDkTfH4Slkt/pCEU32pTE/DkO46zua0VFxfOAJeLjaol0s11//T+bXx82DtjMsd9APWPuFhA=="], @@ -1235,7 +1240,7 @@ "@types/babel__traverse": ["@types/babel__traverse@7.20.6", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg=="], - "@types/bun": ["@types/bun@1.2.15", "", { "dependencies": { "bun-types": "1.2.15" } }, "sha512-U1ljPdBEphF0nw1MIk0hI7kPg7dFdPyM7EenHsp6W5loNHl7zqy6JQf/RKCgnUn2KDzUpkBwHPnEJEjII594bA=="], + "@types/bun": ["@types/bun@1.2.16", "", { "dependencies": { "bun-types": "1.2.16" } }, "sha512-1aCZJ/6nSiViw339RsaNhkNoEloLaPzZhxMOYEa7OzRzO41IGg5n/7I43/ZIAW/c+Q6cT12Vf7fOZOoVIzb5BQ=="], "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], @@ -2571,7 +2576,11 @@ "levn": ["levn@0.3.0", "", { "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } }, "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA=="], - "libsql": ["libsql@0.5.4", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.4", "@libsql/darwin-x64": "0.5.4", "@libsql/linux-arm64-gnu": "0.5.4", "@libsql/linux-arm64-musl": "0.5.4", "@libsql/linux-x64-gnu": "0.5.4", "@libsql/linux-x64-musl": "0.5.4", "@libsql/win32-x64-msvc": "0.5.4" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-GEFeWca4SDAQFxjHWJBE6GK52LEtSskiujbG3rqmmeTO9t4sfSBKIURNLLpKDDF7fb7jmTuuRkDAn9BZGITQNw=="], + "libsql": ["libsql@0.5.13", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.13", "@libsql/darwin-x64": "0.5.13", "@libsql/linux-arm-gnueabihf": "0.5.13", "@libsql/linux-arm-musleabihf": "0.5.13", "@libsql/linux-arm64-gnu": "0.5.13", "@libsql/linux-arm64-musl": "0.5.13", "@libsql/linux-x64-gnu": "0.5.13", "@libsql/linux-x64-musl": "0.5.13", "@libsql/win32-x64-msvc": "0.5.13" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-5Bwoa/CqzgkTwySgqHA5TsaUDRrdLIbdM4egdPcaAnqO3aC+qAgS6BwdzuZwARA5digXwiskogZ8H7Yy4XfdOg=="], + + "libsql-stateless": ["libsql-stateless@2.9.1", "", {}, "sha512-vxq2eyQoKYjGl2J6vYpZ4+rfX9zLckUswbchbgcaeiV/d6Do7T77NHWkiS57KywJRJdbxxoZUS404Nx9AfUDzQ=="], + + "libsql-stateless-easy": ["libsql-stateless-easy@1.8.0", "", { "dependencies": { "libsql-stateless": "2.9.1" } }, "sha512-0Hm2bW0Ntx3X8BAnX+qUUNMRr/GfmJj7HfVkhBDkCld8flSaIO6bwqDAUX6DGLH32KOANmk1dM18VSGjx2BLyQ=="], "lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], @@ -3867,6 +3876,8 @@ "@babel/runtime/regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], + "@bknd/postgres/@types/bun": ["@types/bun@1.2.15", "", { "dependencies": { "bun-types": "1.2.15" } }, "sha512-U1ljPdBEphF0nw1MIk0hI7kPg7dFdPyM7EenHsp6W5loNHl7zqy6JQf/RKCgnUn2KDzUpkBwHPnEJEjII594bA=="], + "@bundled-es-modules/cookie/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "@bundled-es-modules/tough-cookie/tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="], @@ -4081,7 +4092,7 @@ "@testing-library/jest-dom/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="], - "@types/bun/bun-types": ["bun-types@1.2.15", "", { "dependencies": { "@types/node": "*" } }, "sha512-NarRIaS+iOaQU1JPfyKhZm4AsUOrwUOqRNHY0XxI8GI8jYxiLXLcdjYMG9UKS+fwWasc1uw1htV9AX24dD+p4w=="], + "@types/bun/bun-types": ["bun-types@1.2.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A=="], "@types/jest/jest-diff": ["jest-diff@25.5.0", "", { "dependencies": { "chalk": "^3.0.0", "diff-sequences": "^25.2.6", "jest-get-type": "^25.2.6", "pretty-format": "^25.5.0" } }, "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A=="], @@ -4729,6 +4740,8 @@ "@babel/preset-env/babel-plugin-polyfill-regenerator/@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg=="], + "@bknd/postgres/@types/bun/bun-types": ["bun-types@1.2.15", "", { "dependencies": { "@types/node": "*" } }, "sha512-NarRIaS+iOaQU1JPfyKhZm4AsUOrwUOqRNHY0XxI8GI8jYxiLXLcdjYMG9UKS+fwWasc1uw1htV9AX24dD+p4w=="], + "@bundled-es-modules/tough-cookie/tough-cookie/universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="], "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],