@aws/aurora-dsql-postgresjs-connector 0.2.0 → 0.2.1
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 +31 -9
- package/dist/index.cjs +8 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Aurora DSQL Connector for Postgres.js
|
|
2
2
|
|
|
3
|
-
[](https://github.com/awslabs/aurora-dsql-
|
|
3
|
+
[](https://github.com/awslabs/aurora-dsql-connectors/tree/main/node/postgres-js)
|
|
4
|
+
[](https://github.com/awslabs/aurora-dsql-connectors/blob/main/LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/@aws/aurora-dsql-postgresjs-connector)
|
|
6
6
|
[](https://discord.com/invite/nEF6ksFWru)
|
|
7
7
|
|
|
@@ -52,6 +52,15 @@ The Aurora DSQL Connector for Postgres.js is designed to understand these requir
|
|
|
52
52
|
- Set up appropriate IAM permissions to allow your application to connect to Aurora DSQL.
|
|
53
53
|
- AWS credentials configured (via AWS CLI, environment variables, or IAM roles)
|
|
54
54
|
|
|
55
|
+
## ⚠️ Important
|
|
56
|
+
|
|
57
|
+
* Running this code might result in charges to your AWS account.
|
|
58
|
+
* We recommend that you grant your code least privilege. At most, grant only the
|
|
59
|
+
minimum permissions required to perform the task. For more information, see
|
|
60
|
+
[Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
|
|
61
|
+
* This code is not tested in every AWS Region. For more information, see
|
|
62
|
+
[AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
|
|
63
|
+
|
|
55
64
|
### Installation
|
|
56
65
|
|
|
57
66
|
```bash
|
|
@@ -132,16 +141,29 @@ const sql = AuroraDSQLPostgres({
|
|
|
132
141
|
All standard [Postgres.js options](https://github.com/porsager/postgres?tab=readme-ov-file#connection-details) are also supported.
|
|
133
142
|
|
|
134
143
|
## Websocket Connector
|
|
135
|
-
The websocket connector provides an alternative connection method to Aurora DSQL using WebSockets instead of standard TCP sockets. This
|
|
144
|
+
The websocket connector provides an alternative connection method to Aurora DSQL using WebSockets instead of standard TCP sockets. This is designed for environments where TCP sockets are unavailable. For Node.js server applications, use the standard TCP socket connector shown above.
|
|
145
|
+
|
|
146
|
+
### Use Case - Environments Without TCP Sockets
|
|
147
|
+
|
|
148
|
+
Some JavaScript runtimes don't provide TCP socket support. The WebSocket connector enables DSQL connections from these environments. If credentials remain server-controlled, the security model is similar to traditional server-side applications and credentials can be configured using your platform's secrets management (e.g., environment variables, secrets store).
|
|
149
|
+
|
|
150
|
+
### Use Case - Browser Applications
|
|
151
|
+
|
|
152
|
+
Web browsers don't support TCP sockets. The WebSocket connector enables direct browser-to-database connections for use cases like internal tools, prototypes, or applications where users can safely have direct database access.
|
|
153
|
+
|
|
154
|
+
#### ⚠️ Security Considerations for Browser Usage
|
|
155
|
+
|
|
156
|
+
When using the WebSocket connector from a browser, the database connection runs in an environment controlled by the end user. This has important security implications:
|
|
157
|
+
|
|
158
|
+
- **Users can execute any query their database role permits.** There is no server-side layer to validate, filter, or restrict queries. The browser's JavaScript can be inspected and modified.
|
|
136
159
|
|
|
137
|
-
|
|
138
|
-
- Browser Compatibility - Web browsers don't support raw TCP sockets (Node.js net module). WebSockets are a common way to establish persistent database connections from browser-based applications.
|
|
160
|
+
- **Database role permissions are your access control boundary.** The IAM role grants connection ability, but the PostgreSQL database role determines what data the user can access. Configure database roles with minimal necessary permissions.
|
|
139
161
|
|
|
140
|
-
|
|
162
|
+
This approach is appropriate when users should have direct database access such as internal admin tools, single-user applications, or scenarios with properly scoped database roles. It is not a substitute for a backend API when you need to control what queries users can run.
|
|
141
163
|
|
|
142
|
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
164
|
+
For guidance on configuring IAM roles and database permissions, see:
|
|
165
|
+
- [Authentication and authorization for Aurora DSQL](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/authentication-authorization.html)
|
|
166
|
+
- [Using database roles and IAM authentication](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/using-database-and-iam-roles.html)
|
|
145
167
|
|
|
146
168
|
### Basic Usage
|
|
147
169
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -36,11 +37,11 @@ const HEARTBEAT_TIMEOUT = 5e3;
|
|
|
36
37
|
const MESSAGE_CODE_SIMPLE_QUERY = "Q".charCodeAt(0);
|
|
37
38
|
const MESSAGE_CODE_SYNC = "S".charCodeAt(0);
|
|
38
39
|
const MESSAGE_CODE_RFQ = "Z".charCodeAt(0);
|
|
39
|
-
var ReadyState = /* @__PURE__ */ function(ReadyState
|
|
40
|
-
ReadyState
|
|
41
|
-
ReadyState
|
|
42
|
-
ReadyState
|
|
43
|
-
return ReadyState
|
|
40
|
+
var ReadyState = /* @__PURE__ */ function(ReadyState) {
|
|
41
|
+
ReadyState["Closed"] = "closed";
|
|
42
|
+
ReadyState["Querying"] = "querying";
|
|
43
|
+
ReadyState["Open"] = "open";
|
|
44
|
+
return ReadyState;
|
|
44
45
|
}(ReadyState || {});
|
|
45
46
|
var PostgresWs = class extends events.EventEmitter {
|
|
46
47
|
constructor(config) {
|
|
@@ -244,7 +245,7 @@ function createPostgresWs(config) {
|
|
|
244
245
|
|
|
245
246
|
//#endregion
|
|
246
247
|
//#region src/client.ts
|
|
247
|
-
const version = "0.2.
|
|
248
|
+
const version = "0.2.1";
|
|
248
249
|
const ADMIN = "admin";
|
|
249
250
|
const DEFAULT_DATABASE = "postgres";
|
|
250
251
|
const DEFAULT_EXPIRY = 30;
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/client.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;iBAgGgB,kBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,GAAA,UACA,OAAA,GAAU,gBAAA,CAAiB,CAAA,IAC1B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAKU,kBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,OAAA,EAAS,gBAAA,CAAiB,CAAA,IACzB,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAqCU,oBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,GAAA,UACA,OAAA,GAAU,kBAAA,CAAmB,CAAA,IAC5B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAKU,oBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,OAAA,EAAS,kBAAA,CAAmB,CAAA,IAC3B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,UAwIW,gBAAA,WAA2B,MAAA,SAAe,YAAA,CAAa,CAAA,YAAa,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,CAAA;EAEzG,MAAA;EAEA,OAAA;EAEA,iBAAA;EAEA,yBAAA,GAA4B,qBAAA,GAAwB,6BAAA;AAAA;AAAA,UAGrC,kBAAA,WAA6B,MAAA,SAAe,YAAA,CAAa,CAAA,YAChE,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,CAAA;EAC9B,MAAA;EACA,iBAAA;EACA,yBAAA,GACE,qBAAA,GACA,6BAAA;EACF,eAAA;EACA,YAAA;EACA,yBAAA,IAA6B,YAAA;AAAA"}
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;iBAgGgB,kBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,GAAA,UACA,OAAA,GAAU,gBAAA,CAAiB,CAAA,IAC1B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAKU,kBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,OAAA,EAAS,gBAAA,CAAiB,CAAA,IACzB,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAqCU,oBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,GAAA,UACA,OAAA,GAAU,kBAAA,CAAmB,CAAA,IAC5B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,iBAKU,oBAAA,WACJ,MAAA,SAAe,QAAA,CAAS,YAAA,OAAA,CAElC,OAAA,EAAS,kBAAA,CAAmB,CAAA,IAC3B,QAAA,CAAS,GAAA,CACV,MAAA,SAAe,QAAA,CAAS,YAAA,UAAsB,CAAA,yBAG7B,CAAA,GAAI,CAAA,CAAE,IAAA;EACnB,SAAA,GAAY,KAAA;EACZ,KAAA,GAAQ,GAAA;AAAA,IAER,CAAA;AAAA,UAwIW,gBAAA,WAA2B,MAAA,SAAe,YAAA,CAAa,CAAA,YAAa,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,CAAA;EAEzG,MAAA;EAEA,OAAA;EAEA,iBAAA;EAEA,yBAAA,GAA4B,qBAAA,GAAwB,6BAAA;AAAA;AAAA,UAGrC,kBAAA,WAA6B,MAAA,SAAe,YAAA,CAAa,CAAA,YAChE,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,CAAA;EAC9B,MAAA;EACA,iBAAA;EACA,yBAAA,GACE,qBAAA,GACA,6BAAA;EACF,eAAA;EACA,YAAA;EACA,yBAAA,IAA6B,YAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -8,11 +8,11 @@ const HEARTBEAT_TIMEOUT = 5e3;
|
|
|
8
8
|
const MESSAGE_CODE_SIMPLE_QUERY = "Q".charCodeAt(0);
|
|
9
9
|
const MESSAGE_CODE_SYNC = "S".charCodeAt(0);
|
|
10
10
|
const MESSAGE_CODE_RFQ = "Z".charCodeAt(0);
|
|
11
|
-
var ReadyState = /* @__PURE__ */ function(ReadyState
|
|
12
|
-
ReadyState
|
|
13
|
-
ReadyState
|
|
14
|
-
ReadyState
|
|
15
|
-
return ReadyState
|
|
11
|
+
var ReadyState = /* @__PURE__ */ function(ReadyState) {
|
|
12
|
+
ReadyState["Closed"] = "closed";
|
|
13
|
+
ReadyState["Querying"] = "querying";
|
|
14
|
+
ReadyState["Open"] = "open";
|
|
15
|
+
return ReadyState;
|
|
16
16
|
}(ReadyState || {});
|
|
17
17
|
var PostgresWs = class extends EventEmitter {
|
|
18
18
|
constructor(config) {
|
|
@@ -216,7 +216,7 @@ function createPostgresWs(config) {
|
|
|
216
216
|
|
|
217
217
|
//#endregion
|
|
218
218
|
//#region src/client.ts
|
|
219
|
-
const version = "0.2.
|
|
219
|
+
const version = "0.2.1";
|
|
220
220
|
const ADMIN = "admin";
|
|
221
221
|
const DEFAULT_DATABASE = "postgres";
|
|
222
222
|
const DEFAULT_EXPIRY = 30;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["callbackFn: ((err?: Error) => void) | undefined","sendData: Uint8Array","opts: any","host: string","username: string","database: string | undefined","signerConfig: DsqlSignerConfig","postgresOpts: postgres.Options<T>"],"sources":["../src/postgres-web-socket.ts","../src/client.ts"],"sourcesContent":["/*\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { EventEmitter } from \"events\";\nimport { AuroraDSQLWsConfig } from \"./client\";\nimport { Mutex } from \"async-mutex\";\n\nconst HEARTBEAT_TIMEOUT = 5_000; // 5 seconds\n\nconst MESSAGE_CODE_SIMPLE_QUERY = \"Q\".charCodeAt(0);\nconst MESSAGE_CODE_SYNC = \"S\".charCodeAt(0);\nconst MESSAGE_CODE_RFQ = \"Z\".charCodeAt(0);\n\ninterface Query {\n buffer: Buffer | Uint8Array;\n numOfQueries: number;\n isHeartBeat: boolean;\n}\n\nenum ReadyState {\n Closed = 'closed',\n Querying = 'querying',\n Open = 'open'\n}\n\nexport class PostgresWs extends EventEmitter {\n private mutex = new Mutex();\n private mutexRelease: (() => void) | null = null;\n\n private config: AuroraDSQLWsConfig<{}>;\n private ws: WebSocket | null = null;\n private connected: boolean = false;\n\n private disableHeartBeat: boolean = false;\n private heartBeatTimeout: NodeJS.Timeout | null = null;\n private pendingQueries: Query[] = [];\n\n public readyState: ReadyState = ReadyState.Closed;\n\n\n // these parameters are referenced when an Error is thrown\n private host: string;\n private port: number = 443;\n\n constructor(config: AuroraDSQLWsConfig<{}>) {\n super();\n this.config = config;\n this.host = config.host || '';\n }\n\n\n onReadyForQuery() {\n if (this.pendingQueries.length > 0) {\n if (this.pendingQueries[0].numOfQueries > 0) {\n this.pendingQueries[0].numOfQueries--;\n }\n\n // remove the pendingQueries now that we received the reply only if the querycount is at 0\n if (this.pendingQueries[0].numOfQueries <= 0) {\n this.pendingQueries.shift();\n this.readyState = ReadyState.Open;\n this.disableHeartBeat = false;\n this.releaseMutex();\n this.processQueue();\n }\n }\n }\n\n handleHeartBeatResponse(data: Uint8Array): boolean {\n if (this.pendingQueries.length === 0 || !this.pendingQueries[0].isHeartBeat) return false;\n\n const messageType = String.fromCharCode(data[0]);\n\n if (messageType === \"D\") {\n const dataStr = new TextDecoder().decode(data.slice(5));\n // verify that it is from heartbeat\n if (dataStr.includes(\"1\")) {\n clearTimeout(this.heartBeatTimeout!);\n this.heartBeatTimeout = null;\n }\n } else if (messageType === \"Z\") {\n this.onReadyForQuery();\n }\n\n return true;\n }\n\n async connect(): Promise<this> {\n const url = `wss://${this.config.host}:${this.port}`;\n this.ws = new WebSocket(url);\n this.ws.binaryType = \"arraybuffer\";\n\n return new Promise((resolve, reject) => {\n if (this.ws != null) {\n this.ws.onopen = () => {\n this.connected = true;\n this.readyState = ReadyState.Open;\n resolve(this);\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n const data = new Uint8Array(event.data);\n\n if (this.config.connectionCheck) {\n if (this.handleHeartBeatResponse(data)) return;\n\n if (data.length > 0 && data[0] === MESSAGE_CODE_RFQ) {\n\n if (data.length > 5) {\n const status = String.fromCharCode(data[5]);\n\n if (status === \"E\") {\n // temporarily disable heart beat when the connection has a transaction error\n this.disableHeartBeat = true;\n this.cleanUpTxErrorState();\n } else {\n // I (IDLE) or T (Transaction) \n this.onReadyForQuery();\n }\n }\n }\n }\n\n this.emit(\"data\", Buffer.from(data));\n };\n\n this.ws.onerror = (event: Event) => {\n const msg = (event as ErrorEvent).message || \"WebSocket error\";\n const error = new Error(`${msg} ${this.host}:${this.port}`);\n this.emit(\"error\", error);\n reject(error);\n };\n\n this.ws.onclose = () => {\n if (this.heartBeatTimeout) {\n clearTimeout(this.heartBeatTimeout);\n this.heartBeatTimeout = null;\n }\n\n this.releaseMutex();\n\n this.connected = false;\n this.readyState = ReadyState.Closed;\n this.ws = null;\n this.emit(\"close\");\n\n if (this.config.onReservedConnectionClose) {\n this.config.onReservedConnectionClose(this.config.connectionId);\n }\n };\n }\n });\n }\n\n createQueryBuffer(sql: string): Uint8Array {\n const sqlBytes = new TextEncoder().encode(sql + \"\\0\");\n const length = 4 + sqlBytes.length;\n const buf = new Uint8Array(1 + length);\n const view = new DataView(buf.buffer);\n\n buf[0] = MESSAGE_CODE_SIMPLE_QUERY;\n view.setInt32(1, length, false);\n buf.set(sqlBytes, 5);\n\n return buf;\n }\n\n // future proofing in case postgres.js starts using the write function with 3 parameters\n // currently the library uses the write function with 2 parameters\n // callback is needed for copy related operations \n write(data: Buffer | Uint8Array, callback?: (err?: Error) => void): boolean;\n write(data: string, encoding?: string, callback?: (err?: Error) => void): boolean;\n\n write(\n data: Buffer | Uint8Array | string,\n encodingOrCallback?: string | ((err?: Error) => void),\n callback?: (err?: Error) => void\n ): boolean {\n\n let callbackFn: ((err?: Error) => void) | undefined;\n\n if (typeof encodingOrCallback === 'function') {\n callbackFn = encodingOrCallback;\n } else {\n callbackFn = callback;\n }\n\n let sendData: Uint8Array;\n if (typeof data === 'string') {\n const encoder = new TextEncoder();\n sendData = encoder.encode(data); // Always UTF-8\n } else if (data instanceof Buffer) {\n sendData = new Uint8Array(data);\n } else {\n sendData = data;\n }\n\n if (!this.ws || !this.connected) {\n if (callbackFn) {\n callbackFn(new Error(\"websocket is not connected\"));\n }\n return false;\n }\n\n let offset = 0;\n\n let queryCount = 0; // simple query \n let hasSync = false; // extended query protocol \n\n while (offset < sendData.length) {\n if (sendData[offset] === MESSAGE_CODE_SIMPLE_QUERY) {\n queryCount++;\n }\n\n if (sendData[offset] === MESSAGE_CODE_SYNC) {\n hasSync = true;\n }\n\n // Read message length to skip to next message\n if (offset + 5 <= sendData.length) {\n const length = new DataView(sendData.buffer, sendData.byteOffset + offset + 1, 4).getInt32(0, false);\n offset += 1 + length;\n } else {\n break;\n }\n }\n\n // directly send message to websocket when \n // * connection check (heart beat) is disabled \n // * Z (ReadyForQuery) message is not expected to be returned\n if (!this.config.connectionCheck || (queryCount == 0 && hasSync === false)) {\n try {\n this.ws.send(sendData);\n if (callbackFn) {\n callbackFn();\n }\n return true;\n } catch (err) {\n if (callbackFn) {\n callbackFn(err as Error);\n }\n return false;\n }\n }\n\n // if the buffer contains a query, send a heart beat first\n if (\n queryCount > 0 &&\n this.config.connectionCheck &&\n this.heartBeatTimeout === null && // make sure no existing heart beat time out is overwritten\n !this.disableHeartBeat\n ) {\n const buf = this.createQueryBuffer(\"select 1;\");\n this.pendingQueries.push({ buffer: buf, numOfQueries: 1, isHeartBeat: true });\n }\n this.pendingQueries.push({ buffer: sendData, numOfQueries: queryCount, isHeartBeat: false });\n this.processQueue();\n\n if (callbackFn) {\n callbackFn();\n }\n\n return true;\n }\n\n private releaseMutex() {\n if (this.mutexRelease) {\n this.mutexRelease();\n this.mutexRelease = null;\n }\n }\n\n // cleans up the error state during a transaction error \n private cleanUpTxErrorState() {\n // throw away last query as the result set has a transaction error and no more result set should return \n if (this.pendingQueries.length > 0) {\n this.pendingQueries.shift();\n }\n\n // since heart beat cant be performed during a transaction error, discard heart beat queries which are already in pending queries\n while (this.pendingQueries.length > 0 && this.pendingQueries[0].isHeartBeat) {\n this.pendingQueries.shift();\n }\n this.readyState = ReadyState.Open;\n this.releaseMutex();\n\n if (this.pendingQueries.length > 0) {\n this.processQueue();\n }\n }\n\n private async processQueue(): Promise<void> {\n if (\n this.mutexRelease ||\n this.readyState !== ReadyState.Open ||\n this.pendingQueries.length === 0\n ) {\n return;\n }\n\n this.mutexRelease = await this.mutex.acquire();\n\n // it is possible that the pendingQueries is now empty \n if (this.pendingQueries.length == 0) {\n this.releaseMutex();\n return;\n }\n\n const data = this.pendingQueries[0];\n\n if (data.buffer.length > 0 && data.buffer[0] === MESSAGE_CODE_SIMPLE_QUERY) {\n this.readyState = ReadyState.Querying;\n }\n\n if (data.isHeartBeat) {\n this.heartBeatTimeout = setTimeout(() => {\n console.log(\"Heart beat timed out\");\n if (this.ws) {\n this.ws.close(1000, \"Heart beat timeout\");\n }\n }, HEARTBEAT_TIMEOUT);\n }\n\n if (this.ws) {\n this.ws.send(data.buffer);\n } else {\n throw Error(\"Websocket is not initialized\");\n }\n }\n\n end(): void {\n if (this.ws && this.readyState !== ReadyState.Closed) {\n this.ws.close();\n }\n }\n\n destroy(): void {\n if (this.ws) {\n this.ws.close();\n }\n }\n\n // Following functions needs to be defined as connection.js \n // in postgres.js can call these functions but they will be no-op\n setKeepAlive(): this {\n return this;\n }\n\n resume(): this {\n return this;\n }\n\n pause(): this {\n return this;\n }\n\n cork(): this {\n return this;\n }\n\n uncork(): this {\n return this;\n }\n}\n\nexport function createPostgresWs(\n config: AuroraDSQLWsConfig<{}>\n): () => Promise<PostgresWs> {\n return async () => {\n\n const socket = new PostgresWs(config);\n await socket.connect();\n return socket;\n };\n}\n","/*\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport postgres, { PostgresType } from \"postgres\";\nimport {\n AwsCredentialIdentity,\n AwsCredentialIdentityProvider,\n} from \"@aws-sdk/types\";\nimport { DsqlSigner, DsqlSignerConfig } from \"@aws-sdk/dsql-signer\";\nimport { createPostgresWs } from \"./postgres-web-socket\";\n\n// Version is injected at build time via tsdown\ndeclare const __VERSION__: string;\nconst version = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : \"0.0.0\";\n\nconst ADMIN = \"admin\";\nconst DEFAULT_DATABASE = \"postgres\";\nconst DEFAULT_EXPIRY = 30; // Based on default Postgres.js connect_timeout\n// String components of a DSQL hostname, <Cluster ID>.dsql.<region>.on.aws\nconst PRE_REGION_HOST_PATTERN = \".dsql.\";\nconst POST_REGION_HOST_PATTERN = \".on.aws\";\nconst APPLICATION_NAME = `aurora-dsql-nodejs-postgresjs/${version}`;\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction parseConnectionParams(\n urlOrOptions: string | any,\n options?: any\n): { opts: any; } {\n let opts: any;\n let host: string;\n let username: string;\n let database: string | undefined;\n\n if (typeof urlOrOptions === \"string\") {\n let parsedOptions = parseConnectionString(urlOrOptions);\n host = options?.hostname || options?.host || parsedOptions.host || process.env.PGHOST!;\n username = options?.username || options?.user || parsedOptions.username! ||\n process.env.PGUSERNAME || process.env.USER || ADMIN;\n database = options?.database || options?.db || parsedOptions.database || process.env.PGDATABASE;\n opts = {\n ...options,\n ssl: options?.ssl || parsedOptions.ssl\n };\n } else {\n host = urlOrOptions?.hostname || urlOrOptions?.host || process.env.PGHOST!;\n username = urlOrOptions?.username || urlOrOptions?.user ||\n process.env.PGUSERNAME || process.env.USER || ADMIN;\n database = urlOrOptions?.database || urlOrOptions?.db || process.env.PGDATABASE;\n opts = { ...urlOrOptions };\n }\n\n if (Array.isArray(host)) {\n throw new Error(\"Multi-host configurations are not supported for Aurora DSQL\");\n }\n\n if (!opts.region) {\n opts.region = parseRegionFromHost(host);\n }\n\n if (isClusterID(host)) {\n host = buildHostnameFromIdAndRegion(host, opts.region);\n }\n\n if (!database) {\n opts.database = DEFAULT_DATABASE;\n }\n\n opts.host = host;\n opts.username = username;\n opts.connection = {\n ...opts.connection,\n application_name: buildApplicationName(opts.connection?.application_name),\n };\n\n return { opts };\n}\n\nfunction setupDsqlSigner(opts: any): { signerConfig: DsqlSignerConfig; } {\n\n let signerConfig: DsqlSignerConfig = {\n hostname: opts.host,\n region: opts.region,\n expiresIn: opts.tokenDurationSecs ?? opts.connect_timeout ??\n (process.env.PGCONNECT_TIMEOUT ? parseInt(process.env.PGCONNECT_TIMEOUT) : undefined) ??\n DEFAULT_EXPIRY,\n profile: opts.profile || process.env.AWS_PROFILE || \"default\",\n };\n\n if (opts.customCredentialsProvider) {\n signerConfig.credentials = opts.customCredentialsProvider;\n }\n\n return { signerConfig };\n}\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n url: string,\n options?: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n options: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n urlOrOptions: string | AuroraDSQLConfig<T>,\n options?: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n> {\n\n let { opts } = parseConnectionParams(urlOrOptions, options);\n const { signerConfig } = setupDsqlSigner(opts);\n let signer = new DsqlSigner(signerConfig);\n\n if (!opts.ssl) opts.ssl = true;\n const postgresOpts: postgres.Options<T> = {\n ...opts,\n pass: () => getToken(signer, opts.username),\n };\n return typeof urlOrOptions === \"string\"\n ? postgres(urlOrOptions, postgresOpts)\n : postgres(postgresOpts);\n}\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n url: string,\n options?: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n options: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n urlOrOptions: string | AuroraDSQLWsConfig<T>,\n options?: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n> {\n\n let { opts } = parseConnectionParams(urlOrOptions, options);\n const { signerConfig } = setupDsqlSigner(opts);\n\n if (!opts.pass) {\n opts.pass = async () => {\n let signer = new DsqlSigner(signerConfig);\n return await getToken(signer, opts.username);\n };\n }\n\n // swap out socket to use websocket\n opts.socket = createPostgresWs(opts);\n\n // ssl must be false otherwise postgres.js will try to use the net.socket \n opts.ssl = false;\n\n if (opts.connectionCheck == undefined) {\n // disable connection check by default \n // connection check sends a 'select 1' before every query\n opts.connectionCheck = false;\n }\n\n opts.port = 443;\n\n return typeof urlOrOptions === \"string\"\n ? postgres(urlOrOptions, opts)\n : postgres(opts);\n}\n\n\nfunction parseConnectionString(url: string): {\n database?: string;\n host?: string;\n username?: string;\n ssl?: string;\n} {\n let decodedUrl = decodeURI(url);\n const parsed = new URL(decodedUrl);\n\n // Check for multi-host\n if (parsed.hostname?.includes(\",\")) {\n throw new Error(\n \"Multi-host connection strings are not supported for Aurora DSQL\"\n );\n }\n\n return {\n username: parsed.username,\n host: parsed.hostname,\n database: parsed.pathname?.slice(1),\n ssl:\n parsed.searchParams.get(\"ssl\") ||\n parsed.searchParams.get(\"sslmode\") ||\n undefined,\n };\n}\n\nfunction parseRegionFromHost(host: string): string | undefined {\n if (!host) {\n throw new Error(\"Hostname is required to parse region\");\n }\n\n const match = host.match(\n /^(?<instance>[^.]+)\\.(?<dns>dsql(?:-[^.]+)?)\\.(?<domain>(?<region>[a-zA-Z0-9-]+)\\.on\\.aws\\.?)$/i\n );\n if (match?.groups) {\n return match.groups.region;\n }\n throw new Error(`Unable to parse region from hostname: ${host}`);\n}\n\nfunction isClusterID(host: string) {\n return !host.includes(\".\");\n}\n\nfunction buildHostnameFromIdAndRegion(\n host: string,\n region: string | undefined\n) {\n return host + PRE_REGION_HOST_PATTERN + region + POST_REGION_HOST_PATTERN;\n}\n\nasync function getToken(signer: DsqlSigner, username: string): Promise<string> {\n if (username === ADMIN) {\n return await signer.getDbConnectAdminAuthToken();\n } else {\n return await signer.getDbConnectAuthToken();\n }\n}\n\n/**\n * Build the application_name with optional ORM prefix.\n *\n * If ormPrefix is provided and non-empty after trimming, prepends it to\n * the connector identifier. Otherwise, returns the connector's application_name.\n *\n * PostgreSQL limits application_name to 64 characters. After accounting for\n * the connector identifier and separator, 27 characters are available for\n * the ORM name.\n *\n * @param ormPrefix Optional ORM name to prepend (e.g., \"prisma\")\n * @returns Formatted application_name string\n */\nfunction buildApplicationName(ormPrefix?: string): string {\n if (ormPrefix) {\n const trimmed = ormPrefix.trim();\n if (trimmed) {\n return `${trimmed}:${APPLICATION_NAME}`;\n }\n }\n return APPLICATION_NAME;\n}\n\nexport interface AuroraDSQLConfig<T extends Record<string, PostgresType<T>>> extends Omit<postgres.Options<T>, 'password' | 'pass'> {\n\n region?: string;\n\n profile?: string;\n\n tokenDurationSecs?: number;\n\n customCredentialsProvider?: AwsCredentialIdentity | AwsCredentialIdentityProvider;\n\n}\nexport interface AuroraDSQLWsConfig<T extends Record<string, PostgresType<T>>>\n extends Omit<postgres.Options<T>, \"socket\" | \"ssl\" | \"port\"> {\n region?: string;\n tokenDurationSecs?: number;\n customCredentialsProvider?:\n | AwsCredentialIdentity\n | AwsCredentialIdentityProvider;\n connectionCheck?: boolean;\n connectionId?: string;\n onReservedConnectionClose?: (connectionId?: string) => void;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/postgres-web-socket.ts","../src/client.ts"],"sourcesContent":["/*\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { EventEmitter } from \"events\";\nimport { AuroraDSQLWsConfig } from \"./client\";\nimport { Mutex } from \"async-mutex\";\n\nconst HEARTBEAT_TIMEOUT = 5_000; // 5 seconds\n\nconst MESSAGE_CODE_SIMPLE_QUERY = \"Q\".charCodeAt(0);\nconst MESSAGE_CODE_SYNC = \"S\".charCodeAt(0);\nconst MESSAGE_CODE_RFQ = \"Z\".charCodeAt(0);\n\ninterface Query {\n buffer: Buffer | Uint8Array;\n numOfQueries: number;\n isHeartBeat: boolean;\n}\n\nenum ReadyState {\n Closed = 'closed',\n Querying = 'querying',\n Open = 'open'\n}\n\nexport class PostgresWs extends EventEmitter {\n private mutex = new Mutex();\n private mutexRelease: (() => void) | null = null;\n\n private config: AuroraDSQLWsConfig<{}>;\n private ws: WebSocket | null = null;\n private connected: boolean = false;\n\n private disableHeartBeat: boolean = false;\n private heartBeatTimeout: NodeJS.Timeout | null = null;\n private pendingQueries: Query[] = [];\n\n public readyState: ReadyState = ReadyState.Closed;\n\n\n // these parameters are referenced when an Error is thrown\n private host: string;\n private port: number = 443;\n\n constructor(config: AuroraDSQLWsConfig<{}>) {\n super();\n this.config = config;\n this.host = config.host || '';\n }\n\n\n onReadyForQuery() {\n if (this.pendingQueries.length > 0) {\n if (this.pendingQueries[0].numOfQueries > 0) {\n this.pendingQueries[0].numOfQueries--;\n }\n\n // remove the pendingQueries now that we received the reply only if the querycount is at 0\n if (this.pendingQueries[0].numOfQueries <= 0) {\n this.pendingQueries.shift();\n this.readyState = ReadyState.Open;\n this.disableHeartBeat = false;\n this.releaseMutex();\n this.processQueue();\n }\n }\n }\n\n handleHeartBeatResponse(data: Uint8Array): boolean {\n if (this.pendingQueries.length === 0 || !this.pendingQueries[0].isHeartBeat) return false;\n\n const messageType = String.fromCharCode(data[0]);\n\n if (messageType === \"D\") {\n const dataStr = new TextDecoder().decode(data.slice(5));\n // verify that it is from heartbeat\n if (dataStr.includes(\"1\")) {\n clearTimeout(this.heartBeatTimeout!);\n this.heartBeatTimeout = null;\n }\n } else if (messageType === \"Z\") {\n this.onReadyForQuery();\n }\n\n return true;\n }\n\n async connect(): Promise<this> {\n const url = `wss://${this.config.host}:${this.port}`;\n this.ws = new WebSocket(url);\n this.ws.binaryType = \"arraybuffer\";\n\n return new Promise((resolve, reject) => {\n if (this.ws != null) {\n this.ws.onopen = () => {\n this.connected = true;\n this.readyState = ReadyState.Open;\n resolve(this);\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n const data = new Uint8Array(event.data);\n\n if (this.config.connectionCheck) {\n if (this.handleHeartBeatResponse(data)) return;\n\n if (data.length > 0 && data[0] === MESSAGE_CODE_RFQ) {\n\n if (data.length > 5) {\n const status = String.fromCharCode(data[5]);\n\n if (status === \"E\") {\n // temporarily disable heart beat when the connection has a transaction error\n this.disableHeartBeat = true;\n this.cleanUpTxErrorState();\n } else {\n // I (IDLE) or T (Transaction) \n this.onReadyForQuery();\n }\n }\n }\n }\n\n this.emit(\"data\", Buffer.from(data));\n };\n\n this.ws.onerror = (event: Event) => {\n const msg = (event as ErrorEvent).message || \"WebSocket error\";\n const error = new Error(`${msg} ${this.host}:${this.port}`);\n this.emit(\"error\", error);\n reject(error);\n };\n\n this.ws.onclose = () => {\n if (this.heartBeatTimeout) {\n clearTimeout(this.heartBeatTimeout);\n this.heartBeatTimeout = null;\n }\n\n this.releaseMutex();\n\n this.connected = false;\n this.readyState = ReadyState.Closed;\n this.ws = null;\n this.emit(\"close\");\n\n if (this.config.onReservedConnectionClose) {\n this.config.onReservedConnectionClose(this.config.connectionId);\n }\n };\n }\n });\n }\n\n createQueryBuffer(sql: string): Uint8Array {\n const sqlBytes = new TextEncoder().encode(sql + \"\\0\");\n const length = 4 + sqlBytes.length;\n const buf = new Uint8Array(1 + length);\n const view = new DataView(buf.buffer);\n\n buf[0] = MESSAGE_CODE_SIMPLE_QUERY;\n view.setInt32(1, length, false);\n buf.set(sqlBytes, 5);\n\n return buf;\n }\n\n // future proofing in case postgres.js starts using the write function with 3 parameters\n // currently the library uses the write function with 2 parameters\n // callback is needed for copy related operations \n write(data: Buffer | Uint8Array, callback?: (err?: Error) => void): boolean;\n write(data: string, encoding?: string, callback?: (err?: Error) => void): boolean;\n\n write(\n data: Buffer | Uint8Array | string,\n encodingOrCallback?: string | ((err?: Error) => void),\n callback?: (err?: Error) => void\n ): boolean {\n\n let callbackFn: ((err?: Error) => void) | undefined;\n\n if (typeof encodingOrCallback === 'function') {\n callbackFn = encodingOrCallback;\n } else {\n callbackFn = callback;\n }\n\n let sendData: Uint8Array;\n if (typeof data === 'string') {\n const encoder = new TextEncoder();\n sendData = encoder.encode(data); // Always UTF-8\n } else if (data instanceof Buffer) {\n sendData = new Uint8Array(data);\n } else {\n sendData = data;\n }\n\n if (!this.ws || !this.connected) {\n if (callbackFn) {\n callbackFn(new Error(\"websocket is not connected\"));\n }\n return false;\n }\n\n let offset = 0;\n\n let queryCount = 0; // simple query \n let hasSync = false; // extended query protocol \n\n while (offset < sendData.length) {\n if (sendData[offset] === MESSAGE_CODE_SIMPLE_QUERY) {\n queryCount++;\n }\n\n if (sendData[offset] === MESSAGE_CODE_SYNC) {\n hasSync = true;\n }\n\n // Read message length to skip to next message\n if (offset + 5 <= sendData.length) {\n const length = new DataView(sendData.buffer, sendData.byteOffset + offset + 1, 4).getInt32(0, false);\n offset += 1 + length;\n } else {\n break;\n }\n }\n\n // directly send message to websocket when \n // * connection check (heart beat) is disabled \n // * Z (ReadyForQuery) message is not expected to be returned\n if (!this.config.connectionCheck || (queryCount == 0 && hasSync === false)) {\n try {\n this.ws.send(sendData);\n if (callbackFn) {\n callbackFn();\n }\n return true;\n } catch (err) {\n if (callbackFn) {\n callbackFn(err as Error);\n }\n return false;\n }\n }\n\n // if the buffer contains a query, send a heart beat first\n if (\n queryCount > 0 &&\n this.config.connectionCheck &&\n this.heartBeatTimeout === null && // make sure no existing heart beat time out is overwritten\n !this.disableHeartBeat\n ) {\n const buf = this.createQueryBuffer(\"select 1;\");\n this.pendingQueries.push({ buffer: buf, numOfQueries: 1, isHeartBeat: true });\n }\n this.pendingQueries.push({ buffer: sendData, numOfQueries: queryCount, isHeartBeat: false });\n this.processQueue();\n\n if (callbackFn) {\n callbackFn();\n }\n\n return true;\n }\n\n private releaseMutex() {\n if (this.mutexRelease) {\n this.mutexRelease();\n this.mutexRelease = null;\n }\n }\n\n // cleans up the error state during a transaction error \n private cleanUpTxErrorState() {\n // throw away last query as the result set has a transaction error and no more result set should return \n if (this.pendingQueries.length > 0) {\n this.pendingQueries.shift();\n }\n\n // since heart beat cant be performed during a transaction error, discard heart beat queries which are already in pending queries\n while (this.pendingQueries.length > 0 && this.pendingQueries[0].isHeartBeat) {\n this.pendingQueries.shift();\n }\n this.readyState = ReadyState.Open;\n this.releaseMutex();\n\n if (this.pendingQueries.length > 0) {\n this.processQueue();\n }\n }\n\n private async processQueue(): Promise<void> {\n if (\n this.mutexRelease ||\n this.readyState !== ReadyState.Open ||\n this.pendingQueries.length === 0\n ) {\n return;\n }\n\n this.mutexRelease = await this.mutex.acquire();\n\n // it is possible that the pendingQueries is now empty \n if (this.pendingQueries.length == 0) {\n this.releaseMutex();\n return;\n }\n\n const data = this.pendingQueries[0];\n\n if (data.buffer.length > 0 && data.buffer[0] === MESSAGE_CODE_SIMPLE_QUERY) {\n this.readyState = ReadyState.Querying;\n }\n\n if (data.isHeartBeat) {\n this.heartBeatTimeout = setTimeout(() => {\n console.log(\"Heart beat timed out\");\n if (this.ws) {\n this.ws.close(1000, \"Heart beat timeout\");\n }\n }, HEARTBEAT_TIMEOUT);\n }\n\n if (this.ws) {\n this.ws.send(data.buffer);\n } else {\n throw Error(\"Websocket is not initialized\");\n }\n }\n\n end(): void {\n if (this.ws && this.readyState !== ReadyState.Closed) {\n this.ws.close();\n }\n }\n\n destroy(): void {\n if (this.ws) {\n this.ws.close();\n }\n }\n\n // Following functions needs to be defined as connection.js \n // in postgres.js can call these functions but they will be no-op\n setKeepAlive(): this {\n return this;\n }\n\n resume(): this {\n return this;\n }\n\n pause(): this {\n return this;\n }\n\n cork(): this {\n return this;\n }\n\n uncork(): this {\n return this;\n }\n}\n\nexport function createPostgresWs(\n config: AuroraDSQLWsConfig<{}>\n): () => Promise<PostgresWs> {\n return async () => {\n\n const socket = new PostgresWs(config);\n await socket.connect();\n return socket;\n };\n}\n","/*\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport postgres, { PostgresType } from \"postgres\";\nimport {\n AwsCredentialIdentity,\n AwsCredentialIdentityProvider,\n} from \"@aws-sdk/types\";\nimport { DsqlSigner, DsqlSignerConfig } from \"@aws-sdk/dsql-signer\";\nimport { createPostgresWs } from \"./postgres-web-socket\";\n\n// Version is injected at build time via tsdown\ndeclare const __VERSION__: string;\nconst version = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : \"0.0.0\";\n\nconst ADMIN = \"admin\";\nconst DEFAULT_DATABASE = \"postgres\";\nconst DEFAULT_EXPIRY = 30; // Based on default Postgres.js connect_timeout\n// String components of a DSQL hostname, <Cluster ID>.dsql.<region>.on.aws\nconst PRE_REGION_HOST_PATTERN = \".dsql.\";\nconst POST_REGION_HOST_PATTERN = \".on.aws\";\nconst APPLICATION_NAME = `aurora-dsql-nodejs-postgresjs/${version}`;\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction parseConnectionParams(\n urlOrOptions: string | any,\n options?: any\n): { opts: any; } {\n let opts: any;\n let host: string;\n let username: string;\n let database: string | undefined;\n\n if (typeof urlOrOptions === \"string\") {\n let parsedOptions = parseConnectionString(urlOrOptions);\n host = options?.hostname || options?.host || parsedOptions.host || process.env.PGHOST!;\n username = options?.username || options?.user || parsedOptions.username! ||\n process.env.PGUSERNAME || process.env.USER || ADMIN;\n database = options?.database || options?.db || parsedOptions.database || process.env.PGDATABASE;\n opts = {\n ...options,\n ssl: options?.ssl || parsedOptions.ssl\n };\n } else {\n host = urlOrOptions?.hostname || urlOrOptions?.host || process.env.PGHOST!;\n username = urlOrOptions?.username || urlOrOptions?.user ||\n process.env.PGUSERNAME || process.env.USER || ADMIN;\n database = urlOrOptions?.database || urlOrOptions?.db || process.env.PGDATABASE;\n opts = { ...urlOrOptions };\n }\n\n if (Array.isArray(host)) {\n throw new Error(\"Multi-host configurations are not supported for Aurora DSQL\");\n }\n\n if (!opts.region) {\n opts.region = parseRegionFromHost(host);\n }\n\n if (isClusterID(host)) {\n host = buildHostnameFromIdAndRegion(host, opts.region);\n }\n\n if (!database) {\n opts.database = DEFAULT_DATABASE;\n }\n\n opts.host = host;\n opts.username = username;\n opts.connection = {\n ...opts.connection,\n application_name: buildApplicationName(opts.connection?.application_name),\n };\n\n return { opts };\n}\n\nfunction setupDsqlSigner(opts: any): { signerConfig: DsqlSignerConfig; } {\n\n let signerConfig: DsqlSignerConfig = {\n hostname: opts.host,\n region: opts.region,\n expiresIn: opts.tokenDurationSecs ?? opts.connect_timeout ??\n (process.env.PGCONNECT_TIMEOUT ? parseInt(process.env.PGCONNECT_TIMEOUT) : undefined) ??\n DEFAULT_EXPIRY,\n profile: opts.profile || process.env.AWS_PROFILE || \"default\",\n };\n\n if (opts.customCredentialsProvider) {\n signerConfig.credentials = opts.customCredentialsProvider;\n }\n\n return { signerConfig };\n}\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n url: string,\n options?: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n options: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n urlOrOptions: string | AuroraDSQLConfig<T>,\n options?: AuroraDSQLConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n> {\n\n let { opts } = parseConnectionParams(urlOrOptions, options);\n const { signerConfig } = setupDsqlSigner(opts);\n let signer = new DsqlSigner(signerConfig);\n\n if (!opts.ssl) opts.ssl = true;\n const postgresOpts: postgres.Options<T> = {\n ...opts,\n pass: () => getToken(signer, opts.username),\n };\n return typeof urlOrOptions === \"string\"\n ? postgres(urlOrOptions, postgresOpts)\n : postgres(postgresOpts);\n}\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n url: string,\n options?: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n options: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n>;\n\nexport function auroraDSQLWsPostgres<\n T extends Record<string, postgres.PostgresType> = {}\n>(\n urlOrOptions: string | AuroraDSQLWsConfig<T>,\n options?: AuroraDSQLWsConfig<T>\n): postgres.Sql<\n Record<string, postgres.PostgresType> extends T\n ? {}\n : {\n [type in keyof T]: T[type] extends {\n serialize: (value: infer R) => any;\n parse: (raw: any) => infer R;\n }\n ? R\n : never;\n }\n> {\n\n let { opts } = parseConnectionParams(urlOrOptions, options);\n const { signerConfig } = setupDsqlSigner(opts);\n\n if (!opts.pass) {\n opts.pass = async () => {\n let signer = new DsqlSigner(signerConfig);\n return await getToken(signer, opts.username);\n };\n }\n\n // swap out socket to use websocket\n opts.socket = createPostgresWs(opts);\n\n // ssl must be false otherwise postgres.js will try to use the net.socket \n opts.ssl = false;\n\n if (opts.connectionCheck == undefined) {\n // disable connection check by default \n // connection check sends a 'select 1' before every query\n opts.connectionCheck = false;\n }\n\n opts.port = 443;\n\n return typeof urlOrOptions === \"string\"\n ? postgres(urlOrOptions, opts)\n : postgres(opts);\n}\n\n\nfunction parseConnectionString(url: string): {\n database?: string;\n host?: string;\n username?: string;\n ssl?: string;\n} {\n let decodedUrl = decodeURI(url);\n const parsed = new URL(decodedUrl);\n\n // Check for multi-host\n if (parsed.hostname?.includes(\",\")) {\n throw new Error(\n \"Multi-host connection strings are not supported for Aurora DSQL\"\n );\n }\n\n return {\n username: parsed.username,\n host: parsed.hostname,\n database: parsed.pathname?.slice(1),\n ssl:\n parsed.searchParams.get(\"ssl\") ||\n parsed.searchParams.get(\"sslmode\") ||\n undefined,\n };\n}\n\nfunction parseRegionFromHost(host: string): string | undefined {\n if (!host) {\n throw new Error(\"Hostname is required to parse region\");\n }\n\n const match = host.match(\n /^(?<instance>[^.]+)\\.(?<dns>dsql(?:-[^.]+)?)\\.(?<domain>(?<region>[a-zA-Z0-9-]+)\\.on\\.aws\\.?)$/i\n );\n if (match?.groups) {\n return match.groups.region;\n }\n throw new Error(`Unable to parse region from hostname: ${host}`);\n}\n\nfunction isClusterID(host: string) {\n return !host.includes(\".\");\n}\n\nfunction buildHostnameFromIdAndRegion(\n host: string,\n region: string | undefined\n) {\n return host + PRE_REGION_HOST_PATTERN + region + POST_REGION_HOST_PATTERN;\n}\n\nasync function getToken(signer: DsqlSigner, username: string): Promise<string> {\n if (username === ADMIN) {\n return await signer.getDbConnectAdminAuthToken();\n } else {\n return await signer.getDbConnectAuthToken();\n }\n}\n\n/**\n * Build the application_name with optional ORM prefix.\n *\n * If ormPrefix is provided and non-empty after trimming, prepends it to\n * the connector identifier. Otherwise, returns the connector's application_name.\n *\n * PostgreSQL limits application_name to 64 characters. After accounting for\n * the connector identifier and separator, 27 characters are available for\n * the ORM name.\n *\n * @param ormPrefix Optional ORM name to prepend (e.g., \"prisma\")\n * @returns Formatted application_name string\n */\nfunction buildApplicationName(ormPrefix?: string): string {\n if (ormPrefix) {\n const trimmed = ormPrefix.trim();\n if (trimmed) {\n return `${trimmed}:${APPLICATION_NAME}`;\n }\n }\n return APPLICATION_NAME;\n}\n\nexport interface AuroraDSQLConfig<T extends Record<string, PostgresType<T>>> extends Omit<postgres.Options<T>, 'password' | 'pass'> {\n\n region?: string;\n\n profile?: string;\n\n tokenDurationSecs?: number;\n\n customCredentialsProvider?: AwsCredentialIdentity | AwsCredentialIdentityProvider;\n\n}\nexport interface AuroraDSQLWsConfig<T extends Record<string, PostgresType<T>>>\n extends Omit<postgres.Options<T>, \"socket\" | \"ssl\" | \"port\"> {\n region?: string;\n tokenDurationSecs?: number;\n customCredentialsProvider?:\n | AwsCredentialIdentity\n | AwsCredentialIdentityProvider;\n connectionCheck?: boolean;\n connectionId?: string;\n onReservedConnectionClose?: (connectionId?: string) => void;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws/aurora-dsql-postgresjs-connector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "An AWS Aurora DSQL connector with IAM authentication for Postgres.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/awslabs/aurora-dsql-
|
|
8
|
+
"url": "git+https://github.com/awslabs/aurora-dsql-connectors.git",
|
|
9
|
+
"directory": "node/postgres-js"
|
|
9
10
|
},
|
|
10
|
-
"homepage": "https://github.com/awslabs/aurora-dsql-
|
|
11
|
+
"homepage": "https://github.com/awslabs/aurora-dsql-connectors/tree/main/node/postgres-js",
|
|
11
12
|
"keywords": [
|
|
12
13
|
"aws",
|
|
13
14
|
"aurora",
|
|
@@ -80,7 +81,7 @@
|
|
|
80
81
|
"postgres": "^3.4.7",
|
|
81
82
|
"publint": "^0.3.16",
|
|
82
83
|
"ts-jest": "^29.4.5",
|
|
83
|
-
"tsdown": "^0.
|
|
84
|
+
"tsdown": "^0.20.2",
|
|
84
85
|
"typescript": "^5.9.3"
|
|
85
86
|
}
|
|
86
87
|
}
|