Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add typeorm examples #255

Merged
merged 10 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 2 additions & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:

- name: Calculate base code coverage
run: |
export CUR_COVER=$(npx tap | xargs -0 node -p 'parseInt(process.argv[1].split("\nAll files")[1].split("|")[1].trim(), 10)')
export CUR_COVER=$(npx tap test | xargs -0 node -p 'parseInt(process.argv[1].split("\nAll files")[1].split("|")[1].trim(), 10)')
jackwotherspoon marked this conversation as resolved.
Show resolved Hide resolved
echo "CUR_COVER=$CUR_COVER" >> $GITHUB_ENV

- name: Checkout PR branch
Expand All @@ -75,7 +75,7 @@ jobs:

- name: Calculate PR code coverage
run: |
export PR_COVER=$(npx tap | xargs -0 node -p 'parseInt(process.argv[1].split("\nAll files")[1].split("|")[1].trim(), 10)')
export PR_COVER=$(npx tap test | xargs -0 node -p 'parseInt(process.argv[1].split("\nAll files")[1].split("|")[1].trim(), 10)')
echo "PR_COVER=$PR_COVER" >> $GITHUB_ENV

- name: Verify code coverage. If your reading this and the step has failed, please add tests to cover your changes.
Expand Down
102 changes: 94 additions & 8 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:

- name: Run Tests v14.x
if: "${{ matrix.node-version == 'v14.x' }}"
run: npx tap -c -t0 --no-coverage --no-ts --node-arg="--require" --node-arg="./scripts/tap16-adapter.js" --node-arg="--no-warnings" --node-arg="--loader" --node-arg="ts-node/esm"
run: npx tap -c -t0 --no-coverage --no-ts --node-arg="--require" --node-arg="./scripts/tap16-adapter.js" --node-arg="--no-warnings" --node-arg="--loader" --node-arg="ts-node/esm" test
timeout-minutes: 5

- name: Run Tests
Expand All @@ -111,7 +111,7 @@ jobs:
TAP_ALLOW_INCOMPLETE_COVERAGE: "${{ matrix.os == 'windows-latest' && '1' || '0' }}"
TAP_ALLOW_EMPTY_COVERAGE: "${{ matrix.os == 'windows-latest' && '1' || '0' }}"
if: "${{ matrix.node-version != 'v14.x' }}"
run: npx tap -c -t0 -o test_results.tap
run: npx tap -c -t0 -o test_results.tap test
timeout-minutes: 5

- name: Convert test output to XML
Expand Down Expand Up @@ -191,12 +191,6 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Setup self-direct dependency
run: npm link

- name: Link self-direct dependency
run: npm link @google-cloud/cloud-sql-connector

- name: Transpile TypeScript
run: npm run prepare

Expand Down Expand Up @@ -236,6 +230,12 @@ jobs:
if: "${{ matrix.node-version == 'v14.x' }}"
run: npm uninstall @typescript-eslint/eslint-plugin eslint-plugin-prettier tap && npm install tap@16 ts-node && npx npm@7 pkg delete tap

- name: Setup self-direct dependency
run: npm link

- name: Link self-direct dependency
run: npm link @google-cloud/cloud-sql-connector

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this block since it was interfering with the npm uninstall from the Setup v14.x-compatible tap step above

- name: Run System Tests v14.x
env:
MYSQL_CONNECTION_NAME: '${{ steps.secrets.outputs.MYSQL_CONNECTION_NAME }}'
Expand Down Expand Up @@ -304,3 +304,89 @@ jobs:
curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-1.1.0/flakybot-darwin-amd64 -o flakybot -s -L
chmod +x ./flakybot
./flakybot --repo ${{github.repository}} --commit_hash ${{github.sha}} --build_url https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}

sample-tests:
jackwotherspoon marked this conversation as resolved.
Show resolved Hide resolved
# run job on proper workflow event triggers (skip job for pull_request event from forks and only run pull_request_target for "tests: run" label)
if: "${{ (github.event.action != 'labeled' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name) || github.event.label.name == 'tests: run' }}"
name: Sample tests
permissions:
contents: 'read'
id-token: 'write'

runs-on: ubuntu-latest

steps:

- name: Checkout Repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }}

- name: Setup Node.js
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
with:
node-version: ${{ matrix.node-version }}
ruyadorno marked this conversation as resolved.
Show resolved Hide resolved

