Skip to content
This repository was archived by the owner on Mar 3, 2024. It is now read-only.

Commit e089487

Browse files
committed
fix: make postgres adapter work
1 parent bc14935 commit e089487

File tree

5 files changed

+41
-90
lines changed

5 files changed

+41
-90
lines changed

src/adapters/postgresql-adapter.ts

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,65 @@ import postgres, { JSONValue } from "postgres";
22
import { IDatabaseAdapter } from "../interfaces/database-adapter";
33

44
export class PostgreSQLAdapter implements IDatabaseAdapter {
5-
private _url: string | undefined;
6-
private _sql: postgres.Sql<{}> | undefined;
5+
private async _connect(url: string): Promise<postgres.Sql<{}>> {
6+
// note(clouedoc): there is a bug where postgres:// URLs are not working in Obsidian env, for some reason.
7+
// (I think the issue is that the protocol is not recognized)
8+
url = url.replace("postgres://", "http://");
9+
url = url.replace("postgresql://", "http://");
710

8-
public async ensureConnection(url: string): Promise<void> {
9-
console.log("Connecting to PostgreSQL database at " + url);
10-
if (this._url === url && this._sql) {
11-
return;
12-
}
13-
14-
this._url = url;
15-
if (this._sql) {
16-
await this._sql.end();
17-
this._sql = undefined;
18-
}
11+
console.log("Connecting to URL: " + url);
12+
const connUrl: URL = new URL(url);
1913

20-
this._sql = postgres(url, {
14+
console.log(connUrl);
15+
return postgres(url, {
2116
prepare: false,
2217
types: {
2318
bigint: postgres.BigInt,
2419
},
2520
});
26-
console.log("Connected to PostgreSQL database at " + url);
2721
}
2822

2923
/**
3024
* Create the initial schema if not existing already.
3125
*/
32-
public async createInitialSchema(): Promise<void> {
26+
public async migrate(url: string): Promise<void> {
3327
console.log("Creating initial schema");
34-
if (!this._sql) {
35-
throw new Error("Not connected");
36-
}
37-
await this._sql`CREATE SCHEMA IF NOT EXISTS obsidian`;
38-
await this._sql`CREATE TABLE IF NOT EXISTS obsidian.file (
28+
// eslint-disable-next-line @typescript-eslint/typedef
29+
const sql = await this._connect(url);
30+
try {
31+
await sql`CREATE SCHEMA IF NOT EXISTS obsidian`;
32+
await sql`CREATE TABLE IF NOT EXISTS obsidian.file (
3933
path text PRIMARY KEY,
4034
dataview_data json
4135
);`;
42-
console.log("Created initial schema");
36+
console.log("Created initial schema");
37+
} finally {
38+
await sql.end();
39+
}
4340
}
4441

4542
public async insertPage(
43+
url: string,
4644
path: string,
4745
data: Record<string, unknown>
4846
): Promise<void> {
49-
console.log("Inserting page " + path);
50-
if (!this._sql) {
51-
throw new Error("Not connected");
52-
}
47+
// eslint-disable-next-line @typescript-eslint/typedef
48+
const sql = await this._connect(url);
5349

54-
await this._sql`INSERT INTO obsidian.file
55-
${this._sql({
50+
try {
51+
await sql`INSERT INTO obsidian.file
52+
${sql({
5653
path,
57-
dataview_data: this._sql.json(data as JSONValue),
54+
dataview_data: sql.json(data as JSONValue),
5855
})}
5956
ON CONFLICT (path)
6057
DO
6158
UPDATE SET dataview_data = EXCLUDED.dataview_data
6259
;
6360
`;
64-
console.log("Inserted page " + path);
65-
}
66-
67-
public async end(): Promise<void> {
68-
if (this._sql) {
69-
await this._sql.end();
70-
this._sql = undefined;
61+
console.log("Inserted page " + path);
62+
} finally {
63+
await sql.end();
7164
}
7265
}
7366
}

src/classes/postgresql-plugin.ts

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ export class PostgreSQLPlugin extends Plugin {
2121
name: "PostgreSQL: upload current file information",
2222
callback: async () => {
2323
// ensure that an adapter is connected
24-
const adapter: IDatabaseAdapter = await this._ensureAdapter();
24+
const adapter: IDatabaseAdapter = await constructAdapter(
25+
this.settings.adapterName
26+
);
2527

2628
const dv: DataviewApi | undefined = getAPI();
2729
if (!dv) {
@@ -52,7 +54,12 @@ export class PostgreSQLPlugin extends Plugin {
5254
delete dataviewData.position;
5355

5456
try {
55-
await adapter.insertPage(filepath, dataviewData);
57+
await adapter.migrate(this.settings.connectionUrl);
58+
await adapter.insertPage(
59+
this.settings.connectionUrl,
60+
filepath,
61+
dataviewData
62+
);
5663
// eslint-disable-next-line no-new
5764
new Notice(`${this.settings.adapterName}: Inserted page`);
5865
} catch (err) {
@@ -63,10 +70,6 @@ export class PostgreSQLPlugin extends Plugin {
6370
});
6471
}
6572

66-
public async onunload(): Promise<void> {
67-
await this._disconnectAdapter();
68-
}
69-
7073
public async loadSettings(): Promise<void> {
7174
this.settings = Object.assign(
7275
{},
@@ -75,39 +78,8 @@ export class PostgreSQLPlugin extends Plugin {
7578
);
7679
}
7780

78-
/**
79-
* Disconnect the underlying database adapter.
80-
* Note: won't do anything if the adapter is not connected.
81-
*/
82-
private async _disconnectAdapter(): Promise<void> {
83-
if (this._adapter) {
84-
await this._adapter.end();
85-
this._adapter = undefined;
86-
}
87-
}
88-
89-
/**
90-
* Ensure that a database adapter is connected.
91-
*/
92-
private async _ensureAdapter(): Promise<IDatabaseAdapter> {
93-
await this._disconnectAdapter();
94-
this._adapter = await constructAdapter(
95-
this.settings.adapterName,
96-
this.settings.connectionUrl
97-
);
98-
return this._adapter;
99-
}
100-
10181
public async saveSettings(): Promise<void> {
10282
// FIXME: debounce this function
10383
await this.saveData(this.settings);
104-
try {
105-
await this._ensureAdapter();
106-
} catch (err) {
107-
// eslint-disable-next-line no-new
108-
new Notice(
109-
`${this.settings.adapterName} instantiation error: ${err}`
110-
);
111-
}
11284
}
11385
}

src/functions/construct-adapter.spec.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import { constructAdapter } from "./construct-adapter";
33

44
it.skip("can construct a PostgreSQL adapter", async () => {
55
await expect(
6-
constructAdapter(
7-
AdapterName.PostgreSQL,
8-
"postgres://gitpod:1234@localhost:5432/postgres"
9-
)
6+
constructAdapter(AdapterName.PostgreSQL)
107
).resolves.not.toThrow();
118
});

src/functions/construct-adapter.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,8 @@ const adapters: Record<AdapterName, IDatabaseAdapter> = {
1111
* @returns
1212
*/
1313
export async function constructAdapter(
14-
name: AdapterName,
15-
url: string
14+
name: AdapterName
1615
): Promise<IDatabaseAdapter> {
1716
const adapter: IDatabaseAdapter = adapters[name];
18-
try {
19-
await adapter.ensureConnection(url);
20-
} catch (err) {
21-
throw new Error("Error while ensuring connection: " + err);
22-
}
23-
try {
24-
await adapter.createInitialSchema();
25-
} catch (err) {
26-
throw new Error("Error while creating initial schema: " + err);
27-
}
2817
return adapter;
2918
}

src/interfaces/database-adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export interface IDatabaseAdapter {
22
/**
33
* Create the initial schema of the database, if required
44
*/
5-
createInitialSchema: (url: string) => Promise<void>;
5+
migrate: (url: string) => Promise<void>;
66
/**
77
* Insert a page into the database
88
*/

0 commit comments

Comments
 (0)