From 0e6b7d78685d2ff70f5de69a3f584256e83215c9 Mon Sep 17 00:00:00 2001 From: Ace Nassri Date: Fri, 24 Aug 2018 16:56:06 -0700 Subject: [PATCH 1/2] Initial commit of SQL samples --- functions/sql/index.js | 91 ++++++++++++++++++++++++++++++++ functions/sql/package.json | 47 +++++++++++++++++ functions/sql/test/index.test.js | 80 ++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 functions/sql/index.js create mode 100644 functions/sql/package.json create mode 100644 functions/sql/test/index.test.js diff --git a/functions/sql/index.js b/functions/sql/index.js new file mode 100644 index 0000000000..dff0b2d976 --- /dev/null +++ b/functions/sql/index.js @@ -0,0 +1,91 @@ +/** + * Copyright 2018, 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 + * + * http://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. + */ + +'use strict'; + +const process = require('process'); // Allow env variable mocking + +// [START functions_sql_mysql] +const mysql = require('mysql'); +// [END functions_sql_mysql] + +// [START functions_sql_postgres] +const pg = require('pg'); +// [END functions_sql_postgres] + +// [START functions_sql_mysql] +// [START functions_sql_postgres] + +/** + * TODO(developer): specify SQL connection details + */ +const connectionName = process.env.INSTANCE_CONNECTION_NAME || ''; +const dbUser = process.env.SQL_USER || ''; +const dbPassword = process.env.SQL_PASSWORD || ''; +const dbName = process.env.SQL_NAME || ''; + +// [END functions_sql_postgres] +// [END functions_sql_mysql] + +// [START functions_sql_mysql] +const mysqlConfig = { + connectionLimit: 1, + user: dbUser, + password: dbPassword, + database: dbName +}; +if (process.env.NODE_ENV === 'production') { + mysqlConfig.socketPath = `/cloudsql/${connectionName}`; +} + +const mysqlPool = mysql.createPool(mysqlConfig); + +exports.mysqlDemo = (req, res) => { + mysqlPool.query('SELECT NOW() AS now', (err, results) => { + if (err) { + console.error(err); + res.status(500).send(err); + } else { + res.send(JSON.stringify(results)); + } + }); +}; +// [END functions_sql_mysql] + +// [START functions_sql_postgres] +const pgConfig = { + max: 1, + user: dbUser, + password: dbPassword, + database: dbName +}; + +if (process.env.NODE_ENV === 'production') { + pgConfig.socketPath = `/cloudsql/${connectionName}`; +} + +const pgPool = new pg.Pool(pgConfig); + +exports.postgresDemo = (req, res) => { + pgPool.query('SELECT NOW() as now', (err, results) => { + if (err) { + console.error(err); + res.status(500).send(err); + } else { + res.send(JSON.stringify(results)); + } + }); +}; +// [END functions_sql_postgres] diff --git a/functions/sql/package.json b/functions/sql/package.json new file mode 100644 index 0000000000..2cad1b0dcb --- /dev/null +++ b/functions/sql/package.json @@ -0,0 +1,47 @@ +{ + "name": "nodejs-docs-samples-functions-sql", + "version": "0.0.1", + "private": true, + "license": "Apache-2.0", + "author": "Google Inc.", + "repository": { + "type": "git", + "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" + }, + "engines": { + "node": ">=4.3.2" + }, + "scripts": { + "start-proxy-mysql": "cloud_sql_proxy -instances=$INSTANCE_CONNECTION_NAME-mysql=tcp:3306 &", + "start-proxy-pg": "cloud_sql_proxy -instances=$INSTANCE_CONNECTION_NAME-pg=tcp:5432 &", + "start-proxy": "! pgrep cloud_sql_proxy > /dev/null && npm run start-proxy-pg && npm run start-proxy-mysql || exit 0", + "kill-proxy": "killall cloud_sql_proxy", + "lint": "repo-tools lint", + "pretest": "npm run lint", + "ava": "ava -T 20s --verbose test/*.test.js", + "test": "npm run start-proxy && npm run ava && npm run kill-proxy" + }, + "dependencies": { + "@google-cloud/nodejs-repo-tools": "^2.3.3", + "mysql": "^2.16.0", + "pg": "^7.4.3", + "proxyquire": "^2.1.0" + }, + "devDependencies": { + "ava": "0.25.0", + "semistandard": "^12.0.1", + "sinon": "4.4.2" + }, + "cloud-repo-tools": { + "requiresKeyFile": true, + "requiresProjectId": true, + "requiredEnvVars": [ + "MYSQL_USER", + "MYSQL_PASSWORD", + "MYSQL_DATABASE", + "POSTGRES_USER", + "POSTGRES_PASSWORD", + "POSTGRES_DATABASE" + ] + } +} diff --git a/functions/sql/test/index.test.js b/functions/sql/test/index.test.js new file mode 100644 index 0000000000..05de2625a9 --- /dev/null +++ b/functions/sql/test/index.test.js @@ -0,0 +1,80 @@ +/** + * Copyright 2018, 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 + * + * http://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. + */ + +'use strict'; + +const sinon = require(`sinon`); +const test = require(`ava`); +const proxyquire = require(`proxyquire`); + +const INSTANCE_PREFIX = `nodejs-docs-samples:us-central1:integration-tests-instance`; + +const getProgram = (env) => { + return proxyquire(`../`, { + process: { + env: env + } + }); +}; + +test(`should query MySQL`, async (t) => { + const program = getProgram({ + INSTANCE_CONNECTION_NAME: `${INSTANCE_PREFIX}-mysql`, + SQL_USER: process.env.MYSQL_USER, + SQL_PASSWORD: process.env.MYSQL_PASSWORD, + SQL_NAME: process.env.MYSQL_DATABASE + }); + + const resMock = { + status: sinon.stub().returnsThis(), + send: sinon.stub() + }; + + program.mysqlDemo(null, resMock); + + // Give the query time to complete + await new Promise(resolve => { setTimeout(resolve, 1500); }); + + t.false(resMock.status.called); + t.true(resMock.send.calledOnce); + + const response = resMock.send.firstCall.args[0]; + t.regex(response, /\d{4}-\d{1,2}-\d{1,2}/); +}); + +test(`should query Postgres`, async (t) => { + const program = getProgram({ + INSTANCE_CONNECTION_NAME: `${INSTANCE_PREFIX}-pg`, + SQL_USER: process.env.POSTGRES_USER, + SQL_PASSWORD: process.env.POSTGRES_PASSWORD, + SQL_NAME: process.env.POSTGRES_DATABASE + }); + + const resMock = { + status: sinon.stub().returnsThis(), + send: sinon.stub() + }; + + program.postgresDemo(null, resMock); + + // Give the query time to complete + await new Promise(resolve => { setTimeout(resolve, 1500); }); + + t.false(resMock.status.called); + t.true(resMock.send.calledOnce); + + const response = resMock.send.firstCall.args[0]; + t.regex(response, /\d{4}-\d{1,2}-\d{1,2}/); +}); From dc4e66c018081fd79ac9d872ca705b244aaa587d Mon Sep 17 00:00:00 2001 From: Ace Nassri Date: Mon, 27 Aug 2018 12:54:35 -0700 Subject: [PATCH 2/2] Move some deps to devDeps --- functions/sql/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/functions/sql/package.json b/functions/sql/package.json index 2cad1b0dcb..1f61865a8b 100644 --- a/functions/sql/package.json +++ b/functions/sql/package.json @@ -22,13 +22,13 @@ "test": "npm run start-proxy && npm run ava && npm run kill-proxy" }, "dependencies": { - "@google-cloud/nodejs-repo-tools": "^2.3.3", "mysql": "^2.16.0", - "pg": "^7.4.3", - "proxyquire": "^2.1.0" + "pg": "^7.4.3" }, "devDependencies": { + "@google-cloud/nodejs-repo-tools": "^2.3.3", "ava": "0.25.0", + "proxyquire": "^2.1.0", "semistandard": "^12.0.1", "sinon": "4.4.2" },