@mtcute/postgres 0.29.1 → 0.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -3
- package/driver.cjs +4 -2
- package/driver.d.cts +8 -1
- package/driver.d.ts +8 -1
- package/driver.js +4 -2
- package/package.json +1 -1
- package/repository/auth-keys.cjs +33 -15
- package/repository/auth-keys.d.cts +1 -0
- package/repository/auth-keys.d.ts +1 -0
- package/repository/auth-keys.js +33 -15
- package/repository/kv.cjs +20 -5
- package/repository/kv.d.cts +1 -0
- package/repository/kv.d.ts +1 -0
- package/repository/kv.js +20 -5
- package/repository/peers.cjs +24 -10
- package/repository/peers.d.cts +1 -0
- package/repository/peers.d.ts +1 -0
- package/repository/peers.js +24 -10
- package/repository/ref-messages.cjs +21 -8
- package/repository/ref-messages.d.cts +1 -0
- package/repository/ref-messages.d.ts +1 -0
- package/repository/ref-messages.js +21 -8
package/README.md
CHANGED
|
@@ -35,9 +35,30 @@ console.log(`logged in as ${self.displayName}`)
|
|
|
35
35
|
new PostgresStorage(pool, {
|
|
36
36
|
// PostgreSQL schema to use for all tables (default: 'mtcute')
|
|
37
37
|
schema: 'my_schema',
|
|
38
|
-
// Whether to automatically close the client when the storage is destroyed (default:
|
|
38
|
+
// Whether to automatically close the client when the storage is destroyed (default: false)
|
|
39
39
|
// Calls .end(), .release(), or .close() depending on what the client supports
|
|
40
40
|
autoClose: true,
|
|
41
|
+
// Account tag for multi-account isolation within the same schema (default: 'default')
|
|
42
|
+
account: 'bot-1',
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Multi-account
|
|
47
|
+
|
|
48
|
+
Multiple clients can share the same database and schema by using different `account` tags.
|
|
49
|
+
Each account's data is fully isolated from others:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const pool = new pg.Pool({ connectionString: 'postgres://localhost/mydb' })
|
|
53
|
+
|
|
54
|
+
const bot1 = new TelegramClient({
|
|
55
|
+
storage: new PostgresStorage(pool, { account: 'bot-1' }),
|
|
56
|
+
// ...
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const bot2 = new TelegramClient({
|
|
60
|
+
storage: new PostgresStorage(pool, { account: 'bot-2' }),
|
|
61
|
+
// ...
|
|
41
62
|
})
|
|
42
63
|
```
|
|
43
64
|
|
|
@@ -72,8 +93,8 @@ const poolClient = await pool.connect()
|
|
|
72
93
|
const storage = new PostgresStorage(poolClient)
|
|
73
94
|
```
|
|
74
95
|
|
|
75
|
-
> **Note:** By default, mtcute
|
|
76
|
-
>
|
|
96
|
+
> **Note:** By default, mtcute does **not** close the client when the storage is destroyed.
|
|
97
|
+
> Set `autoClose: true` if you want the storage to call `.end()`, `.release()`, or `.close()` automatically.
|
|
77
98
|
|
|
78
99
|
## Database schema
|
|
79
100
|
|
package/driver.cjs
CHANGED
|
@@ -9,16 +9,18 @@ const core = require("@mtcute/core");
|
|
|
9
9
|
class PostgresStorageDriver extends core.BaseStorageDriver {
|
|
10
10
|
client;
|
|
11
11
|
schema;
|
|
12
|
+
account;
|
|
12
13
|
_cleanup;
|
|
13
14
|
_migrations = /* @__PURE__ */ new Map();
|
|
14
15
|
_maxVersion = /* @__PURE__ */ new Map();
|
|
15
16
|
_onLoadCallbacks = /* @__PURE__ */ new Set();
|
|
16
|
-
_autoClose =
|
|
17
|
+
_autoClose = false;
|
|
17
18
|
constructor(client, options) {
|
|
18
19
|
super();
|
|
19
20
|
this.client = client;
|
|
20
21
|
this.schema = options?.schema ?? "mtcute";
|
|
21
|
-
this.
|
|
22
|
+
this.account = options?.account ?? "default";
|
|
23
|
+
this._autoClose = options?.autoClose ?? false;
|
|
22
24
|
}
|
|
23
25
|
/** Returns a schema-qualified table name, safe for interpolation into SQL */
|
|
24
26
|
tableName(name) {
|
package/driver.d.cts
CHANGED
|
@@ -23,13 +23,20 @@ export interface PostgresStorageDriverOptions {
|
|
|
23
23
|
/**
|
|
24
24
|
* Whether to automatically close the client when the driver is destroyed.
|
|
25
25
|
*
|
|
26
|
-
* @default
|
|
26
|
+
* @default false
|
|
27
27
|
*/
|
|
28
28
|
autoClose?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Account tag used to isolate data when multiple clients share the same database and schema.
|
|
31
|
+
*
|
|
32
|
+
* @default 'default'
|
|
33
|
+
*/
|
|
34
|
+
account?: string;
|
|
29
35
|
}
|
|
30
36
|
export declare class PostgresStorageDriver extends BaseStorageDriver {
|
|
31
37
|
readonly client: PgClient;
|
|
32
38
|
readonly schema: string;
|
|
39
|
+
readonly account: string;
|
|
33
40
|
private _cleanup?;
|
|
34
41
|
private _migrations;
|
|
35
42
|
private _maxVersion;
|
package/driver.d.ts
CHANGED
|
@@ -23,13 +23,20 @@ export interface PostgresStorageDriverOptions {
|
|
|
23
23
|
/**
|
|
24
24
|
* Whether to automatically close the client when the driver is destroyed.
|
|
25
25
|
*
|
|
26
|
-
* @default
|
|
26
|
+
* @default false
|
|
27
27
|
*/
|
|
28
28
|
autoClose?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Account tag used to isolate data when multiple clients share the same database and schema.
|
|
31
|
+
*
|
|
32
|
+
* @default 'default'
|
|
33
|
+
*/
|
|
34
|
+
account?: string;
|
|
29
35
|
}
|
|
30
36
|
export declare class PostgresStorageDriver extends BaseStorageDriver {
|
|
31
37
|
readonly client: PgClient;
|
|
32
38
|
readonly schema: string;
|
|
39
|
+
readonly account: string;
|
|
33
40
|
private _cleanup?;
|
|
34
41
|
private _migrations;
|
|
35
42
|
private _maxVersion;
|
package/driver.js
CHANGED
|
@@ -2,16 +2,18 @@ import { BaseStorageDriver } from "@mtcute/core";
|
|
|
2
2
|
class PostgresStorageDriver extends BaseStorageDriver {
|
|
3
3
|
client;
|
|
4
4
|
schema;
|
|
5
|
+
account;
|
|
5
6
|
_cleanup;
|
|
6
7
|
_migrations = /* @__PURE__ */ new Map();
|
|
7
8
|
_maxVersion = /* @__PURE__ */ new Map();
|
|
8
9
|
_onLoadCallbacks = /* @__PURE__ */ new Set();
|
|
9
|
-
_autoClose =
|
|
10
|
+
_autoClose = false;
|
|
10
11
|
constructor(client, options) {
|
|
11
12
|
super();
|
|
12
13
|
this.client = client;
|
|
13
14
|
this.schema = options?.schema ?? "mtcute";
|
|
14
|
-
this.
|
|
15
|
+
this.account = options?.account ?? "default";
|
|
16
|
+
this._autoClose = options?.autoClose ?? false;
|
|
15
17
|
}
|
|
16
18
|
/** Returns a schema-qualified table name, safe for interpolation into SQL */
|
|
17
19
|
tableName(name) {
|
package/package.json
CHANGED
package/repository/auth-keys.cjs
CHANGED
|
@@ -27,53 +27,71 @@ class PostgresAuthKeysRepository {
|
|
|
27
27
|
);
|
|
28
28
|
`);
|
|
29
29
|
});
|
|
30
|
+
_driver.registerMigration("auth_keys", 2, async (client) => {
|
|
31
|
+
await client.query(`alter table ${this._authKeys} add column account text not null default 'default'`);
|
|
32
|
+
await client.query(`alter table ${this._authKeys} drop constraint auth_keys_pkey`);
|
|
33
|
+
await client.query(`alter table ${this._authKeys} add primary key (account, dc)`);
|
|
34
|
+
await client.query(`alter table ${this._tempAuthKeys} add column account text not null default 'default'`);
|
|
35
|
+
await client.query(`alter table ${this._tempAuthKeys} drop constraint temp_auth_keys_pkey`);
|
|
36
|
+
await client.query(`alter table ${this._tempAuthKeys} add primary key (account, dc, idx)`);
|
|
37
|
+
});
|
|
30
38
|
}
|
|
31
39
|
_authKeys;
|
|
32
40
|
_tempAuthKeys;
|
|
41
|
+
get _account() {
|
|
42
|
+
return this._driver.account;
|
|
43
|
+
}
|
|
33
44
|
async set(dc, key) {
|
|
34
45
|
if (!key) {
|
|
35
|
-
await this._driver.client.query(
|
|
46
|
+
await this._driver.client.query(
|
|
47
|
+
`delete from ${this._authKeys} where account = $1 and dc = $2`,
|
|
48
|
+
[this._account, dc]
|
|
49
|
+
);
|
|
36
50
|
return;
|
|
37
51
|
}
|
|
38
52
|
await this._driver.client.query(
|
|
39
|
-
`insert into ${this._authKeys} (dc, key) values ($1, $2
|
|
40
|
-
|
|
53
|
+
`insert into ${this._authKeys} (account, dc, key) values ($1, $2, $3)
|
|
54
|
+
on conflict (account, dc) do update set key = $3`,
|
|
55
|
+
[this._account, dc, key]
|
|
41
56
|
);
|
|
42
57
|
}
|
|
43
58
|
async get(dc) {
|
|
44
|
-
const res = await this._driver.client.query(
|
|
59
|
+
const res = await this._driver.client.query(
|
|
60
|
+
`select key from ${this._authKeys} where account = $1 and dc = $2`,
|
|
61
|
+
[this._account, dc]
|
|
62
|
+
);
|
|
45
63
|
if (!res.rows[0]) return null;
|
|
46
64
|
return new Uint8Array(res.rows[0].key);
|
|
47
65
|
}
|
|
48
66
|
async setTemp(dc, idx, key, expires) {
|
|
49
67
|
if (!key) {
|
|
50
68
|
await this._driver.client.query(
|
|
51
|
-
`delete from ${this._tempAuthKeys} where
|
|
52
|
-
[dc, idx]
|
|
69
|
+
`delete from ${this._tempAuthKeys} where account = $1 and dc = $2 and idx = $3`,
|
|
70
|
+
[this._account, dc, idx]
|
|
53
71
|
);
|
|
54
72
|
return;
|
|
55
73
|
}
|
|
56
74
|
await this._driver.client.query(
|
|
57
|
-
`insert into ${this._tempAuthKeys} (dc, idx, key, expires) values ($1, $2, $3, $4)
|
|
58
|
-
on conflict (dc, idx) do update set key = $
|
|
59
|
-
[dc, idx, key, expires]
|
|
75
|
+
`insert into ${this._tempAuthKeys} (account, dc, idx, key, expires) values ($1, $2, $3, $4, $5)
|
|
76
|
+
on conflict (account, dc, idx) do update set key = $4, expires = $5`,
|
|
77
|
+
[this._account, dc, idx, key, expires]
|
|
60
78
|
);
|
|
61
79
|
}
|
|
62
80
|
async getTemp(dc, idx, now) {
|
|
63
81
|
const res = await this._driver.client.query(
|
|
64
|
-
`select key from ${this._tempAuthKeys} where
|
|
65
|
-
[dc, idx, now]
|
|
82
|
+
`select key from ${this._tempAuthKeys} where account = $1 and dc = $2 and idx = $3 and expires > $4`,
|
|
83
|
+
[this._account, dc, idx, now]
|
|
66
84
|
);
|
|
67
85
|
if (!res.rows[0]) return null;
|
|
68
86
|
return new Uint8Array(res.rows[0].key);
|
|
69
87
|
}
|
|
70
88
|
async deleteByDc(dc) {
|
|
71
|
-
await this._driver.client.query(`delete from ${this._authKeys} where dc = $
|
|
72
|
-
await this._driver.client.query(`delete from ${this._tempAuthKeys} where dc = $
|
|
89
|
+
await this._driver.client.query(`delete from ${this._authKeys} where account = $1 and dc = $2`, [this._account, dc]);
|
|
90
|
+
await this._driver.client.query(`delete from ${this._tempAuthKeys} where account = $1 and dc = $2`, [this._account, dc]);
|
|
73
91
|
}
|
|
74
92
|
async deleteAll() {
|
|
75
|
-
await this._driver.client.query(`delete from ${this._authKeys}
|
|
76
|
-
await this._driver.client.query(`delete from ${this._tempAuthKeys}
|
|
93
|
+
await this._driver.client.query(`delete from ${this._authKeys} where account = $1`, [this._account]);
|
|
94
|
+
await this._driver.client.query(`delete from ${this._tempAuthKeys} where account = $1`, [this._account]);
|
|
77
95
|
}
|
|
78
96
|
}
|
|
79
97
|
exports.PostgresAuthKeysRepository = PostgresAuthKeysRepository;
|
|
@@ -5,6 +5,7 @@ export declare class PostgresAuthKeysRepository implements IAuthKeysRepository {
|
|
|
5
5
|
private _authKeys;
|
|
6
6
|
private _tempAuthKeys;
|
|
7
7
|
constructor(_driver: PostgresStorageDriver);
|
|
8
|
+
private get _account();
|
|
8
9
|
set(dc: number, key: Uint8Array | null): Promise<void>;
|
|
9
10
|
get(dc: number): Promise<Uint8Array | null>;
|
|
10
11
|
setTemp(dc: number, idx: number, key: Uint8Array | null, expires: number): Promise<void>;
|
|
@@ -5,6 +5,7 @@ export declare class PostgresAuthKeysRepository implements IAuthKeysRepository {
|
|
|
5
5
|
private _authKeys;
|
|
6
6
|
private _tempAuthKeys;
|
|
7
7
|
constructor(_driver: PostgresStorageDriver);
|
|
8
|
+
private get _account();
|
|
8
9
|
set(dc: number, key: Uint8Array | null): Promise<void>;
|
|
9
10
|
get(dc: number): Promise<Uint8Array | null>;
|
|
10
11
|
setTemp(dc: number, idx: number, key: Uint8Array | null, expires: number): Promise<void>;
|
package/repository/auth-keys.js
CHANGED
|
@@ -20,53 +20,71 @@ class PostgresAuthKeysRepository {
|
|
|
20
20
|
);
|
|
21
21
|
`);
|
|
22
22
|
});
|
|
23
|
+
_driver.registerMigration("auth_keys", 2, async (client) => {
|
|
24
|
+
await client.query(`alter table ${this._authKeys} add column account text not null default 'default'`);
|
|
25
|
+
await client.query(`alter table ${this._authKeys} drop constraint auth_keys_pkey`);
|
|
26
|
+
await client.query(`alter table ${this._authKeys} add primary key (account, dc)`);
|
|
27
|
+
await client.query(`alter table ${this._tempAuthKeys} add column account text not null default 'default'`);
|
|
28
|
+
await client.query(`alter table ${this._tempAuthKeys} drop constraint temp_auth_keys_pkey`);
|
|
29
|
+
await client.query(`alter table ${this._tempAuthKeys} add primary key (account, dc, idx)`);
|
|
30
|
+
});
|
|
23
31
|
}
|
|
24
32
|
_authKeys;
|
|
25
33
|
_tempAuthKeys;
|
|
34
|
+
get _account() {
|
|
35
|
+
return this._driver.account;
|
|
36
|
+
}
|
|
26
37
|
async set(dc, key) {
|
|
27
38
|
if (!key) {
|
|
28
|
-
await this._driver.client.query(
|
|
39
|
+
await this._driver.client.query(
|
|
40
|
+
`delete from ${this._authKeys} where account = $1 and dc = $2`,
|
|
41
|
+
[this._account, dc]
|
|
42
|
+
);
|
|
29
43
|
return;
|
|
30
44
|
}
|
|
31
45
|
await this._driver.client.query(
|
|
32
|
-
`insert into ${this._authKeys} (dc, key) values ($1, $2
|
|
33
|
-
|
|
46
|
+
`insert into ${this._authKeys} (account, dc, key) values ($1, $2, $3)
|
|
47
|
+
on conflict (account, dc) do update set key = $3`,
|
|
48
|
+
[this._account, dc, key]
|
|
34
49
|
);
|
|
35
50
|
}
|
|
36
51
|
async get(dc) {
|
|
37
|
-
const res = await this._driver.client.query(
|
|
52
|
+
const res = await this._driver.client.query(
|
|
53
|
+
`select key from ${this._authKeys} where account = $1 and dc = $2`,
|
|
54
|
+
[this._account, dc]
|
|
55
|
+
);
|
|
38
56
|
if (!res.rows[0]) return null;
|
|
39
57
|
return new Uint8Array(res.rows[0].key);
|
|
40
58
|
}
|
|
41
59
|
async setTemp(dc, idx, key, expires) {
|
|
42
60
|
if (!key) {
|
|
43
61
|
await this._driver.client.query(
|
|
44
|
-
`delete from ${this._tempAuthKeys} where
|
|
45
|
-
[dc, idx]
|
|
62
|
+
`delete from ${this._tempAuthKeys} where account = $1 and dc = $2 and idx = $3`,
|
|
63
|
+
[this._account, dc, idx]
|
|
46
64
|
);
|
|
47
65
|
return;
|
|
48
66
|
}
|
|
49
67
|
await this._driver.client.query(
|
|
50
|
-
`insert into ${this._tempAuthKeys} (dc, idx, key, expires) values ($1, $2, $3, $4)
|
|
51
|
-
on conflict (dc, idx) do update set key = $
|
|
52
|
-
[dc, idx, key, expires]
|
|
68
|
+
`insert into ${this._tempAuthKeys} (account, dc, idx, key, expires) values ($1, $2, $3, $4, $5)
|
|
69
|
+
on conflict (account, dc, idx) do update set key = $4, expires = $5`,
|
|
70
|
+
[this._account, dc, idx, key, expires]
|
|
53
71
|
);
|
|
54
72
|
}
|
|
55
73
|
async getTemp(dc, idx, now) {
|
|
56
74
|
const res = await this._driver.client.query(
|
|
57
|
-
`select key from ${this._tempAuthKeys} where
|
|
58
|
-
[dc, idx, now]
|
|
75
|
+
`select key from ${this._tempAuthKeys} where account = $1 and dc = $2 and idx = $3 and expires > $4`,
|
|
76
|
+
[this._account, dc, idx, now]
|
|
59
77
|
);
|
|
60
78
|
if (!res.rows[0]) return null;
|
|
61
79
|
return new Uint8Array(res.rows[0].key);
|
|
62
80
|
}
|
|
63
81
|
async deleteByDc(dc) {
|
|
64
|
-
await this._driver.client.query(`delete from ${this._authKeys} where dc = $
|
|
65
|
-
await this._driver.client.query(`delete from ${this._tempAuthKeys} where dc = $
|
|
82
|
+
await this._driver.client.query(`delete from ${this._authKeys} where account = $1 and dc = $2`, [this._account, dc]);
|
|
83
|
+
await this._driver.client.query(`delete from ${this._tempAuthKeys} where account = $1 and dc = $2`, [this._account, dc]);
|
|
66
84
|
}
|
|
67
85
|
async deleteAll() {
|
|
68
|
-
await this._driver.client.query(`delete from ${this._authKeys}
|
|
69
|
-
await this._driver.client.query(`delete from ${this._tempAuthKeys}
|
|
86
|
+
await this._driver.client.query(`delete from ${this._authKeys} where account = $1`, [this._account]);
|
|
87
|
+
await this._driver.client.query(`delete from ${this._tempAuthKeys} where account = $1`, [this._account]);
|
|
70
88
|
}
|
|
71
89
|
}
|
|
72
90
|
export {
|
package/repository/kv.cjs
CHANGED
|
@@ -17,24 +17,39 @@ class PostgresKeyValueRepository {
|
|
|
17
17
|
);
|
|
18
18
|
`);
|
|
19
19
|
});
|
|
20
|
+
_driver.registerMigration("kv", 2, async (client) => {
|
|
21
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
22
|
+
await client.query(`alter table ${this._table} drop constraint key_value_pkey`);
|
|
23
|
+
await client.query(`alter table ${this._table} add primary key (account, key)`);
|
|
24
|
+
});
|
|
20
25
|
}
|
|
21
26
|
_table;
|
|
27
|
+
get _account() {
|
|
28
|
+
return this._driver.account;
|
|
29
|
+
}
|
|
22
30
|
async set(key, value) {
|
|
23
31
|
await this._driver.client.query(
|
|
24
|
-
`insert into ${this._table} (key, value) values ($1, $2
|
|
25
|
-
|
|
32
|
+
`insert into ${this._table} (account, key, value) values ($1, $2, $3)
|
|
33
|
+
on conflict (account, key) do update set value = $3`,
|
|
34
|
+
[this._account, key, value]
|
|
26
35
|
);
|
|
27
36
|
}
|
|
28
37
|
async get(key) {
|
|
29
|
-
const res = await this._driver.client.query(
|
|
38
|
+
const res = await this._driver.client.query(
|
|
39
|
+
`select value from ${this._table} where account = $1 and key = $2`,
|
|
40
|
+
[this._account, key]
|
|
41
|
+
);
|
|
30
42
|
if (!res.rows[0]) return null;
|
|
31
43
|
return new Uint8Array(res.rows[0].value);
|
|
32
44
|
}
|
|
33
45
|
async delete(key) {
|
|
34
|
-
await this._driver.client.query(
|
|
46
|
+
await this._driver.client.query(
|
|
47
|
+
`delete from ${this._table} where account = $1 and key = $2`,
|
|
48
|
+
[this._account, key]
|
|
49
|
+
);
|
|
35
50
|
}
|
|
36
51
|
async deleteAll() {
|
|
37
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
52
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
38
53
|
}
|
|
39
54
|
}
|
|
40
55
|
exports.PostgresKeyValueRepository = PostgresKeyValueRepository;
|
package/repository/kv.d.cts
CHANGED
|
@@ -4,6 +4,7 @@ export declare class PostgresKeyValueRepository implements IKeyValueRepository {
|
|
|
4
4
|
readonly _driver: PostgresStorageDriver;
|
|
5
5
|
private _table;
|
|
6
6
|
constructor(_driver: PostgresStorageDriver);
|
|
7
|
+
private get _account();
|
|
7
8
|
set(key: string, value: Uint8Array): Promise<void>;
|
|
8
9
|
get(key: string): Promise<Uint8Array | null>;
|
|
9
10
|
delete(key: string): Promise<void>;
|
package/repository/kv.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare class PostgresKeyValueRepository implements IKeyValueRepository {
|
|
|
4
4
|
readonly _driver: PostgresStorageDriver;
|
|
5
5
|
private _table;
|
|
6
6
|
constructor(_driver: PostgresStorageDriver);
|
|
7
|
+
private get _account();
|
|
7
8
|
set(key: string, value: Uint8Array): Promise<void>;
|
|
8
9
|
get(key: string): Promise<Uint8Array | null>;
|
|
9
10
|
delete(key: string): Promise<void>;
|
package/repository/kv.js
CHANGED
|
@@ -10,24 +10,39 @@ class PostgresKeyValueRepository {
|
|
|
10
10
|
);
|
|
11
11
|
`);
|
|
12
12
|
});
|
|
13
|
+
_driver.registerMigration("kv", 2, async (client) => {
|
|
14
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
15
|
+
await client.query(`alter table ${this._table} drop constraint key_value_pkey`);
|
|
16
|
+
await client.query(`alter table ${this._table} add primary key (account, key)`);
|
|
17
|
+
});
|
|
13
18
|
}
|
|
14
19
|
_table;
|
|
20
|
+
get _account() {
|
|
21
|
+
return this._driver.account;
|
|
22
|
+
}
|
|
15
23
|
async set(key, value) {
|
|
16
24
|
await this._driver.client.query(
|
|
17
|
-
`insert into ${this._table} (key, value) values ($1, $2
|
|
18
|
-
|
|
25
|
+
`insert into ${this._table} (account, key, value) values ($1, $2, $3)
|
|
26
|
+
on conflict (account, key) do update set value = $3`,
|
|
27
|
+
[this._account, key, value]
|
|
19
28
|
);
|
|
20
29
|
}
|
|
21
30
|
async get(key) {
|
|
22
|
-
const res = await this._driver.client.query(
|
|
31
|
+
const res = await this._driver.client.query(
|
|
32
|
+
`select value from ${this._table} where account = $1 and key = $2`,
|
|
33
|
+
[this._account, key]
|
|
34
|
+
);
|
|
23
35
|
if (!res.rows[0]) return null;
|
|
24
36
|
return new Uint8Array(res.rows[0].value);
|
|
25
37
|
}
|
|
26
38
|
async delete(key) {
|
|
27
|
-
await this._driver.client.query(
|
|
39
|
+
await this._driver.client.query(
|
|
40
|
+
`delete from ${this._table} where account = $1 and key = $2`,
|
|
41
|
+
[this._account, key]
|
|
42
|
+
);
|
|
28
43
|
}
|
|
29
44
|
async deleteAll() {
|
|
30
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
45
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
31
46
|
}
|
|
32
47
|
}
|
|
33
48
|
export {
|
package/repository/peers.cjs
CHANGED
|
@@ -38,12 +38,22 @@ class PostgresPeersRepository {
|
|
|
38
38
|
create index if not exists idx_peers_phone on ${this._table} (phone);
|
|
39
39
|
`);
|
|
40
40
|
});
|
|
41
|
+
_driver.registerMigration("peers", 2, async (client) => {
|
|
42
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
43
|
+
await client.query(`alter table ${this._table} drop constraint peers_pkey`);
|
|
44
|
+
await client.query(`alter table ${this._table} add primary key (account, id)`);
|
|
45
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_peers_phone")}`);
|
|
46
|
+
await client.query(`create index idx_peers_phone on ${this._table} (account, phone)`);
|
|
47
|
+
});
|
|
41
48
|
_driver.onLoad(() => {
|
|
42
49
|
this._loaded = true;
|
|
43
50
|
});
|
|
44
51
|
}
|
|
45
52
|
_loaded = false;
|
|
46
53
|
_table;
|
|
54
|
+
get _account() {
|
|
55
|
+
return this._driver.account;
|
|
56
|
+
}
|
|
47
57
|
_ensureLoaded() {
|
|
48
58
|
if (!this._loaded) {
|
|
49
59
|
throw new core.MtcuteError("Peers repository is not loaded. Have you called client.start() (or similar)?");
|
|
@@ -51,11 +61,12 @@ class PostgresPeersRepository {
|
|
|
51
61
|
}
|
|
52
62
|
async store(peer) {
|
|
53
63
|
await this._driver.client.query(
|
|
54
|
-
`insert into ${this._table} (id, hash, is_min, usernames, updated, phone, complete)
|
|
55
|
-
values ($1, $2, $3, $4, $5, $6, $7)
|
|
56
|
-
on conflict (id) do update set
|
|
57
|
-
hash = $
|
|
64
|
+
`insert into ${this._table} (account, id, hash, is_min, usernames, updated, phone, complete)
|
|
65
|
+
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
66
|
+
on conflict (account, id) do update set
|
|
67
|
+
hash = $3, is_min = $4, usernames = $5, updated = $6, phone = $7, complete = $8`,
|
|
58
68
|
[
|
|
69
|
+
this._account,
|
|
59
70
|
peer.id,
|
|
60
71
|
peer.accessHash,
|
|
61
72
|
peer.isMin,
|
|
@@ -68,15 +79,18 @@ class PostgresPeersRepository {
|
|
|
68
79
|
}
|
|
69
80
|
async getById(id) {
|
|
70
81
|
this._ensureLoaded();
|
|
71
|
-
const res = await this._driver.client.query(
|
|
82
|
+
const res = await this._driver.client.query(
|
|
83
|
+
`select * from ${this._table} where account = $1 and id = $2`,
|
|
84
|
+
[this._account, id]
|
|
85
|
+
);
|
|
72
86
|
if (!res.rows[0]) return null;
|
|
73
87
|
return mapPeerDto(res.rows[0]);
|
|
74
88
|
}
|
|
75
89
|
async getByUsername(username) {
|
|
76
90
|
this._ensureLoaded();
|
|
77
91
|
const res = await this._driver.client.query(
|
|
78
|
-
`select * from ${this._table} where usernames ? $
|
|
79
|
-
[username]
|
|
92
|
+
`select * from ${this._table} where account = $1 and usernames ? $2 and is_min = false`,
|
|
93
|
+
[this._account, username]
|
|
80
94
|
);
|
|
81
95
|
if (!res.rows[0]) return null;
|
|
82
96
|
return mapPeerDto(res.rows[0]);
|
|
@@ -84,14 +98,14 @@ class PostgresPeersRepository {
|
|
|
84
98
|
async getByPhone(phone) {
|
|
85
99
|
this._ensureLoaded();
|
|
86
100
|
const res = await this._driver.client.query(
|
|
87
|
-
`select * from ${this._table} where
|
|
88
|
-
[phone]
|
|
101
|
+
`select * from ${this._table} where account = $1 and phone = $2 and is_min = false`,
|
|
102
|
+
[this._account, phone]
|
|
89
103
|
);
|
|
90
104
|
if (!res.rows[0]) return null;
|
|
91
105
|
return mapPeerDto(res.rows[0]);
|
|
92
106
|
}
|
|
93
107
|
async deleteAll() {
|
|
94
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
108
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
95
109
|
}
|
|
96
110
|
}
|
|
97
111
|
exports.PostgresPeersRepository = PostgresPeersRepository;
|
package/repository/peers.d.cts
CHANGED
|
@@ -5,6 +5,7 @@ export declare class PostgresPeersRepository implements IPeersRepository {
|
|
|
5
5
|
private _loaded;
|
|
6
6
|
private _table;
|
|
7
7
|
constructor(_driver: PostgresStorageDriver);
|
|
8
|
+
private get _account();
|
|
8
9
|
private _ensureLoaded;
|
|
9
10
|
store(peer: IPeersRepository.PeerInfo): Promise<void>;
|
|
10
11
|
getById(id: number): Promise<IPeersRepository.PeerInfo | null>;
|
package/repository/peers.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare class PostgresPeersRepository implements IPeersRepository {
|
|
|
5
5
|
private _loaded;
|
|
6
6
|
private _table;
|
|
7
7
|
constructor(_driver: PostgresStorageDriver);
|
|
8
|
+
private get _account();
|
|
8
9
|
private _ensureLoaded;
|
|
9
10
|
store(peer: IPeersRepository.PeerInfo): Promise<void>;
|
|
10
11
|
getById(id: number): Promise<IPeersRepository.PeerInfo | null>;
|
package/repository/peers.js
CHANGED
|
@@ -31,12 +31,22 @@ class PostgresPeersRepository {
|
|
|
31
31
|
create index if not exists idx_peers_phone on ${this._table} (phone);
|
|
32
32
|
`);
|
|
33
33
|
});
|
|
34
|
+
_driver.registerMigration("peers", 2, async (client) => {
|
|
35
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
36
|
+
await client.query(`alter table ${this._table} drop constraint peers_pkey`);
|
|
37
|
+
await client.query(`alter table ${this._table} add primary key (account, id)`);
|
|
38
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_peers_phone")}`);
|
|
39
|
+
await client.query(`create index idx_peers_phone on ${this._table} (account, phone)`);
|
|
40
|
+
});
|
|
34
41
|
_driver.onLoad(() => {
|
|
35
42
|
this._loaded = true;
|
|
36
43
|
});
|
|
37
44
|
}
|
|
38
45
|
_loaded = false;
|
|
39
46
|
_table;
|
|
47
|
+
get _account() {
|
|
48
|
+
return this._driver.account;
|
|
49
|
+
}
|
|
40
50
|
_ensureLoaded() {
|
|
41
51
|
if (!this._loaded) {
|
|
42
52
|
throw new MtcuteError("Peers repository is not loaded. Have you called client.start() (or similar)?");
|
|
@@ -44,11 +54,12 @@ class PostgresPeersRepository {
|
|
|
44
54
|
}
|
|
45
55
|
async store(peer) {
|
|
46
56
|
await this._driver.client.query(
|
|
47
|
-
`insert into ${this._table} (id, hash, is_min, usernames, updated, phone, complete)
|
|
48
|
-
values ($1, $2, $3, $4, $5, $6, $7)
|
|
49
|
-
on conflict (id) do update set
|
|
50
|
-
hash = $
|
|
57
|
+
`insert into ${this._table} (account, id, hash, is_min, usernames, updated, phone, complete)
|
|
58
|
+
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
59
|
+
on conflict (account, id) do update set
|
|
60
|
+
hash = $3, is_min = $4, usernames = $5, updated = $6, phone = $7, complete = $8`,
|
|
51
61
|
[
|
|
62
|
+
this._account,
|
|
52
63
|
peer.id,
|
|
53
64
|
peer.accessHash,
|
|
54
65
|
peer.isMin,
|
|
@@ -61,15 +72,18 @@ class PostgresPeersRepository {
|
|
|
61
72
|
}
|
|
62
73
|
async getById(id) {
|
|
63
74
|
this._ensureLoaded();
|
|
64
|
-
const res = await this._driver.client.query(
|
|
75
|
+
const res = await this._driver.client.query(
|
|
76
|
+
`select * from ${this._table} where account = $1 and id = $2`,
|
|
77
|
+
[this._account, id]
|
|
78
|
+
);
|
|
65
79
|
if (!res.rows[0]) return null;
|
|
66
80
|
return mapPeerDto(res.rows[0]);
|
|
67
81
|
}
|
|
68
82
|
async getByUsername(username) {
|
|
69
83
|
this._ensureLoaded();
|
|
70
84
|
const res = await this._driver.client.query(
|
|
71
|
-
`select * from ${this._table} where usernames ? $
|
|
72
|
-
[username]
|
|
85
|
+
`select * from ${this._table} where account = $1 and usernames ? $2 and is_min = false`,
|
|
86
|
+
[this._account, username]
|
|
73
87
|
);
|
|
74
88
|
if (!res.rows[0]) return null;
|
|
75
89
|
return mapPeerDto(res.rows[0]);
|
|
@@ -77,14 +91,14 @@ class PostgresPeersRepository {
|
|
|
77
91
|
async getByPhone(phone) {
|
|
78
92
|
this._ensureLoaded();
|
|
79
93
|
const res = await this._driver.client.query(
|
|
80
|
-
`select * from ${this._table} where
|
|
81
|
-
[phone]
|
|
94
|
+
`select * from ${this._table} where account = $1 and phone = $2 and is_min = false`,
|
|
95
|
+
[this._account, phone]
|
|
82
96
|
);
|
|
83
97
|
if (!res.rows[0]) return null;
|
|
84
98
|
return mapPeerDto(res.rows[0]);
|
|
85
99
|
}
|
|
86
100
|
async deleteAll() {
|
|
87
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
101
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
export {
|
|
@@ -21,18 +21,28 @@ class PostgresRefMessagesRepository {
|
|
|
21
21
|
await client.query(`create index if not exists idx_message_refs_peer on ${this._table} (peer_id);`);
|
|
22
22
|
await client.query(`create index if not exists idx_message_refs on ${this._table} (chat_id, msg_id);`);
|
|
23
23
|
});
|
|
24
|
+
_driver.registerMigration("ref_messages", 2, async (client) => {
|
|
25
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
26
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_message_refs_peer")}`);
|
|
27
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_message_refs")}`);
|
|
28
|
+
await client.query(`create index idx_message_refs_peer on ${this._table} (account, peer_id)`);
|
|
29
|
+
await client.query(`create index idx_message_refs on ${this._table} (account, chat_id, msg_id)`);
|
|
30
|
+
});
|
|
24
31
|
}
|
|
25
32
|
_table;
|
|
33
|
+
get _account() {
|
|
34
|
+
return this._driver.account;
|
|
35
|
+
}
|
|
26
36
|
async store(peerId, chatId, msgId) {
|
|
27
37
|
await this._driver.client.query(
|
|
28
|
-
`insert into ${this._table} (peer_id, chat_id, msg_id) values ($1, $2, $3)`,
|
|
29
|
-
[peerId, chatId, msgId]
|
|
38
|
+
`insert into ${this._table} (account, peer_id, chat_id, msg_id) values ($1, $2, $3, $4)`,
|
|
39
|
+
[this._account, peerId, chatId, msgId]
|
|
30
40
|
);
|
|
31
41
|
}
|
|
32
42
|
async getByPeer(peerId) {
|
|
33
43
|
const res = await this._driver.client.query(
|
|
34
|
-
`select chat_id, msg_id from ${this._table} where
|
|
35
|
-
[peerId]
|
|
44
|
+
`select chat_id, msg_id from ${this._table} where account = $1 and peer_id = $2 limit 1`,
|
|
45
|
+
[this._account, peerId]
|
|
36
46
|
);
|
|
37
47
|
if (!res.rows[0]) return null;
|
|
38
48
|
const row = res.rows[0];
|
|
@@ -41,15 +51,18 @@ class PostgresRefMessagesRepository {
|
|
|
41
51
|
async delete(chatId, msgIds) {
|
|
42
52
|
if (msgIds.length === 0) return;
|
|
43
53
|
await this._driver.client.query(
|
|
44
|
-
`delete from ${this._table} where
|
|
45
|
-
[chatId, msgIds]
|
|
54
|
+
`delete from ${this._table} where account = $1 and chat_id = $2 and msg_id = any($3)`,
|
|
55
|
+
[this._account, chatId, msgIds]
|
|
46
56
|
);
|
|
47
57
|
}
|
|
48
58
|
async deleteByPeer(peerId) {
|
|
49
|
-
await this._driver.client.query(
|
|
59
|
+
await this._driver.client.query(
|
|
60
|
+
`delete from ${this._table} where account = $1 and peer_id = $2`,
|
|
61
|
+
[this._account, peerId]
|
|
62
|
+
);
|
|
50
63
|
}
|
|
51
64
|
async deleteAll() {
|
|
52
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
65
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
53
66
|
}
|
|
54
67
|
}
|
|
55
68
|
exports.PostgresRefMessagesRepository = PostgresRefMessagesRepository;
|
|
@@ -4,6 +4,7 @@ export declare class PostgresRefMessagesRepository implements IReferenceMessages
|
|
|
4
4
|
readonly _driver: PostgresStorageDriver;
|
|
5
5
|
private _table;
|
|
6
6
|
constructor(_driver: PostgresStorageDriver);
|
|
7
|
+
private get _account();
|
|
7
8
|
store(peerId: number, chatId: number, msgId: number): Promise<void>;
|
|
8
9
|
getByPeer(peerId: number): Promise<[number, number] | null>;
|
|
9
10
|
delete(chatId: number, msgIds: number[]): Promise<void>;
|
|
@@ -4,6 +4,7 @@ export declare class PostgresRefMessagesRepository implements IReferenceMessages
|
|
|
4
4
|
readonly _driver: PostgresStorageDriver;
|
|
5
5
|
private _table;
|
|
6
6
|
constructor(_driver: PostgresStorageDriver);
|
|
7
|
+
private get _account();
|
|
7
8
|
store(peerId: number, chatId: number, msgId: number): Promise<void>;
|
|
8
9
|
getByPeer(peerId: number): Promise<[number, number] | null>;
|
|
9
10
|
delete(chatId: number, msgIds: number[]): Promise<void>;
|
|
@@ -14,18 +14,28 @@ class PostgresRefMessagesRepository {
|
|
|
14
14
|
await client.query(`create index if not exists idx_message_refs_peer on ${this._table} (peer_id);`);
|
|
15
15
|
await client.query(`create index if not exists idx_message_refs on ${this._table} (chat_id, msg_id);`);
|
|
16
16
|
});
|
|
17
|
+
_driver.registerMigration("ref_messages", 2, async (client) => {
|
|
18
|
+
await client.query(`alter table ${this._table} add column account text not null default 'default'`);
|
|
19
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_message_refs_peer")}`);
|
|
20
|
+
await client.query(`drop index if exists ${_driver.tableName("idx_message_refs")}`);
|
|
21
|
+
await client.query(`create index idx_message_refs_peer on ${this._table} (account, peer_id)`);
|
|
22
|
+
await client.query(`create index idx_message_refs on ${this._table} (account, chat_id, msg_id)`);
|
|
23
|
+
});
|
|
17
24
|
}
|
|
18
25
|
_table;
|
|
26
|
+
get _account() {
|
|
27
|
+
return this._driver.account;
|
|
28
|
+
}
|
|
19
29
|
async store(peerId, chatId, msgId) {
|
|
20
30
|
await this._driver.client.query(
|
|
21
|
-
`insert into ${this._table} (peer_id, chat_id, msg_id) values ($1, $2, $3)`,
|
|
22
|
-
[peerId, chatId, msgId]
|
|
31
|
+
`insert into ${this._table} (account, peer_id, chat_id, msg_id) values ($1, $2, $3, $4)`,
|
|
32
|
+
[this._account, peerId, chatId, msgId]
|
|
23
33
|
);
|
|
24
34
|
}
|
|
25
35
|
async getByPeer(peerId) {
|
|
26
36
|
const res = await this._driver.client.query(
|
|
27
|
-
`select chat_id, msg_id from ${this._table} where
|
|
28
|
-
[peerId]
|
|
37
|
+
`select chat_id, msg_id from ${this._table} where account = $1 and peer_id = $2 limit 1`,
|
|
38
|
+
[this._account, peerId]
|
|
29
39
|
);
|
|
30
40
|
if (!res.rows[0]) return null;
|
|
31
41
|
const row = res.rows[0];
|
|
@@ -34,15 +44,18 @@ class PostgresRefMessagesRepository {
|
|
|
34
44
|
async delete(chatId, msgIds) {
|
|
35
45
|
if (msgIds.length === 0) return;
|
|
36
46
|
await this._driver.client.query(
|
|
37
|
-
`delete from ${this._table} where
|
|
38
|
-
[chatId, msgIds]
|
|
47
|
+
`delete from ${this._table} where account = $1 and chat_id = $2 and msg_id = any($3)`,
|
|
48
|
+
[this._account, chatId, msgIds]
|
|
39
49
|
);
|
|
40
50
|
}
|
|
41
51
|
async deleteByPeer(peerId) {
|
|
42
|
-
await this._driver.client.query(
|
|
52
|
+
await this._driver.client.query(
|
|
53
|
+
`delete from ${this._table} where account = $1 and peer_id = $2`,
|
|
54
|
+
[this._account, peerId]
|
|
55
|
+
);
|
|
43
56
|
}
|
|
44
57
|
async deleteAll() {
|
|
45
|
-
await this._driver.client.query(`delete from ${this._table}
|
|
58
|
+
await this._driver.client.query(`delete from ${this._table} where account = $1`, [this._account]);
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
export {
|