@powersync/service-module-postgres 0.14.3 → 0.15.0
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/CHANGELOG.md +50 -0
- package/dist/api/PostgresRouteAPIAdapter.js +3 -1
- package/dist/api/PostgresRouteAPIAdapter.js.map +1 -1
- package/dist/module/PostgresModule.d.ts +1 -2
- package/dist/module/PostgresModule.js +8 -42
- package/dist/module/PostgresModule.js.map +1 -1
- package/dist/replication/PgManager.js +3 -2
- package/dist/replication/PgManager.js.map +1 -1
- package/dist/replication/PgRelation.js +1 -1
- package/dist/replication/PgRelation.js.map +1 -1
- package/dist/replication/SnapshotQuery.js +4 -4
- package/dist/replication/SnapshotQuery.js.map +1 -1
- package/dist/replication/WalStream.d.ts +1 -0
- package/dist/replication/WalStream.js +13 -13
- package/dist/replication/WalStream.js.map +1 -1
- package/dist/replication/WalStreamReplicationJob.js +5 -2
- package/dist/replication/WalStreamReplicationJob.js.map +1 -1
- package/dist/replication/WalStreamReplicator.js +3 -1
- package/dist/replication/WalStreamReplicator.js.map +1 -1
- package/dist/replication/replication-utils.js +10 -2
- package/dist/replication/replication-utils.js.map +1 -1
- package/dist/utils/application-name.d.ts +4 -0
- package/dist/utils/application-name.js +8 -0
- package/dist/utils/application-name.js.map +1 -0
- package/dist/utils/populate_test_data_worker.js +4 -1
- package/dist/utils/populate_test_data_worker.js.map +1 -1
- package/package.json +11 -11
- package/src/api/PostgresRouteAPIAdapter.ts +3 -1
- package/src/module/PostgresModule.ts +7 -45
- package/src/replication/PgManager.ts +3 -2
- package/src/replication/PgRelation.ts +2 -2
- package/src/replication/SnapshotQuery.ts +4 -4
- package/src/replication/WalStream.ts +13 -15
- package/src/replication/WalStreamReplicationJob.ts +5 -2
- package/src/replication/WalStreamReplicator.ts +3 -1
- package/src/replication/replication-utils.ts +10 -2
- package/src/utils/application-name.ts +8 -0
- package/src/utils/populate_test_data_worker.ts +4 -1
- package/test/src/checkpoints.test.ts +2 -0
- package/test/src/large_batch.test.ts +0 -1
- package/test/src/slow_tests.test.ts +0 -2
- package/test/src/util.ts +3 -5
- package/test/src/wal_stream.test.ts +12 -21
- package/test/src/wal_stream_utils.ts +10 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/auth/SupabaseKeyCollector.d.ts +0 -17
- package/dist/auth/SupabaseKeyCollector.js +0 -69
- package/dist/auth/SupabaseKeyCollector.js.map +0 -1
- package/src/auth/SupabaseKeyCollector.ts +0 -81
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { auth, KeyResult } from '@powersync/service-core';
|
|
2
|
-
import * as types from '../types/types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Fetches key from the Supabase database.
|
|
5
|
-
*
|
|
6
|
-
* Unfortunately, despite the JWTs containing a kid, we have no way to lookup that kid
|
|
7
|
-
* before receiving a valid token.
|
|
8
|
-
*
|
|
9
|
-
* @deprecated Supabase is removing support for "app.settings.jwt_secret". This is likely to not function anymore, except in some self-hosted setups.
|
|
10
|
-
*/
|
|
11
|
-
export declare class SupabaseKeyCollector implements auth.KeyCollector {
|
|
12
|
-
private pool;
|
|
13
|
-
private keyOptions;
|
|
14
|
-
constructor(connectionConfig: types.ResolvedConnectionConfig);
|
|
15
|
-
shutdown(): Promise<void>;
|
|
16
|
-
getKeys(): Promise<KeyResult>;
|
|
17
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import * as lib_postgres from '@powersync/lib-service-postgres';
|
|
2
|
-
import { auth } from '@powersync/service-core';
|
|
3
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
4
|
-
import { AuthorizationError, ErrorCode } from '@powersync/lib-services-framework';
|
|
5
|
-
/**
|
|
6
|
-
* Fetches key from the Supabase database.
|
|
7
|
-
*
|
|
8
|
-
* Unfortunately, despite the JWTs containing a kid, we have no way to lookup that kid
|
|
9
|
-
* before receiving a valid token.
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Supabase is removing support for "app.settings.jwt_secret". This is likely to not function anymore, except in some self-hosted setups.
|
|
12
|
-
*/
|
|
13
|
-
export class SupabaseKeyCollector {
|
|
14
|
-
pool;
|
|
15
|
-
keyOptions = {
|
|
16
|
-
requiresAudience: ['authenticated'],
|
|
17
|
-
maxLifetimeSeconds: 86400 * 7 + 1200 // 1 week + 20 minutes margin
|
|
18
|
-
};
|
|
19
|
-
constructor(connectionConfig) {
|
|
20
|
-
this.pool = pgwire.connectPgWirePool(connectionConfig, {
|
|
21
|
-
// To avoid overloading the source database with open connections,
|
|
22
|
-
// limit to a single connection, and close the connection shortly
|
|
23
|
-
// after using it.
|
|
24
|
-
idleTimeout: 5_000,
|
|
25
|
-
maxSize: 1
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
shutdown() {
|
|
29
|
-
return this.pool.end();
|
|
30
|
-
}
|
|
31
|
-
async getKeys() {
|
|
32
|
-
let row;
|
|
33
|
-
try {
|
|
34
|
-
const rows = pgwire.pgwireRows(await lib_postgres.retriedQuery(this.pool, `SELECT current_setting('app.settings.jwt_secret') as jwt_secret`));
|
|
35
|
-
row = rows[0];
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
if (e.message?.includes('unrecognized configuration parameter')) {
|
|
39
|
-
throw new AuthorizationError(ErrorCode.PSYNC_S2201, 'No JWT secret found in Supabase database. Manually configure the secret.');
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
throw e;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const secret = row?.jwt_secret;
|
|
46
|
-
if (secret == null) {
|
|
47
|
-
return {
|
|
48
|
-
keys: [],
|
|
49
|
-
errors: [
|
|
50
|
-
new AuthorizationError(ErrorCode.PSYNC_S2201, 'No JWT secret found in Supabase database. Manually configure the secret.')
|
|
51
|
-
]
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const key = {
|
|
56
|
-
kty: 'oct',
|
|
57
|
-
alg: 'HS256',
|
|
58
|
-
// While the secret is valid base64, the base64-encoded form is the secret value.
|
|
59
|
-
k: Buffer.from(secret, 'utf8').toString('base64url')
|
|
60
|
-
};
|
|
61
|
-
const imported = await auth.KeySpec.importKey(key, this.keyOptions);
|
|
62
|
-
return {
|
|
63
|
-
keys: [imported],
|
|
64
|
-
errors: []
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=SupabaseKeyCollector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SupabaseKeyCollector.js","sourceRoot":"","sources":["../../src/auth/SupabaseKeyCollector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,IAAI,EAAa,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAIrD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAElF;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAoB;IACvB,IAAI,CAAkB;IAEtB,UAAU,GAAoB;QACpC,gBAAgB,EAAE,CAAC,eAAe,CAAC;QACnC,kBAAkB,EAAE,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,6BAA6B;KACnE,CAAC;IAEF,YAAY,gBAAgD;QAC1D,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,EAAE;YACrD,kEAAkE;YAClE,iEAAiE;YACjE,kBAAkB;YAClB,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;IACL,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,GAA2B,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAC5B,MAAM,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,iEAAiE,CAAC,CAC9G,CAAC;YACF,GAAG,GAAG,IAAI,CAAC,CAAC,CAAQ,CAAC;QACvB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,sCAAsC,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,kBAAkB,CAC1B,SAAS,CAAC,WAAW,EACrB,0EAA0E,CAC3E,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,CAAC;YACV,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,EAAE,UAAgC,CAAC;QACrD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,OAAO;gBACL,IAAI,EAAE,EAAE;gBACR,MAAM,EAAE;oBACN,IAAI,kBAAkB,CACpB,SAAS,CAAC,WAAW,EACrB,0EAA0E,CAC3E;iBACF;aACF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAa;gBACpB,GAAG,EAAE,KAAK;gBACV,GAAG,EAAE,OAAO;gBACZ,iFAAiF;gBACjF,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;aACrD,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACpE,OAAO;gBACL,IAAI,EAAE,CAAC,QAAQ,CAAC;gBAChB,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import * as lib_postgres from '@powersync/lib-service-postgres';
|
|
2
|
-
import { auth, KeyResult } from '@powersync/service-core';
|
|
3
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
4
|
-
import * as jose from 'jose';
|
|
5
|
-
|
|
6
|
-
import * as types from '../types/types.js';
|
|
7
|
-
import { AuthorizationError, ErrorCode } from '@powersync/lib-services-framework';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Fetches key from the Supabase database.
|
|
11
|
-
*
|
|
12
|
-
* Unfortunately, despite the JWTs containing a kid, we have no way to lookup that kid
|
|
13
|
-
* before receiving a valid token.
|
|
14
|
-
*
|
|
15
|
-
* @deprecated Supabase is removing support for "app.settings.jwt_secret". This is likely to not function anymore, except in some self-hosted setups.
|
|
16
|
-
*/
|
|
17
|
-
export class SupabaseKeyCollector implements auth.KeyCollector {
|
|
18
|
-
private pool: pgwire.PgClient;
|
|
19
|
-
|
|
20
|
-
private keyOptions: auth.KeyOptions = {
|
|
21
|
-
requiresAudience: ['authenticated'],
|
|
22
|
-
maxLifetimeSeconds: 86400 * 7 + 1200 // 1 week + 20 minutes margin
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
constructor(connectionConfig: types.ResolvedConnectionConfig) {
|
|
26
|
-
this.pool = pgwire.connectPgWirePool(connectionConfig, {
|
|
27
|
-
// To avoid overloading the source database with open connections,
|
|
28
|
-
// limit to a single connection, and close the connection shortly
|
|
29
|
-
// after using it.
|
|
30
|
-
idleTimeout: 5_000,
|
|
31
|
-
maxSize: 1
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
shutdown() {
|
|
36
|
-
return this.pool.end();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async getKeys(): Promise<KeyResult> {
|
|
40
|
-
let row: { jwt_secret: string };
|
|
41
|
-
try {
|
|
42
|
-
const rows = pgwire.pgwireRows(
|
|
43
|
-
await lib_postgres.retriedQuery(this.pool, `SELECT current_setting('app.settings.jwt_secret') as jwt_secret`)
|
|
44
|
-
);
|
|
45
|
-
row = rows[0] as any;
|
|
46
|
-
} catch (e) {
|
|
47
|
-
if (e.message?.includes('unrecognized configuration parameter')) {
|
|
48
|
-
throw new AuthorizationError(
|
|
49
|
-
ErrorCode.PSYNC_S2201,
|
|
50
|
-
'No JWT secret found in Supabase database. Manually configure the secret.'
|
|
51
|
-
);
|
|
52
|
-
} else {
|
|
53
|
-
throw e;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const secret = row?.jwt_secret as string | undefined;
|
|
57
|
-
if (secret == null) {
|
|
58
|
-
return {
|
|
59
|
-
keys: [],
|
|
60
|
-
errors: [
|
|
61
|
-
new AuthorizationError(
|
|
62
|
-
ErrorCode.PSYNC_S2201,
|
|
63
|
-
'No JWT secret found in Supabase database. Manually configure the secret.'
|
|
64
|
-
)
|
|
65
|
-
]
|
|
66
|
-
};
|
|
67
|
-
} else {
|
|
68
|
-
const key: jose.JWK = {
|
|
69
|
-
kty: 'oct',
|
|
70
|
-
alg: 'HS256',
|
|
71
|
-
// While the secret is valid base64, the base64-encoded form is the secret value.
|
|
72
|
-
k: Buffer.from(secret, 'utf8').toString('base64url')
|
|
73
|
-
};
|
|
74
|
-
const imported = await auth.KeySpec.importKey(key, this.keyOptions);
|
|
75
|
-
return {
|
|
76
|
-
keys: [imported],
|
|
77
|
-
errors: []
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|