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
65 changes: 33 additions & 32 deletions .github/workflows/typescript-type-orm-integ-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ name: type-orm integration tests

on:
push:
branches: [ main ]
branches: [main]
paths:
- 'typescript/type-orm/**'
- '.github/workflows/typescript-type-orm-integ-tests.yml'
- "typescript/type-orm/**"
- ".github/workflows/typescript-type-orm-integ-tests.yml"
pull_request:
branches: [ main ]
branches: [main]
paths:
- 'typescript/type-orm/**'
- '.github/workflows/typescript-type-orm-integ-tests.yml'
- "typescript/type-orm/**"
- ".github/workflows/typescript-type-orm-integ-tests.yml"
# Give us a button to allow running the workflow on demand for testing.
workflow_dispatch:
inputs:
tags:
description: 'Manual Workflow Run'
description: "Manual Workflow Run"
required: false
type: string

Expand All @@ -29,32 +29,33 @@ jobs:
actions: read
checks: write
pull-requests: write

steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '18.x'
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "18.x"

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.TYPESCRIPT_IAM_ROLE }}
aws-region: us-east-1
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.TYPESCRIPT_IAM_ROLE }}
aws-region: us-east-1

- name: Configure and run integration for typeORM HowTo
working-directory: ./typescript/type-orm
env:
CLUSTER_ENDPOINT: ${{ secrets.TYPESCRIPT_TYPE_ORM_CLUSTER_ENDPOINT }}
REGION: ${{ secrets.TYPESCRIPT_TYPE_ORM_CLUSTER_REGION }}
run: |
npm install
npm run build
npm run migrations-drop-table
npm run migrations-create-table
npm run migrations-run
npm test

- name: Configure and run integration for typeORM HowTo
working-directory: ./typescript/type-orm
env:
CLUSTER_USER: "admin"
CLUSTER_ENDPOINT: ${{ secrets.TYPESCRIPT_TYPE_ORM_CLUSTER_ENDPOINT }}
REGION: ${{ secrets.TYPESCRIPT_TYPE_ORM_CLUSTER_REGION }}
run: |
npm install
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O root.pem
npm run build
npm run migrations-drop-table
npm run migrations-create-table
npm run migrations-run
npm test
102 changes: 86 additions & 16 deletions typescript/type-orm/README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,112 @@
# Aurora DSQL TypeORM code examples
# TypeORM with Aurora DSQL

## Overview

The code examples in this topic show you how to use the TypeORM work with Aurora DSQL.
This code example demonstrates how to use `TypeORM` with Amazon Aurora DSQL. The example shows you how to connect to an Aurora DSQL cluster and perform basic database operations.

## Run the examples
Aurora DSQL is a distributed SQL database service that provides high availability and scalability for your PostgreSQL-compatible applications. `TypeORM` is a popular ORM for TypeScript and JavaScript that allows you to interact with PostgreSQL databases using object-relational mapping patterns.

## 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

* node version >=18.0 is needed
- 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 18.0.0](https://nodejs.org) or later.
- 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.

### Setup test running environment
### Download the Amazon root certificate from the official trust store

```sh
Download the Amazon root certificate from the official trust store. This example shows one of the available certs that
can be used by the client. Other certs such as AmazonRootCA2.pem, AmazonRootCA3.pem, etc. can also be used.

```
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O root.pem
```

### Set up environment for examples

```
npm install
```

### Run the example tests
## Run the code

```sh
# Use the account credentials dedicated for javascript
export CLUSTER_ENDPOINT="<your cluster endpoint>"
export REGION="<your cluster region>"
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>"
```

```sh
# The following 3 commands are needed only if this is your
# first time running the application.
Run the example:

```
# first time running the application
npm run build
npm run migrations-create-table
npm run migrations-run

# Run the tests
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)
- [TypeORM Documentation](https://typeorm.io/)
- [AWS SDK for JavaScript Documentation](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/)

---

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

SPDX-License-Identifier: MIT-0
8 changes: 7 additions & 1 deletion typescript/type-orm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"migrations-drop-table": "node dist/src/drop-migrations-table.js",
"migrations-run": "npm run typeorm migration:run -- -d ./dist/src/data-source --transaction none",
"migrations-revert": "npm run typeorm migration:revert -- -d ./dist/src/data-source --transaction none",
"build": "tsc --build",
"build:compile": "tsc --build",
"build:copy": "mkdir -p dist/src && cp root.pem dist/src",
"build": "npm-run-all build:compile build:copy",
"clean": "rm -rf build && rm -rf dist",
"typeorm": "ts-node ./node_modules/typeorm/cli.js",
"start": "node dist/index.js",
Expand All @@ -27,9 +29,13 @@
"dependencies": {
"@aws-sdk/dsql-signer": "^3.705.0",
"assert": "^2.1.0",
"npm-run-all": "^4.1.5",
"pg": "^8.13.1",
"ts-node": "^10.9.2",
"typeorm": "^0.3.20",
"uuid": "^11.0.3"
},
"engines": {
"node": ">=18.0.0"
}
}
77 changes: 57 additions & 20 deletions typescript/type-orm/src/create-migrations-table.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,67 @@
import { DsqlSigner } from "@aws-sdk/dsql-signer";
import { Client } from 'pg'
import { Client } from "pg";
import { getEnvironmentVariables } from "./utils";
import { escapeIdentifier } from "pg/lib/utils";
import fs from "fs";
import path from "path";

const createMigrationsTable = async () => {
const { user, clusterEndpoint, region } = getEnvironmentVariables();

const clusterEndpoint = process.env.CLUSTER_ENDPOINT;
const region = process.env.REGION;
const signer = new DsqlSigner({
hostname: clusterEndpoint,
region: region,
});

const signer = new DsqlSigner({
hostname: clusterEndpoint,
region: region
});
let token: string;
let client: Client | undefined;
let schema = "public";

const token = await signer.getDbConnectAdminAuthToken();
try {
if (user === "admin") {
token = await signer.getDbConnectAdminAuthToken();
} else {
// Non admin user
token = await signer.getDbConnectAuthToken();
schema = "myschema";
}

const client = new Client({
user: "admin",
password: token,
host: clusterEndpoint,
port: 5432,
database: "postgres",
ssl: true
})
client = new Client({
user: user,
password: token,
host: clusterEndpoint,
port: 5432,
database: "postgres",
ssl: {
ca: fs.readFileSync(path.join(__dirname, "root.pem")),
rejectUnauthorized: true,
},
});

await client.connect();
await client.query('CREATE TABLE IF NOT EXISTS "migrations" ("id" UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL , "timestamp" bigint NOT NULL, "name" character varying NOT NULL)');
await client.end();
}
// The following is required to set the default schema for the migration scripts
// The schema can't be changed when the migration script is generated
await client.query(
`ALTER USER ${escapeIdentifier(user)}
set SEARCH_PATH = ${escapeIdentifier(schema)};`
);
await client.query(
`CREATE TABLE IF NOT EXISTS
${client.escapeIdentifier(schema)}."migrations" (
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"timestamp" bigint NOT NULL,
"name" character varying NOT NULL
)`
);
console.log(`Created the migration table in ${schema}`);
} catch (error) {
console.error("Failed to create the migration table:", error);
throw error;
} finally {
if (client) {
await client.end();
}
}
};

createMigrationsTable();
createMigrationsTable();
Loading
Loading