diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000000..e013c4bebb --- /dev/null +++ b/.jshintignore @@ -0,0 +1,5 @@ +appengine/kraken/public/components/** +appengine/sails/config/** +appengine/sails/tasks/** +appengine/sails/assets/** +node_modules \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index bb21749e75..c716d9e2f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,4 @@ install: #Use '-q' to disable interactive prompts script: - - jshint --exclude-path=.gitignore . + - jshint --exclude-path=.jshintignore . diff --git a/README.md b/README.md index b4ef96a8ea..48b8598498 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,38 @@ -## Google Cloud Platform NodeJS Samples +# Google Cloud Platform NodeJS Samples -This repository holds the samples used in the nodejs documentation on [cloud.google.com](https://cloud.google.com). +This repository holds the samples used in the nodejs documentation on [cloud.google.com/nodejs](https://cloud.google.com/nodejs). [![Build Status](https://travis-ci.org/GoogleCloudPlatform/nodejs-docs-samples.svg)](https://travis-ci.org/GoogleCloudPlatform/nodejs-docs-samples) -See our other [Google Cloud Platform github -repos](https://github.com/GoogleCloudPlatform) for sample applications and -scaffolding for other frameworks and use cases. +## Google App Engine + +This is a collection of samples and instructions to run common nodejs frameworks and applications on [Google App Engine](http://cloud.google.com/nodejs). + +### Frameworks + +- [Express](appengine/express/) +- [Hapi](appengine/hapi/) +- [Loopback](appengine/loopback/) +- [Sails](appengine/sails/) +- [Koa](appengine/koa/) +- [Kraken](appengine/kraken/) +- [Restify](appengine/restify/) +- [Geddy](appengine/geddy/) + +### Services + +- [Redis](appengine/redis/) + +### Tools + +- [Grunt](appengine/grunt/) + +### More information + +- [Getting started with nodejs on Google Cloud](http://cloud.google.com/nodejs/) +- See our other [Google Cloud Platform github repos](https://github.com/GoogleCloudPlatform) for sample applications and scaffolding for other frameworks and use cases. +- [Using the `gcloud` npm module](https://googlecloudplatform.github.io/gcloud-node/#/) +- [Logging to Google Cloud with Winston](https://github.com/GoogleCloudPlatform/winston-gae) ## Contributing changes diff --git a/appengine/README.md b/appengine/README.md new file mode 100644 index 0000000000..10a0953ea9 --- /dev/null +++ b/appengine/README.md @@ -0,0 +1,29 @@ +# nodejs -> Google App Engine + +This is a collection of samples and instructions to run common nodejs frameworks and applications on [Google App Engine](http://cloud.google.com/nodejs). + +## Frameworks + +- [Express](express/) +- [Hapi](hapi/) +- [Loopback](/loopback) +- [Sails](sails/) +- [Koa](koa/) +- [Kraken](kraken/) +- [Restify](restify/) +- [Geddy](geddy/) + +## Services + +- [Redis](redis/) + +## Tools + +- [Grunt](grunt/) + +## More info + +- [Getting started with nodejs on Google Cloud](http://cloud.google.com/nodejs/) +- [Using the `gcloud` npm module](https://googlecloudplatform.github.io/gcloud-node/#/) +- [Logging to Google Cloud with Winston](https://github.com/GoogleCloudPlatform/winston-gae) + \ No newline at end of file diff --git a/appengine/express/README.md b/appengine/express/README.md new file mode 100644 index 0000000000..46f9dc53da --- /dev/null +++ b/appengine/express/README.md @@ -0,0 +1,25 @@ +# Express -> Google App Engine + +This is a simple guide to running [expressjs](http://expressjs.com/) on Google App Engine. + +1. [Create a new Express app](http://expressjs.com/starter/generator.html) + +2. Create an `app.yaml` in the root of your application with the following contents: + +```yaml +runtime: nodejs +vm: true +env_variables: + PORT: 8080 +``` + +3. Deploy your app. For convenience, you can use an npm script to run the command. Modify your `package.json` to include: + +```js +"scripts": { + "start": "node ./bin/www", + "deploy": "gcloud preview app deploy app.yaml --set-default --project [project id]" +} +``` + +At the terminal you can now run `npm run deploy` to deploy your application. diff --git a/appengine/express/app.js b/appengine/express/app.js new file mode 100644 index 0000000000..f0b53aa705 --- /dev/null +++ b/appengine/express/app.js @@ -0,0 +1,72 @@ +// Copyright 2015, Google, Inc. +// 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'; + +var express = require('express'); +var path = require('path'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var routes = require('./routes/index'); +var users = require('./routes/users'); + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); + +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', routes); +app.use('/users', users); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + + +module.exports = app; diff --git a/appengine/express/app.yaml b/appengine/express/app.yaml new file mode 100644 index 0000000000..00668a6347 --- /dev/null +++ b/appengine/express/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2015, Google, Inc. +# 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. + +runtime: nodejs +api_version: 1 +vm: true +env_variables: + PORT: 8080 \ No newline at end of file diff --git a/appengine/express/bin/www b/appengine/express/bin/www new file mode 100755 index 0000000000..29bd16240e --- /dev/null +++ b/appengine/express/bin/www @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +'use strict'; + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('express:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/appengine/express/package.json b/appengine/express/package.json new file mode 100644 index 0000000000..806153c5f9 --- /dev/null +++ b/appengine/express/package.json @@ -0,0 +1,18 @@ +{ + "name": "express", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www", + "deploy": "gcloud preview app deploy app.yaml --set-default --project express-demo" + }, + "dependencies": { + "body-parser": "~1.12.4", + "cookie-parser": "~1.3.5", + "debug": "~2.2.0", + "express": "~4.12.4", + "jade": "~1.9.2", + "morgan": "~1.5.3", + "serve-favicon": "~2.2.1" + } +} \ No newline at end of file diff --git a/appengine/express/public/stylesheets/style.css b/appengine/express/public/stylesheets/style.css new file mode 100644 index 0000000000..3f27236c04 --- /dev/null +++ b/appengine/express/public/stylesheets/style.css @@ -0,0 +1,21 @@ +/** Copyright 2015, Google, Inc. + * 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. + */ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} \ No newline at end of file diff --git a/appengine/express/routes/index.js b/appengine/express/routes/index.js new file mode 100644 index 0000000000..7b8cb0b8e6 --- /dev/null +++ b/appengine/express/routes/index.js @@ -0,0 +1,24 @@ +// Copyright 2015, Google, Inc. +// 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'; + +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res) { + res.render('index', { title: 'Express |2|' }); +}); + +module.exports = router; diff --git a/appengine/express/routes/users.js b/appengine/express/routes/users.js new file mode 100644 index 0000000000..ceb2144cad --- /dev/null +++ b/appengine/express/routes/users.js @@ -0,0 +1,24 @@ +// Copyright 2015, Google, Inc. +// 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'; + +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res) { + res.send('respond with a resource'); +}); + +module.exports = router; diff --git a/appengine/express/views/error.jade b/appengine/express/views/error.jade new file mode 100644 index 0000000000..b9dd8f8eb8 --- /dev/null +++ b/appengine/express/views/error.jade @@ -0,0 +1,19 @@ +// Copyright 2015, Google, Inc. +// 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. + +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/appengine/express/views/index.jade b/appengine/express/views/index.jade new file mode 100644 index 0000000000..0f4bfc7b7b --- /dev/null +++ b/appengine/express/views/index.jade @@ -0,0 +1,18 @@ +// Copyright 2015, Google, Inc. +// 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. + +extends layout + +block content + h1= title + p Welcome to #{title} diff --git a/appengine/express/views/layout.jade b/appengine/express/views/layout.jade new file mode 100644 index 0000000000..08c319bfe3 --- /dev/null +++ b/appengine/express/views/layout.jade @@ -0,0 +1,20 @@ +// Copyright 2015, Google, Inc. +// 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. + +doctype html +html + head + title= title + link(rel='stylesheet', href='/stylesheets/style.css') + body + block content \ No newline at end of file diff --git a/appengine/geddy/.gitignore b/appengine/geddy/.gitignore new file mode 100644 index 0000000000..28aaf8d70e --- /dev/null +++ b/appengine/geddy/.gitignore @@ -0,0 +1,10 @@ +*.swp +*.swo +dist +node_modules +*.DS_Store +log/ +npm-debug.log +config/secrets.json +public/js/core/models.js +public/js/core/helpers.js diff --git a/appengine/geddy/.jshintrc b/appengine/geddy/.jshintrc new file mode 100644 index 0000000000..2320058aac --- /dev/null +++ b/appengine/geddy/.jshintrc @@ -0,0 +1,6 @@ +{ + "node": true, + "globals": { + "geddy": true + } +} \ No newline at end of file diff --git a/appengine/geddy/Jakefile b/appengine/geddy/Jakefile new file mode 100644 index 0000000000..97a84a6f12 --- /dev/null +++ b/appengine/geddy/Jakefile @@ -0,0 +1,6 @@ + +var t = new jake.TestTask('geddy', function () { + this.testFiles.include('test/*.js'); + this.testFiles.include('test/**/*.js'); +}); + diff --git a/appengine/geddy/README.md b/appengine/geddy/README.md new file mode 100644 index 0000000000..c3d4cb1774 --- /dev/null +++ b/appengine/geddy/README.md @@ -0,0 +1,37 @@ +# Geddy -> Google App Engine + +This is a simple guide to running [geddy](http://geddyjs.org/) on Google App Engine. + +1. [Create a new geddy app](http://geddyjs.org/tutorial). + +2. Create an `app.yaml` in the root of your application with the following contents: + +```yaml +runtime: nodejs +vm: true +api_version: 1 +env_variables: + PORT: 8080 +``` + +3. Create a `server.js` that contains the following code: + +```js +var geddy = require('geddy'); + +geddy.start({ + port: process.env.PORT || '3000' +}); +``` + +4. Run `npm install --save geddy` + +5. Deploy! For convenience, you can modify your `package.json` to use an npm script for deployment: + +```js +"scripts": { + "deploy": "gcloud preview app deploy app.yaml --set-default --project [project id]" +} +``` + +At the terminal you can now run `npm run deploy` to deploy your application. diff --git a/appengine/geddy/app.yaml b/appengine/geddy/app.yaml new file mode 100644 index 0000000000..6f48107af0 --- /dev/null +++ b/appengine/geddy/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2015, Google, Inc. +# 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. + +runtime: nodejs +vm: true +api_version: 1 +env_variables: + PORT: 8080 \ No newline at end of file diff --git a/appengine/geddy/app/controllers/application.js b/appengine/geddy/app/controllers/application.js new file mode 100644 index 0000000000..73ba9f958d --- /dev/null +++ b/appengine/geddy/app/controllers/application.js @@ -0,0 +1,24 @@ +/* + * Geddy JavaScript Web development framework + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) + * + * 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'; + +var Application = function () { +}; + +exports.Application = Application; diff --git a/appengine/geddy/app/controllers/main.js b/appengine/geddy/app/controllers/main.js new file mode 100644 index 0000000000..922390ac09 --- /dev/null +++ b/appengine/geddy/app/controllers/main.js @@ -0,0 +1,30 @@ +/* + * Geddy JavaScript Web development framework + * Copyright 2112 Matthew Eernisse (mde@fleegix.org) + * + * 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'; + +var Main = function () { + this.index = function (req, resp, params) { + this.respond({params: params}, { + format: 'html', + template: 'app/views/main/index' + }); + }; +}; + +exports.Main = Main; diff --git a/appengine/geddy/app/views/errors/default.html.ejs b/appengine/geddy/app/views/errors/default.html.ejs new file mode 100644 index 0000000000..ea529f4b79 --- /dev/null +++ b/appengine/geddy/app/views/errors/default.html.ejs @@ -0,0 +1,23 @@ +<% +// Geddy JavaScript Web development framework +// Copyright 2112 Matthew Eernisse (mde@fleegix.org) +// +// 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. +%> +
<%= stack %>
+<% } else if (typeof message != 'undefined') { %>
+<%= message %>
+<% } %>
+
diff --git a/appengine/geddy/app/views/errors/not_found.html.ejs b/appengine/geddy/app/views/errors/not_found.html.ejs
new file mode 100644
index 0000000000..a1057d564b
--- /dev/null
+++ b/appengine/geddy/app/views/errors/not_found.html.ejs
@@ -0,0 +1,21 @@
+<%
+// Geddy JavaScript Web development framework
+// Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+//
+// 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.
+%>
+