~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
61 lines · 1.7 KB Raw History
// Adapts better-sqlite3 to the Cloudflare Durable Object SQL interface, so the
// DO adapter's SQL and logic can run under plain vitest. This does NOT exercise
// the DO runtime itself — that is covered by the PLATFORM=cloudflare e2e path
// once later phases add endpoints touching space storage.

/**
 * @typedef {Object} D1ShimCursor
 * @property {() => any[]} toArray
 */

/**
 * @param {import('better-sqlite3').Database} db
 * @returns {{
 *   sql: {exec: (query: string, ...params: any[]) => D1ShimCursor},
 *   storage: {transactionSync: (fn: () => any) => any},
 * }}
 */
export function createD1Shim(db) {
  return {
    sql: {
      /**
       * @param {string} query
       * @param {...any} params
       * @returns {D1ShimCursor}
       */
      exec(query, ...params) {
        const trimmed = query.trim();
        // The DO's exec accepts multi-statement DDL; better-sqlite3 needs
        // .exec() for that, and .prepare() rejects it.
        if (params.length === 0 && trimmed.includes(';')) {
          db.exec(query);
          return { toArray: () => [] };
        }
        const stmt = db.prepare(query);
        if (/^\s*select/i.test(trimmed)) {
          const rows = stmt.all(...params);
          return { toArray: () => rows };
        }
        stmt.run(...params);
        return { toArray: () => [] };
      },
    },
    storage: {
      /**
       * @param {() => any} fn
       * @returns {any}
       */
      transactionSync(fn) {
        db.exec('BEGIN');
        try {
          const result = fn();
          db.exec('COMMIT');
          return result;
        } catch (err) {
          db.exec('ROLLBACK');
          throw err;
        }
      },
    },
  };
}