Turso: Has anyone attempted running with a Turso database backend?

we would basically have to completely rebuild our own entire SQL connection library which to support just one extra database is not even a possibility. It would make basically no sense, especially for a SQLite driver

The implementation is right here: GitHub - libsql/libsql-node-sqlite3: node-sqlite3 compatible API for libSQL

It’s a drop in replacement for sqlite3, there’s no rebuilding

You can open a request with the Knex team to see if they would entertain supporting a new one

Yeah we can’t swap out the drivers, we tried with the sqlite3 one was going through changes and switched to better-sqlite3 (which knex added support for)

The drivers themselves come from Knex, if you try to use one that’s not in it’s list it will literally throw an error and refuse to use it

I suppose the custom client interface is just for lollygagging then.

Believe me if we had an option to swap to better drivers, we would

Would love to see turso supported. May I ask, wouldn’t adding support for custom dialects allow us to make de connection without waiting on Knex?

I got it working locally to Turso by patching @strapi/database with pnpm or yarn. (have not tried deploying it yet)
I made a blog post with the full guide Use Turso DB with Strapi 4

With pnpm you:
Create a patch with pnpm patch @strapi/database@4.25.9 --edit-dir strapi-db-patch
Edit the file you’re patching which will be in strapi-db-patch/dist/index.js
You need to add this to the top of the file

const Client_SQLite3 = require("knex/lib/dialects/sqlite3");
class Client_Libsql extends Client_SQLite3 {
  _driver() {
    return require("@libsql/sqlite3");
  }
}
Object.assign(Client_Libsql.prototype, {
  dialect: "libsql",
  driverName: "libsql",
});

And also add a near copy of the existing SqliteDialect like this:

class LibsqlDialect extends SqliteDialect {
  schemaInspector;
  constructor(db) {
    super(db);
    this.client = "libsql";
  }
  configure() {}
}

Then edit the getDialectClass and getDialectName functions like this:

const getDialectClass = (client) => {
  switch (client) {
    case "postgres":
      return PostgresDialect;
    case "mysql":
      return MysqlDialect;
    case "sqlite":
      return SqliteDialect;
    case "libsql":
      return LibsqlDialect;
    default:
      throw new Error(`Unknown dialect ${client}`);
  }
};
const getDialectName = (client) => {
  switch (client) {
    case "postgres":
      return "postgres";
    case "libsql":
      return "libsql";
    case "mysql":
    case "mysql2":
      return "mysql";
    case "sqlite":
    case "sqlite-legacy":
      return "sqlite";
    default:
      throw new Error(`Unknown dialect ${client}`);
  }
};

Add this one line to applySearch above case “sqlite”:

// ...
case "libsql":
case "sqlite": {
// ...

The discord message limit is reached, see next post for the rest

[continuing from previous post]

Finally, edit createConnection to this:

const createConnection = (config) => {
  const knexConfig = { ...config };
  if (knexConfig.client === "libsql") {
    knexConfig.client = Client_Libsql;
  }
  if (knexConfig.client === "sqlite") {
    const sqlitePackageName = getSqlitePackageName();
    knexConfig.client = clientMap[sqlitePackageName];
  }
  return knex__default.default(knexConfig);
};

Now you store the patch to your code with pnpm patch-commit 'strapi-db-patch'

Remember to install this libsql package: pnpm i @libsql/sqlite3

Then edit your standard config/database.js with something like this:

const connections = {
// ...
libsql: {
      connection: {
        filename:
          "wss://my-strapi-db.turso.io?authToken=my_turso_auth_token",
      },
      useNullAsDefault: true,
    },

I did not get it to work with the libsql:// or https:// protocols, because the connection timed out or something. So you must use wss://

Update the .env to use the libsql connection DATABASE_CLIENT=libsql

You can now run pnpm develop and see the Turso database be filled up with Strapi tables.

My packages at the time of writing were:
@libsql/sqlite3”: “^0.3.1”,
@strapi/strapi”: “4.25.9”,
“better-sqlite3”: “8.6.0”,
“knex”: “^3.1.0”,

Seems like there is a package from the turso devs that provides a knex dialect for libsql as seen here

Similar to what I did. I just created a sub package then exported the libsql client, and then overrode the bettersqlite3 package with my local one, also gives local read replica support which I don’t believe is in the @libsql/sqlite3 package.

// ./sqlite3-proxy/index.js
const Database = require("libsql");

module.exports = function (path) {
  const ops = {
    syncUrl: process.env.TURSO_DB,
    authToken: process.env.TURSO_TOKEN,
  };
  const db = new Database(path, ops);

  db.sync();

  return db;
};
// ./squite3-proxy/package.json
{
  "name": "better-sqlite3",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "libsql": "^0.4.0-pre.10"
  }
}
// package.json
{
 ...
    "better-sqlite3": "./sqlite3-proxy/",
 ...
}

A bit hacky, but at least it doesn’t require changes to core files.

Hey really interesting to see people wanting turso support. If someone is interested in contributing to the codebase we can guide you to make this a reality. Feel free to reach out