UNPKG

cloudflare-d1-http-knex

Version:

An npm package that query [Cloudflare's D1](https://developers.cloudflare.com/d1/) through [Query D1 Database API](https://developers.cloudflare.com/api/operations/cloudflare-d1-query-database-query) and [Knex](https://knexjs.org/).

152 lines (144 loc) 4.59 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); require('knex'); var Client = require('knex/lib/dialects/sqlite3/index.js'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var Client__default = /*#__PURE__*/_interopDefault(Client); // src/client.ts var CloudflareD1HttpClient = class extends Client__default.default { constructor(config) { config.connection.filename = ":memory:"; config.useNullAsDefault = false; super(config); if (!config.connection.mockedFetch) { if (!config.connection?.account_id) { throw Error("Missing required account_id"); } if (!config.connection?.database_id) { throw Error("Missing required database_id"); } if (!config.connection?.key) { throw Error("Missing required key"); } } this.config = config; } _driver() { return this; } acquireRawConnection() { return Promise.resolve(this); } async _query(_, obj) { if (!obj.sql) return Promise.reject(Error("The query is empty")); if (["BEGIN;", "COMMIT;", "ROLLBACK;"].includes(obj.sql)) { console.warn( "[WARN] D1 doesn't support transactions, see https://blog.cloudflare.com/whats-new-with-d1/" ); return Promise.resolve(); } if (this.config.connection.mockedFetch) return this.config.connection.mockedFetch( `https://api.cloudflare.com/client/v4/accounts/${this.config.connection.account_id}/d1/database/${this.config.connection.database_id}/query`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ sql: obj.sql, params: obj.bindings }) } ).then((res) => this._processResponse(res, obj)); return fetch( `https://api.cloudflare.com/client/v4/accounts/${this.config.connection.account_id}/d1/database/${this.config.connection.database_id}/query`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.config.connection.key}` }, body: JSON.stringify({ sql: obj.sql, params: obj.bindings }) } ).then((res) => this._processResponse(res, obj)); } async _processResponse(res, obj) { return res.json().then((body) => { if (body.success) { if (obj.output) return obj.output.call(null, body.result[0].results); switch (obj.method) { case "first": return body.result[0].results[0]; case "insert": if (obj.returning) { return body.result[0].results; } return [body.result[0].meta.changes]; case "update": if (obj.returning) { return body.result[0].results; } return body.result[0].meta.changes; case "del": case "counter": return body.result[0].meta.changes; case "pluck": return body.result[0].results.map((row) => row[obj.pluck]); default: return body.result[0].results; } } throw Error(body.errors[0].message); }); } async processResponse(res) { return res; } }; // src/mock.ts var db; var mockedFetch = (_, options) => { return Promise.resolve({ json: async () => { if (!db) { const Sqlite3 = globalThis.require === undefined ? (await import('better-sqlite3')).default : globalThis.require("better-sqlite3"); db = new Sqlite3(":memory:"); } const req = JSON.parse(options.body); const prepare = db.prepare(req.sql); let results; let meta; try { results = prepare.all(req.params || []); } catch (error) { if (error.message.includes("Use run() instead")) { meta = prepare.run(req.params || []); } else return Promise.reject(Error(error.message)); } return Promise.resolve({ success: true, result: [ { results, meta } ] }); } }); }; var MockedCloudflareD1HttpClient = class extends CloudflareD1HttpClient { constructor() { super({ connection: { account_id: "", database_id: "", key: "", mockedFetch } }); } }; var mock_default = MockedCloudflareD1HttpClient; exports.MockedCloudflareD1HttpClient = MockedCloudflareD1HttpClient; exports.default = mock_default; exports.mockedFetch = mockedFetch;