Skip to content

wip: effect sql kysely new proposal #5156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kristiannotari
Copy link

@kristiannotari kristiannotari commented Jul 3, 2025

Type

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

This proposal (or suggestion of a proposal) is there to make working with Kysely less prone to errors, due to the current way of patching and proxying Kysely objects. There may be better approaches, in the meanwhile, I wanted to open this PR to start discussing them.

The idea is to build a couple of wrappers while omitting some Kysely builtin methods that would otherwise let the user exit from the Effect world.

Also, this is mainly due to this error occurring: https://discord.com/channels/795981131316985866/1134177528098078861/1389230820790763571

Note: the SqlClient implementation is missing, as well as transaction handling, as I am not that much into how the effect-sql packages should work right now.

Related

  • Related Issue #
  • Closes #

@github-project-automation github-project-automation bot moved this to Discussion Ongoing in PR Backlog Jul 3, 2025
Copy link

changeset-bot bot commented Jul 3, 2025

⚠️ No Changeset found

Latest commit: c1684d7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@jvliwanag
Copy link
Contributor

Hoping this approach pulls through. The current Proxy approach is problematic in what it ends up patching. See here.

Can offer help as well on this.

@jvliwanag
Copy link
Contributor

Currently, the approach of this PR has been to use the kysely drivers for execution.

The current kysely integration allows for using kysely directly for execution or coursing it through effect-sql.

I prefer coursing it more through effect-sql since we get more effect integration for free, and using kysely only as a sql generator. I took a stab at this and replaced effect-sql.

Looks like there isn't much to it though. Briefly:

type Executable<O> = Compilable & { execute: () => Promise<O> };

export function execute<O>(
  s: Executable<O>,
): Effect.Effect<O, SqlError.SqlError, SqlClient.SqlClient> {
  return SqlClient.SqlClient.pipe(
    Effect.flatMap((cl) => {
      let { sql, parameters } = s.compile();
      let r = cl.unsafe(sql, parameters as any);

      return r as unknown as Effect.Effect<
        O,
        SqlError.SqlError,
        SqlClient.SqlClient
      >;
    }),
  );
}

Here, we use kysely's Compilable type to assure that compile is on the arg. There's a type parameter on Compilable that I infer is supposed to be a hint on the output type -- however it's not used and typescript inference isn't useful. As such, we get the output type from the execute result of the arg.

We then declare the db as we do regular kysely instances with the difference of using a dummy driver.

export function mkKyselyPg<DB>(): Kysely<DB> {
  return new Kysely<DB>({
    dialect: {
      createAdapter: () => new PostgresAdapter(),
      createDriver: () => new DummyDriver(),
      createIntrospector: (db) => new PostgresIntrospector(db),
      createQueryCompiler: () => new PostgresQueryCompiler(),
    },
  });
}

and on the usage site:

import * as KSql from "./ksql.js";


let db = KSql. mkKyselyPg<MyDB>();

let eff = KSql.execute(db.selectFrom("foo").selectAll());

The resulting effect should just have SqlClient on the R side, as other effect-sql libs would. It's less appealing to write compared being able to yield the select statements, but imo -- much less worrisome than the current Proxy approach.

Imo, dropping the proxy approach and having kysely be just for sql generation and making effect-sql actually run it is the approach I suggest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Discussion Ongoing
Development

Successfully merging this pull request may close these issues.

2 participants