- name: Install dependencies
run: npm ci

- name: Setup self-direct dependency
run: npm link

- name: Link self-direct dependency
run: npm link @google-cloud/cloud-sql-connector

- name: Transpile TypeScript
run: npm run prepare

- id: 'auth'
name: Authenticate to Google Cloud
uses: google-github-actions/auth@35b0e87d162680511bf346c299f71c9c5c379033 # v1.1.1
with:
workload_identity_provider: ${{ secrets.PROVIDER_NAME }}
service_account: ${{ secrets.SERVICE_ACCOUNT }}
access_token_lifetime: 600s

- id: 'secrets'
name: Get secrets
uses: google-github-actions/get-secretmanager-secrets@4d6d3dfd94110800dda8d84109cb6da0f6a5919d # v1.0.1
with:
secrets: |-
MYSQL_CONNECTION_NAME:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_CONNECTION_NAME
MYSQL_IAM_CONNECTION_NAME:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_IAM_CONNECTION_NAME
MYSQL_USER:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_USER
MYSQL_IAM_USER:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_USER_IAM_NODE
MYSQL_PASS:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_PASS
MYSQL_DB:${{ secrets.GOOGLE_CLOUD_PROJECT }}/MYSQL_DB
POSTGRES_CONNECTION_NAME:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_CONNECTION_NAME
POSTGRES_IAM_CONNECTION_NAME:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_IAM_CONNECTION_NAME
POSTGRES_USER:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_USER
POSTGRES_IAM_USER:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_USER_IAM_NODE
POSTGRES_PASS:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_PASS
POSTGRES_DB:${{ secrets.GOOGLE_CLOUD_PROJECT }}/POSTGRES_DB
SQLSERVER_CONNECTION_NAME:${{ secrets.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_CONNECTION_NAME
SQLSERVER_USER:${{ secrets.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_USER
SQLSERVER_PASS:${{ secrets.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_PASS
SQLSERVER_DB:${{ secrets.GOOGLE_CLOUD_PROJECT }}/SQLSERVER_DB

- name: Run Sample Tests
env:
MYSQL_CONNECTION_NAME: '${{ steps.secrets.outputs.MYSQL_CONNECTION_NAME }}'
MYSQL_IAM_CONNECTION_NAME: '${{ steps.secrets.outputs.MYSQL_IAM_CONNECTION_NAME }}'
MYSQL_USER: '${{ steps.secrets.outputs.MYSQL_USER }}'
MYSQL_IAM_USER: '${{ steps.secrets.outputs.MYSQL_IAM_USER }}'
MYSQL_PASS: '${{ steps.secrets.outputs.MYSQL_PASS }}'
MYSQL_DB: '${{ steps.secrets.outputs.MYSQL_DB }}'
POSTGRES_CONNECTION_NAME: '${{ steps.secrets.outputs.POSTGRES_CONNECTION_NAME }}'
POSTGRES_IAM_CONNECTION_NAME: '${{ steps.secrets.outputs.POSTGRES_IAM_CONNECTION_NAME }}'
POSTGRES_USER: '${{ steps.secrets.outputs.POSTGRES_USER }}'
POSTGRES_IAM_USER: '${{ steps.secrets.outputs.POSTGRES_IAM_USER }}'
POSTGRES_PASS: '${{ steps.secrets.outputs.POSTGRES_PASS }}'
POSTGRES_DB: '${{ steps.secrets.outputs.POSTGRES_DB }}'
SQLSERVER_CONNECTION_NAME: '${{ steps.secrets.outputs.SQLSERVER_CONNECTION_NAME }}'
SQLSERVER_USER: '${{ steps.secrets.outputs.SQLSERVER_USER }}'
SQLSERVER_PASS: '${{ steps.secrets.outputs.SQLSERVER_PASS }}'
SQLSERVER_DB: '${{ steps.secrets.outputs.SQLSERVER_DB }}'
run: npx tap -c -t0 --disable-coverage --allow-empty-coverage examples/*/{mysql2,pg,tedious}/*.test{.cjs,.mjs,.ts} -o test_results.tap
timeout-minutes: 5
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
!/package-lock.json
!/README.md
!/LICENSE{,.*}
!/example
!/examples
!/scripts
!/system-test
!/tap-snapshots
Expand Down
19 changes: 19 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Cloud SQL Node.js Connector Examples

Welcome to the **Cloud SQL Node.js Connector** examples directory. Here you can
find a collection of ready-to-use samples showing how to use the library with
some of the most popular database libraries and frameworks.

## Available Examples

### TypeORM

- [MySQL (CommonJS)](./typeorm/mysql2/connect.cjs)
- [MySQL (ESM)](./typeorm/mysql2/connect.mjs)
- [MySQL (TypeScript)](./typeorm/mysql2/connect.ts)
- [PostgreSQL (CommonJS)](./typeorm/pg/connect.cjs)
- [PostgreSQL (ESM)](./typeorm/pg/connect.mjs)
- [PostgreSQL (TypeScript)](./typeorm/pg/connect.ts)
- [SQL Server (CommonJS)](./typeorm/tedious/connect.cjs)
- [SQL Server (ESM)](./typeorm/tedious/connect.mjs)
- [SQL Server (TypeScript)](./typeorm/tedious/connect.ts)
44 changes: 44 additions & 0 deletions examples/typeorm/mysql2/connect.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const {Connector} = require('@google-cloud/cloud-sql-connector');
const typeorm = require('typeorm');

async function connect({ instanceConnectionName, username, database }) {
const connector = new Connector();
const clientOpts = await connector.getOptions({
instanceConnectionName,
ipType: 'PUBLIC',
authType: 'IAM',
});
const dataSource = new typeorm.DataSource({
type: 'mysql',
username,
database,
extra: clientOpts,
});
await dataSource.initialize()

return {
dataSource,
async close() {
await dataSource.destroy();
connector.close();
}
};
};

module.exports = {
connect,
};
40 changes: 40 additions & 0 deletions examples/typeorm/mysql2/connect.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {Connector} from '@google-cloud/cloud-sql-connector';
import {DataSource} from 'typeorm';

export async function connect({ instanceConnectionName, username, database }) {
const connector = new Connector();
const clientOpts = await connector.getOptions({
instanceConnectionName,
ipType: 'PUBLIC',
authType: 'IAM',
});
const dataSource = new DataSource({
type: 'mysql',
username,
database,
extra: clientOpts,
});
await dataSource.initialize()

return {
dataSource,
async close() {
await dataSource.destroy();
connector.close();
}
};
};
28 changes: 28 additions & 0 deletions examples/typeorm/mysql2/connect.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const t = require('tap');
const connector = require('./connect.cjs');

t.test('mysql2 typeorm cjs', async t => {
const { dataSource, close } = await connector.connect({
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME,
username: process.env.MYSQL_IAM_USER,
database: process.env.MYSQL_DB,
});
const [{ now }] = await dataSource.manager.query('SELECT NOW() as now')
t.ok(now.getTime(), 'should have valid returned date object');
await close();
});

27 changes: 27 additions & 0 deletions examples/typeorm/mysql2/connect.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import t from 'tap';
import {connect} from './connect.mjs';

t.test('mysql2 typeorm mjs', async t => {
const { dataSource, close } = await connect({
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME,
username: process.env.MYSQL_IAM_USER,
database: process.env.MYSQL_DB,
});
const [{ now }] = await dataSource.manager.query('SELECT NOW() as now');
t.ok(now.getTime(), 'should have valid returned date object');
await close();
});
27 changes: 27 additions & 0 deletions examples/typeorm/mysql2/connect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import t from 'tap';
import {connect} from './connect';

t.test('mysql typeorm ts', async t => {
const {dataSource, close} = await connect({
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME,
username: process.env.MYSQL_IAM_USER,
database: process.env.MYSQL_DB,
});
const [{now}] = await dataSource.manager.query('SELECT NOW() as now');
t.ok(now.getTime(), 'should have valid returned date object');
await close();
});
40 changes: 40 additions & 0 deletions examples/typeorm/mysql2/connect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {Connector} from '@google-cloud/cloud-sql-connector';
import {DataSource} from 'typeorm';

export async function connect({instanceConnectionName, username, database}) {
const connector = new Connector();
const clientOpts = await connector.getOptions({
instanceConnectionName,
ipType: 'PUBLIC',
authType: 'IAM',
});
const dataSource = new DataSource({
type: 'mysql',
username,
database,
extra: clientOpts,
});
await dataSource.initialize();

return {
dataSource,
async close() {
await dataSource.destroy();
connector.close();
},
};
}
Loading