├── .babelrc ├── client ├── vue.shims.d.ts ├── hero.ts ├── main.ts ├── index.html ├── hero.service.js ├── hero.service.ts ├── App.vue └── components │ ├── HeroDetail.vue │ └── HeroList.vue ├── Scrapbook-1.mongo ├── .dockerignore ├── .env.example ├── docker-compose.yml ├── index.html ├── server ├── www │ └── index.html ├── hero.model.js ├── routes.js ├── mongo.js └── hero.service.js ├── docker-compose.debug.yml ├── tsconfig.json ├── CHANGELOG.md ├── index.js ├── Dockerfile ├── scripts.azcli ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .vscode └── launch.json ├── LICENSE.md ├── package.json ├── .gitignore ├── README.md ├── webpack.config.js └── CONTRIBUTING.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }] 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /client/vue.shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.vue" { 2 | import Vue from "vue"; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /Scrapbook-1.mongo: -------------------------------------------------------------------------------- 1 | db.heroes.find() 2 | db.heroes.insertOne({ 3 | id: 98, 4 | name: 'Rocket', 5 | saying: 'ha ha ha' 6 | }) 7 | -------------------------------------------------------------------------------- /client/hero.ts: -------------------------------------------------------------------------------- 1 | export class Hero { 2 | constructor(public id: number, public name: string, public saying: string) {} 3 | } 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile* 4 | docker-compose* 5 | .dockerignore 6 | .git 7 | .gitignore 8 | README.md 9 | LICENSE 10 | .vscode -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | SERVER_PORT=3001 2 | PUBLICWEB=./server/www 3 | COSMOSDB_ACCOUNT=your_cosmos_account 4 | COSMOSDB_DB=your_cosmos_db 5 | COSMOSDB_KEY=your_cosmos_key 6 | COSMOSDB_PORT=10255 7 | -------------------------------------------------------------------------------- /client/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | 4 | new Vue({ 5 | el: '#app', 6 | template: '', 7 | components: { 8 | App 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | vue-cosmosdb: 5 | image: vue-cosmosdb 6 | build: . 7 | environment: 8 | NODE_ENV: production 9 | ports: 10 | - 3001:3001 -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Heroes 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue Heroes 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /server/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue.js Heroes 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docker-compose.debug.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | services: 4 | vue-cosmosdb: 5 | image: vue-cosmosdb 6 | build: . 7 | env_file: 8 | - .env 9 | ports: 10 | - 3001:3001 11 | - 9229:9229 12 | command: node --inspect=0.0.0.0:9229 index.js -------------------------------------------------------------------------------- /server/hero.model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const Schema = mongoose.Schema; 4 | 5 | const heroSchema = new Schema( 6 | { 7 | id: { type: Number, required: true, unique: true }, 8 | name: String, 9 | saying: String 10 | }, 11 | { 12 | collection: 'heroes', 13 | read: 'nearest' 14 | } 15 | ); 16 | 17 | const Hero = mongoose.model('Hero', heroSchema); 18 | 19 | module.exports = Hero; 20 | -------------------------------------------------------------------------------- /client/hero.service.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const api = 'api'; 4 | 5 | export default { 6 | deleteHero(hero) { 7 | return axios.delete(`${api}/hero/${hero.id}`); 8 | }, 9 | getHeroes() { 10 | return axios.get(`${api}/heroes`); 11 | }, 12 | addHero(hero) { 13 | return axios.post(`${api}/hero/`, { hero }); 14 | }, 15 | updateHero(hero) { 16 | return axios.put(`${api}/hero/${hero.id}`, { hero }); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./built/", 4 | "sourceMap": true, 5 | "strict": false, 6 | "noImplicitReturns": true, 7 | "noImplicitAny": true, 8 | "module": "es2015", 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "moduleResolution": "node", 12 | "target": "es5", 13 | "lib": [ 14 | "es2016", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "./client/**/*" 20 | ] 21 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## vue-cosmosdb Changelog 2 | 3 | 4 | 5 | # 1.1.0 (2017-12-02) 6 | 7 | _Breaking Changes_ 8 | 9 | * Added `.env` file in the root 10 | * Added `dotenv` to read the `.env` file when running locally (without docker) 11 | * Removed `./src/server/environment` folder and its contents (replaced with `.env`) 12 | * docker-compose "debug" now uses the `.env` file 13 | * docker-compose for prod and cloud hosting will require ENV vars to be set in the cloud 14 | * `.env` is gitignored and not copied in the `Dockerfile` build process 15 | -------------------------------------------------------------------------------- /server/routes.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | const heroService = require('./hero.service'); 5 | 6 | router.get('/heroes', (req, res) => { 7 | heroService.getHeroes(req, res); 8 | }); 9 | 10 | router.post('/hero', (req, res) => { 11 | heroService.postHero(req, res); 12 | }); 13 | 14 | router.put('/hero/:id', (req, res) => { 15 | heroService.putHero(req, res); 16 | }); 17 | 18 | router.delete('/hero/:id', (req, res) => { 19 | heroService.deleteHero(req, res); 20 | }); 21 | 22 | module.exports = router; 23 | -------------------------------------------------------------------------------- /client/hero.service.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { Hero } from './hero'; 3 | 4 | const api = 'api'; 5 | 6 | class HeroService { 7 | deleteHero(hero: Hero) { 8 | return axios.delete(`${api}/hero/${hero.id}`); 9 | } 10 | getHeroes() { 11 | return axios.get(`${api}/heroes`); 12 | } 13 | addHero(hero: Hero) { 14 | return axios.post(`${api}/hero/`, { hero }); 15 | } 16 | updateHero(hero: Hero) { 17 | return axios.put(`${api}/hero/${hero.id}`, { hero }); 18 | } 19 | } 20 | 21 | // Export a singleton instance in the global namespace 22 | export const heroService = new HeroService(); 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const routes = require('./server/routes'); 4 | 5 | const publicWeb = process.env.PUBLICWEB; 6 | const app = express(); 7 | app.use(bodyParser.json()); 8 | app.use(bodyParser.urlencoded({ extended: false })); 9 | 10 | app.use(express.static(publicWeb)); 11 | console.log(`serving ${publicWeb}`); 12 | app.use('/api', routes); 13 | app.get('*', (req, res) => { 14 | res.sendFile(`index.html`, { root: publicWeb }); 15 | }); 16 | 17 | const port = process.env.SERVER_PORT; 18 | app.listen(port, () => console.log(`API running on http://localhost:${port}`)); 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Client App 2 | FROM node:8.9-alpine as client-app 3 | LABEL authors="John Papa" 4 | WORKDIR /usr/src/app 5 | COPY ["package.json", "npm-shrinkwrap.json*", "./"] 6 | RUN npm install --silent 7 | COPY . . 8 | RUN npm run build 9 | 10 | # Node server 11 | FROM node:8.9-alpine as node-server 12 | WORKDIR /usr/src/app 13 | COPY ["package.json", "npm-shrinkwrap.json*", "./"] 14 | RUN npm install --production --silent && mv node_modules ../ 15 | COPY . . 16 | 17 | # Final image 18 | FROM node:8.9-alpine 19 | WORKDIR /usr/src/app 20 | COPY --from=node-server /usr/src /usr/src 21 | COPY --from=client-app /usr/src/app/server/www ./server/www 22 | EXPOSE 3001 23 | CMD ["node", "index.js"] 24 | -------------------------------------------------------------------------------- /scripts.azcli: -------------------------------------------------------------------------------- 1 | # We can run azure cli commands with auto-complete features 2 | az 3 | 4 | # we can run regular bash commands 5 | ls 6 | 7 | # build the image and run the docker container for prod 8 | docker-compose -f docker-compose.debug.yml up -d --build 9 | # Use the docker compose command form the CMD palette 10 | 11 | # open the browser to see the running app 12 | open http://localhost:3001 13 | 14 | # tag and push it from the extension 15 | # tag it 16 | docker tag vue-cosmosdb papacr.azurecr.io/johnpapa/vue-cosmosdb:latest 17 | # log into the container registry 18 | az acr login --name papacr 19 | # push it to the container registry 20 | docker push papacr.azurecr.io/johnpapa/vue-cosmosdb 21 | # docker login papacr.azurecr.io -u papacr -p 22 | -------------------------------------------------------------------------------- /server/mongo.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | /** 3 | * Set to Node.js native promises 4 | * Per http://mongoosejs.com/docs/promises.html 5 | */ 6 | mongoose.Promise = global.Promise; 7 | 8 | // Cosmos DB Connection String 9 | // eslint-disable-next-line max-len 10 | const mongoUri = `mongodb://${process.env.COSMOSDB_ACCOUNT}:${process.env.COSMOSDB_KEY}@${ 11 | process.env.COSMOSDB_ACCOUNT 12 | }.documents.azure.com:${process.env.COSMOSDB_PORT}/${process.env.COSMOSDB_DB}?ssl=true`; 13 | // &replicaSet=globaldb`; 14 | 15 | // Local MongoDB Connection String 16 | // const mongoUri = `mongodb://localhost:27017/connect-heroes`; 17 | 18 | function connect() { 19 | mongoose.set('debug', true); 20 | return mongoose.connect(mongoUri, { useMongoClient: true }); 21 | } 22 | 23 | module.exports = { 24 | connect, 25 | mongoose 26 | }; 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "attach", 10 | "name": "Attach to Node", 11 | "port": 9229 12 | }, 13 | { 14 | "type": "node", 15 | "request": "attach", 16 | "name": "Docker: Attach to Node", 17 | "port": 9229, 18 | "address": "localhost", 19 | "localRoot": "${workspaceFolder}", 20 | "remoteRoot": "/usr/src/app", 21 | "protocol": "inspector" 22 | }, 23 | { 24 | "type": "node", 25 | "request": "launch", 26 | "name": "Debug my vue app", 27 | "runtimeExecutable": "npm", 28 | "runtimeArgs": ["run-script", "debug"], 29 | "port": 9229 30 | }, 31 | { 32 | "type": "node", 33 | "request": "launch", 34 | "name": "Launch Program", 35 | "program": "${workspaceFolder}/index.js" 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cosmosdb", 3 | "version": "1.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev-proxy": "cross-env NODE_ENV=development webpack-dev-server --open --hot", 8 | "build-dev": "webpack --progress --hide-modules", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", 10 | "debug": "concurrently \"node -r dotenv/config --inspect index.js\" \"npm run dev-proxy\"", 11 | "start": "concurrently \"node -r dotenv/config index.js\" \"npm run dev-proxy\"", 12 | "docker-up": "docker-compose up -d --build", 13 | "docker-up-debug": "docker-compose -f docker-compose.debug.yml up -d --build" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "dependencies": { 19 | "axios": "^0.17.0", 20 | "body-parser": "^1.18.2", 21 | "dotenv": "^4.0.0", 22 | "express": "^4.16.2", 23 | "mongoose": "^4.13.0", 24 | "vue": "^2.3.4", 25 | "vue-class-component": "^6.1.0", 26 | "vue-property-decorator": "^6.0.0" 27 | }, 28 | "devDependencies": { 29 | "babel-core": "^6.26.0", 30 | "babel-loader": "^7.1.2", 31 | "babel-preset-env": "^1.6.0", 32 | "concurrently": "^3.5.0", 33 | "cross-env": "^5.0.5", 34 | "css-loader": "^0.28.7", 35 | "file-loader": "^1.1.4", 36 | "node-sass": "^4.5.3", 37 | "sass-loader": "^6.0.6", 38 | "ts-loader": "^3.1.1", 39 | "typescript": "^2.6.1", 40 | "vue-loader": "^13.5.0", 41 | "vue-template-compiler": "^2.3.4", 42 | "webpack": "^3.8.1", 43 | "webpack-dev-server": "^2.9.4" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /client/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # See http://help.github.com/ignore-files/ for more about ignoring files. 61 | 62 | # ignore server configuration 63 | **/env/development.js 64 | docker-compose.local.yml 65 | #*.azcli 66 | 67 | # compiled output 68 | /dist 69 | /tmp 70 | /out-tsc 71 | /server/www 72 | !/server/index.html 73 | 74 | # IDEs and editors 75 | /.idea 76 | .project 77 | .classpath 78 | .c9/ 79 | *.launch 80 | .settings/ 81 | *.sublime-workspace 82 | 83 | # IDE - VSCode 84 | .vscode/* 85 | !.vscode/settings.json 86 | !.vscode/tasks.json 87 | !.vscode/launch.json 88 | !.vscode/extensions.json 89 | 90 | # misc 91 | /.sass-cache 92 | /connect.lock 93 | /coverage 94 | /libpeerconnection.log 95 | npm-debug.log 96 | testem.log 97 | /typings 98 | 99 | # e2e 100 | /e2e/*.js 101 | /e2e/*.map 102 | 103 | # System Files 104 | .DS_Store 105 | Thumbs.db 106 | 107 | #.vscode 108 | -------------------------------------------------------------------------------- /server/hero.service.js: -------------------------------------------------------------------------------- 1 | const Hero = require('./hero.model'); 2 | const ReadPreference = require('mongodb').ReadPreference; 3 | 4 | require('./mongo').connect(); 5 | 6 | function getHeroes(req, res) { 7 | const docquery = Hero.find({}).read(ReadPreference.NEAREST); 8 | docquery 9 | .exec() 10 | .then(heroes => res.status(200).json(heroes)) 11 | .catch(error => res.status(500).send(error)); 12 | } 13 | 14 | function postHero(req, res) { 15 | const originalHero = { 16 | id: req.body.hero.id, 17 | name: req.body.hero.name, 18 | saying: req.body.hero.saying 19 | }; 20 | const hero = new Hero(originalHero); 21 | hero.save(error => { 22 | if (checkServerError(res, error)) return; 23 | res.status(201).json(hero); 24 | console.log('Hero created successfully!'); 25 | }); 26 | } 27 | 28 | function putHero(req, res) { 29 | const updatedHero = { 30 | id: parseInt(req.params.id, 10), 31 | name: req.body.hero.name, 32 | saying: req.body.hero.saying 33 | }; 34 | 35 | Hero.findOneAndUpdate( 36 | { id: updatedHero.id }, 37 | { $set: updatedHero }, 38 | { upsert: true, new: true }, 39 | (error, doc) => { 40 | if (checkServerError(res, error)) return; 41 | res.status(200).json(doc); 42 | console.log('Hero updated successfully!'); 43 | } 44 | ); 45 | } 46 | 47 | function deleteHero(req, res) { 48 | const id = parseInt(req.params.id, 10); 49 | Hero.findOneAndRemove({ id: id }) 50 | .then(hero => { 51 | if (!checkFound(res, hero)) return; 52 | res.status(200).json(hero); 53 | console.log('Hero deleted successfully!'); 54 | }) 55 | .catch(error => { 56 | if (checkServerError(res, error)) return; 57 | }); 58 | } 59 | 60 | function checkServerError(res, error) { 61 | if (error) { 62 | res.status(500).send(error); 63 | return error; 64 | } 65 | } 66 | 67 | function checkFound(res, hero) { 68 | if (!hero) { 69 | res.status(404).send('Hero not found.'); 70 | return; 71 | } 72 | return hero; 73 | } 74 | 75 | module.exports = { 76 | getHeroes, 77 | postHero, 78 | putHero, 79 | deleteHero 80 | }; 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | languages: 3 | - javascript 4 | - nodejs 5 | page_type: sample 6 | products: 7 | - azure 8 | - azure-cosmos-db 9 | description: "A Cosmos DB, Express.js, Vue, and Node.js app." 10 | --- 11 | 12 | # vue-cosmosdb 13 | 14 | A Cosmos DB, Express.js, Vue, and Node.js app 15 | 16 | > Please see the [`connect2017`](https://github.com/Azure-Samples/vue-cosmosdb/tree/connect2017?WT.mc_id=connect-c9-jopapa) branch to see the sample use in the Connect 2017 video (link coming soon) 17 | 18 | ## Features 19 | 20 | This project framework provides the following features: 21 | 22 | * Vue.js 23 | * Node.js 24 | * Express 25 | * Mongoose API 26 | * Connecting to MongoDB or CosmosDB 27 | * Building, Debugging, Deploying with Docker 28 | 29 | ## Getting Started 30 | 31 | ### Prerequisites 32 | 33 | Node.js with npm 34 | 35 | ### Installation 36 | 37 | ``` bash 38 | git clone https://github.com/Azure-Samples/vue-cosmosdb.git 39 | cd vue-cosmosdb 40 | npm install 41 | ``` 42 | 43 | ### Database settings 44 | 45 | * Configure Cosmos DB server settings 46 | 47 | Rename the `.env.example.js` file to `.env` in the root folder and update it with your Cosmos DB settings. Replace the accountName, databaseName, key, and port with your specific configuration. 48 | 49 | ```javascript 50 | SERVER_PORT=3001 51 | PUBLICWEB=./server/www 52 | COSMOSDB_ACCOUNT=your_cosmos_account 53 | COSMOSDB_DB=your_cosmos_db 54 | COSMOSDB_KEY=your_cosmos_key 55 | COSMOSDB_PORT=10255 56 | ``` 57 | 58 | ### Quickstart 59 | 60 | This will build the app and run the dev server for Vue and WebPack. The Node express server will launch and WebPack will proxy the calls from the browser to the API in express. It will also prepare it for local debugging. 61 | 62 | ``` bash 63 | # build for production with minification 64 | npm run build 65 | 66 | # serve on http://localhost:8080 67 | # and run the api on http://localhost:3001 68 | npm run debug 69 | ``` 70 | 71 | ### Local Prod Build 72 | 73 | This will build the app and launch via the Node.js express server. 74 | 75 | ```bash 76 | # build for production with minification 77 | npm run build 78 | 79 | # run the node server 80 | npm start 81 | ``` 82 | 83 | ### Docker 84 | 85 | Build the image and run container. 86 | 87 | ``` bash 88 | npm run docker-up 89 | ``` 90 | 91 | Build the image and run container for local debugging. 92 | 93 | ``` bash 94 | npm run docker-up-debug 95 | ``` 96 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: './client/main.ts', 6 | output: { 7 | path: path.resolve(__dirname, './server/www'), 8 | publicPath: '/server/www/', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.vue$/, 15 | loader: 'vue-loader', 16 | options: { 17 | loaders: { 18 | // Since sass-loader (weirdly) has SCSS as its default parse mode, we map 19 | // the "scss" and "sass" values for the lang attribute to the right configs here. 20 | // other preprocessors should work out of the box, no loader config like this necessary. 21 | scss: 'vue-style-loader!css-loader!sass-loader', 22 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' 23 | } 24 | // other vue-loader options go here 25 | } 26 | }, 27 | { 28 | test: /\.js$/, 29 | loader: 'babel-loader', 30 | exclude: /node_modules/ 31 | }, 32 | { 33 | test: /\.tsx?$/, 34 | loader: 'ts-loader', 35 | exclude: /node_modules/, 36 | options: { 37 | appendTsSuffixTo: [/\.vue$/], 38 | } 39 | }, 40 | { 41 | test: /\.(png|jpg|gif|svg)$/, 42 | loader: 'file-loader', 43 | options: { 44 | name: '[name].[ext]?[hash]' 45 | } 46 | } 47 | ] 48 | }, 49 | resolve: { 50 | extensions: ['.ts', '.js', '.vue', '.json'], 51 | alias: { 52 | vue$: 'vue/dist/vue.esm.js' 53 | } 54 | }, 55 | devServer: { 56 | historyApiFallback: true, 57 | noInfo: true, 58 | overlay: true, 59 | proxy: { 60 | '/api': { 61 | target: 'http://localhost:3001', 62 | changeOrigin: true, 63 | secure: false 64 | } 65 | } 66 | }, 67 | performance: { 68 | hints: false 69 | }, 70 | devtool: '#eval-source-map' 71 | }; 72 | 73 | if (process.env.NODE_ENV === 'production') { 74 | module.exports.devtool = '#source-map'; 75 | // http://vue-loader.vuejs.org/en/workflow/production.html 76 | module.exports.plugins = (module.exports.plugins || []).concat([ 77 | new webpack.DefinePlugin({ 78 | 'process.env': { 79 | NODE_ENV: '"production"' 80 | } 81 | }), 82 | new webpack.optimize.UglifyJsPlugin({ 83 | sourceMap: true, 84 | compress: { 85 | warnings: false 86 | } 87 | }), 88 | new webpack.LoaderOptionsPlugin({ 89 | minimize: true 90 | }) 91 | ]); 92 | } 93 | -------------------------------------------------------------------------------- /client/components/HeroDetail.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 93 | 94 | 110 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 6 | 7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /client/components/HeroList.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 94 | 95 | 184 | --------------------------------------------------------------------------------