Skip to content

Commit

Permalink
feat: add posgresql connector
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed May 19, 2023
1 parent 6c5a07d commit 51823eb
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 2 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
POSTGRESQL_URL=postgresql://<user>:@localhost:5432/sql0
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ tmp
__*
.data
.tmp
.env
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.4",
"@types/pg": "^8.6.6",
"@vitest/coverage-c8": "^0.31.1",
"better-sqlite3": "^8.3.0",
"changelogen": "^0.5.3",
"dotenv": "^16.0.3",
"eslint": "^8.40.0",
"eslint-config-unjs": "^0.1.0",
"jiti": "^1.18.2",
"pg": "^8.11.0",
"prettier": "^2.8.8",
"typescript": "^5.0.4",
"unbuild": "^1.2.1",
Expand Down
122 changes: 122 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions src/connectors/postgresql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Client, ClientConfig, Query } from "pg";

import type { Connector, Statement } from "../types";

export type ConnectorOptions = { url: string } | ClientConfig;

export default function sqliteConnector(opts: ConnectorOptions) {

This comment has been minimized.

Copy link
@benmerckx

benmerckx Mar 15, 2024

I think this function name needs an update :)

let _client: undefined | Client | Promise<Client>;
function getClient() {
if (_client) {
return _client;
}
const client = new Client("url" in opts ? opts.url : opts);
_client = client.connect().then(() => {
_client = client;
return _client;
});
return _client;
}

async function query(sql: string, params?: unknown[]) {
const client = await getClient();
return client.query(normalizeParams(sql), params);
}

return <Connector>{
name: "postgresql",
exec(sql: string) {
return query(sql);
},
prepare(sql: string) {
const stmt = <Statement>{
_sql: sql,
_params: [],
bind(...params) {
if (params.length > 0) {
this._params = params;
}
return stmt;
},
all(...params) {
return query(this._sql, params || this._params).then((r) => r.rows);
},
run(...params) {
return query(this._sql, params || this._params).then((r) => ({
result: r,
}));
},
get(...params) {
// TODO: Append limit?
return query(this._sql, params || this._params).then(
(r) => r.rows[0]
);
},
};
return stmt;
},
};
}

// https://www.postgresql.org/docs/9.3/sql-prepare.html
function normalizeParams(sql: string) {
let i = 0;
return sql.replace(/\?/g, () => `$${++i}`);
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from "./types";

export const connectors = {
sqlite: "sql0/connectors/better-sqlite3",
postgresql: "sql0/connectors/postgresql",
} as const;

export type ConnectorName = keyof typeof connectors;
5 changes: 3 additions & 2 deletions test/connectors/_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ export function testConnector(opts: { connector: Connector }) {
db = createDatabase(opts.connector);
});

it("create table", async () => {
it("drop and create table", async () => {
await db.exec(`DROP TABLE IF EXISTS users`);
const res = await db.exec(
"CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, firstName TEXT, lastName TEXT, email TEXT)"
`CREATE TABLE users ("id" TEXT PRIMARY KEY, "firstName" TEXT, "lastName" TEXT, "email" TEXT)`
);
expect(res).toBeDefined();
});
Expand Down
14 changes: 14 additions & 0 deletions test/connectors/postgresql.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { describe } from "vitest";
import connector from "../../src/connectors/postgresql";
import { testConnector } from "./_tests";

describe.runIf(process.env.POSTGRESQL_URL)(
"connectors: postgresql.test",
() => {
testConnector({
connector: connector({
url: process.env.POSTGRESQL_URL!,
}),
});
}
);
7 changes: 7 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
setupFiles: ["dotenv/config"],
},
});

0 comments on commit 51823eb

Please sign in to comment.