Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/javascript-node-postgres-integ-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ on:
push:
branches: [ main ]
paths:
- 'javascript/nodejs/**'
- 'javascript/node-postgres/**'
- '.github/workflows/javascript-node-postgres-integ-tests.yml'
pull_request:
branches: [ main ]
paths:
- 'javascript/nodejs/**'
- '.github/workflows/jjavascript-node-postgres-integ-tests.yml'
- 'javascript/node-postgres/**'
- '.github/workflows/javascript-node-postgres-integ-tests.yml'
# Give us a button to allow running the workflow on demand for testing.
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -46,10 +46,11 @@ jobs:
aws-region: us-east-1

- name: Configure and run integration for nodejs HowTo
working-directory: ./javascript/nodejs
working-directory: ./javascript/node-postgres
env:
CLUSTER_ENDPOINT: ${{ secrets.JAVASCRIPT_NODEJS_CLUSTER_ENDPOINT }}
REGION: ${{ secrets.JAVASCRIPT_NODEJS_CLUSTER_REGION }}
CLUSTER_USER: 'admin'
run: |
npm install
npm test
Expand Down
4 changes: 4 additions & 0 deletions javascript/node-postgres/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/node_modules
/build
/dist
/coverage
103 changes: 103 additions & 0 deletions javascript/node-postgres/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# node-postgres with Aurora DSQL

## Overview

This code example demonstrates how to use `node-postgres` with Amazon Aurora DSQL.
The example shows you how to connect to an Aurora DSQL cluster and perform basic database operations.

Aurora DSQL is a distributed SQL database service that provides high availability and scalability for
your PostgreSQL-compatible applications. `node-postgres` is a popular PostgreSQL adapter for Node.js that allows
you to interact with PostgreSQL databases using JavaScript code.

## About the code example

The example demonstrates a flexible connection approach that works for both admin and non-admin users:

* When connecting as an **admin user**, the example uses the `public` schema and generates an admin authentication
token.
* When connecting as a **non-admin user**, the example uses a custom `myschema` schema and generates a standard
authentication token.

The code automatically detects the user type and adjusts its behavior accordingly.

## ⚠️ Important

* Running this code might result in charges to your AWS account.
* We recommend that you grant your code least privilege. At most, grant only the
minimum permissions required to perform the task. For more information, see
[Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
* This code is not tested in every AWS Region. For more information, see
[AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).

## Run the example

### Prerequisites

* You must have an AWS account, and have your default credentials and AWS Region
configured as described in the
[Globally configuring AWS SDKs and tools](https://docs.aws.amazon.com/credref/latest/refdocs/creds-config-files.html)
guide.
* Node.js: Ensure you have Node.js 18+ installed.

```bash
node --version
```

It should output something similar to `v18.x` or higher.

* You must have an Aurora DSQL cluster. For information about creating an Aurora DSQL cluster, see the
[Getting started with Aurora DSQL](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/getting-started.html)
guide.
* If connecting as a non-admin user, ensure the user is linked to an IAM role and is granted access to the `myschema`
schema. See the
[Using database roles with IAM roles](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/using-database-and-iam-roles.html)
guide.

### Run the code

The example demonstrates the following operations:

- Opening a connection to an Aurora DSQL cluster
- Creating a table
- Inserting and querying data

The example is designed to work with both admin and non-admin users:

- When run as an admin user, it uses the `public` schema
- When run as a non-admin user, it uses the `myschema` schema

**Note:** running the example will use actual resources in your AWS account and may incur charges.

Set environment variables for your cluster details:

```bash
# e.g. "admin"
export CLUSTER_USER="<your user>"

# e.g. "foo0bar1baz2quux3quuux4.dsql.us-east-1.on.aws"
export CLUSTER_ENDPOINT="<your endpoint>"

# e.g. "us-east-1"
export REGION="<your region>"
```

Run the example:

```bash
npm install
npm test
```

The example contains comments explaining the code and the operations being performed.

## Additional resources

* [Amazon Aurora DSQL Documentation](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/what-is-aurora-dsql.html)
* [node-postgres Documentation](https://node-postgres.com/)
* [AWS SDK for JavaScript Documentation](https://docs.aws.amazon.com/sdk-for-javascript/)

---

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
"@aws-sdk/dsql-signer": "^3.705.0",
"assert": "2.1.0",
"pg": "^8.13.1",
"uuid": "^11.0.2",
"cross-spawn": "7.0.6"
"uuid": "^11.0.2"
},
"devDependencies": {
"jest": "^29.7.0"
Expand Down
92 changes: 92 additions & 0 deletions javascript/node-postgres/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { DsqlSigner } from "@aws-sdk/dsql-signer";
import pg from "pg";
import assert from "node:assert";
const { Client } = pg;

const ADMIN = "admin";
const NON_ADMIN_SCHEMA = "myschema";

async function getConnection(clusterEndpoint, user, region) {
const signer = new DsqlSigner({
hostname: clusterEndpoint,
region,
});
let token;
// Generate a fresh password token for each connection, to ensure the token is
// not expired when the connection is established
if (user === ADMIN) {
token = await signer.getDbConnectAdminAuthToken();
}
else {
signer.user = user;
token = await signer.getDbConnectAuthToken()
}
// <https://node-postgres.com/apis/client>
// By default `rejectUnauthorized` is true in TLS options
// <https://nodejs.org/api/tls.html#tls_tls_connect_options_callback>
// The config does not offer any specific parameter to set sslmode to verify-full
// Settings are controlled either via connection string or by setting
// rejectUnauthorized to false in ssl options
let client = new Client({
host: clusterEndpoint,
user: user,
password: token,
database: "postgres",
port: 5432,
// <https://node-postgres.com/announcements> for version 8.0
ssl: true
});

// Connect
await client.connect();
console.log("Successfully opened connection");
return client;
}

async function example() {

const clusterEndpoint = process.env.CLUSTER_ENDPOINT;
assert(clusterEndpoint);
const user = process.env.CLUSTER_USER;
assert(user);
const region = process.env.REGION;
assert(region);

let client;
try {
client = await getConnection(clusterEndpoint, user, region);

if (user !== ADMIN) {
await client.query("SET search_path=" + NON_ADMIN_SCHEMA)
}

// Create a new table
await client.query(`CREATE TABLE IF NOT EXISTS owner (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(30) NOT NULL,
city VARCHAR(80) NOT NULL,
telephone VARCHAR(20)
)`);

// Insert some data
await client.query("INSERT INTO owner(name, city, telephone) VALUES($1, $2, $3)",
["John Doe", "Anytown", "555-555-1900"]
);

// Check that data is inserted by reading it back
const result = await client.query("SELECT id, city FROM owner where name='John Doe'");
assert.deepEqual(result.rows[0].city, "Anytown")
assert.notEqual(result.rows[0].id, null)

await client.query("DELETE FROM owner where name='John Doe'");

} catch (error) {
console.error(error);
raise
} finally {
client?.end()
}
Promise.resolve()
}

export { example }
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { example } from '../src/index.js';

test('Smoke test', async () => {
await example(process.env.CLUSTER_ENDPOINT, process.env.REGION);
await example();
return Promise.resolve();
});
32 changes: 0 additions & 32 deletions javascript/nodejs/README.md

This file was deleted.

Loading
Loading