├── app
├── src
│ ├── assets
│ │ └── .gitkeep
│ ├── app
│ │ ├── home
│ │ │ ├── home.component.css
│ │ │ ├── home.component.html
│ │ │ ├── home.component.ts
│ │ │ └── home.component.spec.ts
│ │ ├── app.component.css
│ │ ├── appointment-list
│ │ │ ├── appointment-list.component.css
│ │ │ ├── appointment-list.component.spec.ts
│ │ │ ├── appointment-list.component.html
│ │ │ └── appointment-list.component.ts
│ │ ├── app.component.html
│ │ ├── Appointment.ts
│ │ ├── app.component.ts
│ │ ├── appointment
│ │ │ ├── appointment.component.css
│ │ │ ├── appointment.component.spec.ts
│ │ │ ├── appointment.component.html
│ │ │ └── appointment.component.ts
│ │ ├── appointment.service.spec.ts
│ │ ├── app-routing.module.ts
│ │ ├── appointment.service.ts
│ │ ├── app.component.spec.ts
│ │ └── app.module.ts
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── styles.css
│ ├── main.ts
│ ├── index.html
│ ├── test.ts
│ └── polyfills.ts
├── e2e
│ ├── tsconfig.json
│ ├── src
│ │ ├── app.po.ts
│ │ └── app.e2e-spec.ts
│ └── protractor.conf.js
├── tsconfig.app.json
├── .editorconfig
├── tsconfig.spec.json
├── browserslist
├── tsconfig.json
├── .gitignore
├── README.md
├── karma.conf.js
├── package.json
├── tslint.json
└── angular.json
├── api
├── .gitignore
├── views
│ ├── index.jade
│ ├── error.jade
│ └── layout.jade
├── config.js
├── public
│ └── stylesheets
│ │ └── style.css
├── routes
│ ├── users.js
│ └── index.js
├── package.json
├── app.js
├── bin
│ └── www
└── package-lock.json
├── .editorconfig
└── .gitignore
/app/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/app/src/app/home/home.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | .container {
2 | width: 90%;
3 | margin: 50px auto 0 auto;
4 | }
--------------------------------------------------------------------------------
/app/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/app/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codebubb/appointment-booking/HEAD/app/src/favicon.ico
--------------------------------------------------------------------------------
/api/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= title
5 | p Welcome to #{title}
6 |
--------------------------------------------------------------------------------
/app/src/app/appointment-list/appointment-list.component.css:
--------------------------------------------------------------------------------
1 | table {
2 | margin-top: 50px;
3 | width: 100%;
4 | }
--------------------------------------------------------------------------------
/api/views/error.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= message
5 | h2= error.status
6 | pre #{error.stack}
7 |
--------------------------------------------------------------------------------
/app/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Appointment Bookings
3 |
4 |
--------------------------------------------------------------------------------
/api/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dbHost: 'localhost',
3 | dbName: 'appointment-app',
4 | dbCollection: 'appointments',
5 | };
6 |
--------------------------------------------------------------------------------
/app/src/app/Appointment.ts:
--------------------------------------------------------------------------------
1 | export interface Appointment {
2 | _id: string;
3 | appointmentDate: string;
4 | name: string;
5 | email: string;
6 | }
7 |
--------------------------------------------------------------------------------
/api/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 50px;
3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
4 | }
5 |
6 | a {
7 | color: #00B7FF;
8 | }
9 |
--------------------------------------------------------------------------------
/api/views/layout.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | title= title
5 | link(rel='stylesheet', href='/stylesheets/style.css')
6 | body
7 | block content
8 |
--------------------------------------------------------------------------------
/app/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | html, body { height: 100%; }
4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
5 |
--------------------------------------------------------------------------------
/api/routes/users.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 |
4 | /* GET users listing. */
5 | router.get('/', function(req, res, next) {
6 | res.send('respond with a resource');
7 | });
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/app/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | templateUrl: './app.component.html',
6 | styleUrls: ['./app.component.css']
7 | })
8 | export class AppComponent {
9 | title = 'appointments';
10 | }
11 |
--------------------------------------------------------------------------------
/app/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/app",
5 | "types": []
6 | },
7 | "include": [
8 | "src/**/*.ts"
9 | ],
10 | "exclude": [
11 | "src/test.ts",
12 | "src/**/*.spec.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/app/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText() {
9 | return element(by.css('app-root h1')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/app/src/app/appointment/appointment.component.css:
--------------------------------------------------------------------------------
1 | .form-container {
2 | margin-top: 50px;
3 | max-width: 350px;
4 | }
5 |
6 | form {
7 | display: flex;
8 | flex-direction: column;
9 | }
10 |
11 | .error {
12 | background-color: #d84f4f;
13 | padding: 10px;
14 | }
15 |
16 | .success {
17 | background-color: #73cc73;
18 | padding: 10px;
19 | }
--------------------------------------------------------------------------------
/app/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-home',
5 | templateUrl: './home.component.html',
6 | styleUrls: ['./home.component.css']
7 | })
8 | export class HomeComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node ./bin/www"
7 | },
8 | "dependencies": {
9 | "cookie-parser": "~1.4.4",
10 | "cors": "^2.8.5",
11 | "debug": "~2.6.9",
12 | "express": "~4.16.1",
13 | "http-errors": "~1.6.3",
14 | "jade": "~1.11.0",
15 | "mongodb": "^3.3.0",
16 | "morgan": "~1.9.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/app/appointment.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { AppointmentService } from './appointment.service';
4 |
5 | describe('AppointmentService', () => {
6 | beforeEach(() => TestBed.configureTestingModule({}));
7 |
8 | it('should be created', () => {
9 | const service: AppointmentService = TestBed.get(AppointmentService);
10 | expect(service).toBeTruthy();
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/app/src/main.ts:
--------------------------------------------------------------------------------
1 | import 'hammerjs';
2 | import { enableProdMode } from '@angular/core';
3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
4 |
5 | import { AppModule } from './app/app.module';
6 | import { environment } from './environments/environment';
7 |
8 | if (environment.production) {
9 | enableProdMode();
10 | }
11 |
12 | platformBrowserDynamic().bootstrapModule(AppModule)
13 | .catch(err => console.error(err));
14 |
--------------------------------------------------------------------------------
/app/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "typeRoots": [
15 | "node_modules/@types"
16 | ],
17 | "lib": [
18 | "es2018",
19 | "dom"
20 | ]
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Appointments
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 | import { HomeComponent } from './home/home.component';
4 | import { AppointmentListComponent } from './appointment-list/appointment-list.component';
5 |
6 | const routes: Routes = [
7 | {
8 | path: '',
9 | component: HomeComponent,
10 | },
11 | {
12 | path: 'appointment-list',
13 | component: AppointmentListComponent,
14 | }
15 | ];
16 |
17 | @NgModule({
18 | imports: [RouterModule.forRoot(routes)],
19 | exports: [RouterModule]
20 | })
21 | export class AppRoutingModule { }
22 |
--------------------------------------------------------------------------------
/app/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/app/src/app/home/home.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HomeComponent } from './home.component';
4 |
5 | describe('HomeComponent', () => {
6 | let component: HomeComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ HomeComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(HomeComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/app/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('Welcome to appointments!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | } as logging.Entry));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/app/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false,
7 | API_URL: 'http://localhost:3000',
8 | };
9 |
10 | /*
11 | * For easier debugging in development mode, you can import the following file
12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
13 | *
14 | * This import should be commented out in production mode because it will have a negative impact
15 | * on performance if an error is thrown.
16 | */
17 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
18 |
--------------------------------------------------------------------------------
/app/src/app/appointment/appointment.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { AppointmentComponent } from './appointment.component';
4 |
5 | describe('AppointmentComponent', () => {
6 | let component: AppointmentComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ AppointmentComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(AppointmentComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events.json
15 | speed-measure-plugin.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .project
20 | .classpath
21 | .c9/
22 | *.launch
23 | .settings/
24 | *.sublime-workspace
25 |
26 | # IDE - VSCode
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 | .history/*
33 |
34 | # misc
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events.json
15 | speed-measure-plugin.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .project
20 | .classpath
21 | .c9/
22 | *.launch
23 | .settings/
24 | *.sublime-workspace
25 |
26 | # IDE - VSCode
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 | .history/*
33 |
34 | # misc
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
--------------------------------------------------------------------------------
/app/src/app/appointment-list/appointment-list.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { AppointmentListComponent } from './appointment-list.component';
4 |
5 | describe('AppointmentListComponent', () => {
6 | let component: AppointmentListComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ AppointmentListComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(AppointmentListComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/app/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: [
13 | './src/**/*.e2e-spec.ts'
14 | ],
15 | capabilities: {
16 | 'browserName': 'chrome'
17 | },
18 | directConnect: true,
19 | baseUrl: 'http://localhost:4200/',
20 | framework: 'jasmine',
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000,
24 | print: function() {}
25 | },
26 | onPrepare() {
27 | require('ts-node').register({
28 | project: require('path').join(__dirname, './tsconfig.json')
29 | });
30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
31 | }
32 | };
--------------------------------------------------------------------------------
/app/src/app/appointment/appointment.component.html:
--------------------------------------------------------------------------------
1 | {{ successMsg }}
2 | {{ errorMsg }}
3 |
4 |
5 |
19 |
--------------------------------------------------------------------------------
/app/src/app/appointment.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 | import { Appointment } from './Appointment';
5 | import { environment } from 'src/environments/environment';
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class AppointmentService {
11 |
12 | private BASE_URL = environment.API_URL;
13 |
14 | constructor(private http: HttpClient) { }
15 |
16 | getAppointments(): Observable {
17 | return this.http.get(`${this.BASE_URL}/appointments`);
18 | }
19 |
20 | createAppointment(appointmentDate: string, name: string, email: string): Observable {
21 | return this.http.post(`${this.BASE_URL}/appointments`, { appointmentDate, name, email });
22 | }
23 |
24 | cancelAppointment(id: string): Observable {
25 | return this.http.delete(`${this.BASE_URL}/appointments/${id}`);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/api/routes/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | const ObjectID = require('mongodb').ObjectID;
4 |
5 | router.get('/appointments', (req, res, next) => {
6 | req.collection.find({})
7 | .toArray()
8 | .then(results => res.json(results))
9 | .catch(error => res.send(error));
10 | });
11 |
12 | router.post('/appointments', (req, res, next) => {
13 | const { appointmentDate, name, email } = req.body;
14 | if (!appointmentDate || !name || !email) {
15 | return res.status(400).json({
16 | message: 'Appointment Date, Name and email are required',
17 | });
18 | }
19 |
20 | const payload = { appointmentDate, name, email };
21 | req.collection.insertOne(payload)
22 | .then(result => res.json(result.ops[0]))
23 | .catch(error => res.send(error));
24 | });
25 |
26 | router.delete('/appointments/:id', (req, res, next) => {
27 | const { id } = req.params;
28 | const _id = ObjectID(id);
29 | req.collection.deleteOne({ _id })
30 | .then(result => res.json(result))
31 | .catch(error => res.send(error));
32 | });
33 |
34 | module.exports = router;
35 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | # Appointments
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.6.
4 |
5 | ## Development server
6 |
7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Code scaffolding
10 |
11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12 |
13 | ## Build
14 |
15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
16 |
17 | ## Running unit tests
18 |
19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20 |
21 | ## Running end-to-end tests
22 |
23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
28 |
--------------------------------------------------------------------------------
/app/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/appointments'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/app/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(async(() => {
7 | TestBed.configureTestingModule({
8 | imports: [
9 | RouterTestingModule
10 | ],
11 | declarations: [
12 | AppComponent
13 | ],
14 | }).compileComponents();
15 | }));
16 |
17 | it('should create the app', () => {
18 | const fixture = TestBed.createComponent(AppComponent);
19 | const app = fixture.debugElement.componentInstance;
20 | expect(app).toBeTruthy();
21 | });
22 |
23 | it(`should have as title 'appointments'`, () => {
24 | const fixture = TestBed.createComponent(AppComponent);
25 | const app = fixture.debugElement.componentInstance;
26 | expect(app.title).toEqual('appointments');
27 | });
28 |
29 | it('should render title in a h1 tag', () => {
30 | const fixture = TestBed.createComponent(AppComponent);
31 | fixture.detectChanges();
32 | const compiled = fixture.debugElement.nativeElement;
33 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to appointments!');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/app/src/app/appointment/appointment.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { AppointmentService } from '../appointment.service';
3 | import { Appointment } from '../Appointment';
4 |
5 | @Component({
6 | selector: 'app-appointment',
7 | templateUrl: './appointment.component.html',
8 | styleUrls: ['./appointment.component.css']
9 | })
10 | export class AppointmentComponent implements OnInit {
11 |
12 | public successMsg: string;
13 | public errorMsg: string;
14 | appointmentDate: string;
15 | name: string;
16 | email: string;
17 |
18 | constructor(private appointmentService: AppointmentService) { }
19 |
20 | ngOnInit() {
21 | }
22 |
23 | createAppointment() {
24 | this.successMsg = '';
25 | this.errorMsg = '';
26 | this.appointmentService.createAppointment(this.appointmentDate, this.name, this.email)
27 | .subscribe((createdAppointment: Appointment) => {
28 | this.appointmentDate = '';
29 | this.name = '';
30 | this.email = '';
31 | const appointmentDate = new Date(createdAppointment.appointmentDate).toDateString();
32 | this.successMsg = `Appointment Booked Successfully for ${appointmentDate}`;
33 | },
34 | (error: ErrorEvent) => {
35 | this.errorMsg = error.error.message;
36 | });
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/app/appointment-list/appointment-list.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ successMsg }}
3 | {{ errorMsg }}
4 |
5 |
6 |
7 |
8 | | Appointment Date |
9 | {{ appointment.appointmentDate | date:'dd/MM/yyyy' }} |
10 |
11 |
12 | Name |
13 | {{ appointment.name }} |
14 |
15 |
16 | Email |
17 | {{ appointment.email }} |
18 |
19 |
20 | Cancel |
21 | |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
7 | import { HomeComponent } from './home/home.component';
8 | import { AppointmentComponent } from './appointment/appointment.component';
9 | import { AppointmentListComponent } from './appointment-list/appointment-list.component';
10 | import { HttpClientModule } from '@angular/common/http';
11 | import { FormsModule } from '@angular/forms';
12 | import {
13 | MatTableModule,
14 | MatProgressSpinnerModule,
15 | MatFormFieldModule,
16 | MatInputModule,
17 | MatButtonModule,
18 | MatDatepickerModule,
19 | MatNativeDateModule,
20 | MatToolbarModule,
21 | } from '@angular/material';
22 |
23 | @NgModule({
24 | declarations: [
25 | AppComponent,
26 | HomeComponent,
27 | AppointmentComponent,
28 | AppointmentListComponent
29 | ],
30 | imports: [
31 | BrowserModule,
32 | AppRoutingModule,
33 | BrowserAnimationsModule,
34 | HttpClientModule,
35 | FormsModule,
36 | MatTableModule,
37 | MatProgressSpinnerModule,
38 | MatFormFieldModule,
39 | MatInputModule,
40 | MatButtonModule,
41 | MatDatepickerModule,
42 | MatNativeDateModule,
43 | MatToolbarModule,
44 | ],
45 | providers: [],
46 | bootstrap: [AppComponent]
47 | })
48 | export class AppModule { }
49 |
--------------------------------------------------------------------------------
/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appointments",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e"
11 | },
12 | "private": true,
13 | "dependencies": {
14 | "@angular/animations": "~8.0.3",
15 | "@angular/cdk": "~8.1.3",
16 | "@angular/common": "~8.0.3",
17 | "@angular/compiler": "~8.0.3",
18 | "@angular/core": "~8.0.3",
19 | "@angular/forms": "~8.0.3",
20 | "@angular/material": "^8.1.3",
21 | "@angular/platform-browser": "~8.0.3",
22 | "@angular/platform-browser-dynamic": "~8.0.3",
23 | "@angular/router": "~8.0.3",
24 | "hammerjs": "^2.0.8",
25 | "rxjs": "~6.4.0",
26 | "tslib": "^1.9.0",
27 | "zone.js": "~0.9.1"
28 | },
29 | "devDependencies": {
30 | "@angular-devkit/build-angular": "~0.800.6",
31 | "@angular/cli": "~8.0.6",
32 | "@angular/compiler-cli": "~8.0.3",
33 | "@angular/language-service": "~8.0.3",
34 | "@types/node": "~8.9.4",
35 | "@types/jasmine": "~3.3.8",
36 | "@types/jasminewd2": "~2.0.3",
37 | "codelyzer": "^5.0.0",
38 | "jasmine-core": "~3.4.0",
39 | "jasmine-spec-reporter": "~4.2.1",
40 | "karma": "~4.1.0",
41 | "karma-chrome-launcher": "~2.2.0",
42 | "karma-coverage-istanbul-reporter": "~2.0.1",
43 | "karma-jasmine": "~2.0.1",
44 | "karma-jasmine-html-reporter": "^1.4.0",
45 | "protractor": "~5.4.0",
46 | "ts-node": "~7.0.0",
47 | "tslint": "~5.15.0",
48 | "typescript": "~3.4.3"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/app/appointment-list/appointment-list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { AppointmentService } from '../appointment.service';
3 | import { Appointment } from '../Appointment';
4 | import { mergeMap } from 'rxjs/operators';
5 |
6 | @Component({
7 | selector: 'app-appointment-list',
8 | templateUrl: './appointment-list.component.html',
9 | styleUrls: ['./appointment-list.component.css']
10 | })
11 | export class AppointmentListComponent implements OnInit {
12 |
13 | public loading = true;
14 | public errorMsg: string;
15 | public successMsg: string;
16 | public appointments: Appointment[];
17 | public columns = ['appointmentDate', 'name', 'email', 'cancel'];
18 |
19 | constructor(private appointmentService: AppointmentService) { }
20 |
21 | ngOnInit() {
22 | this.appointmentService.getAppointments()
23 | .subscribe((appointments: Appointment[]) => {
24 | this.appointments = appointments;
25 | this.loading = false;
26 | },
27 | (error: ErrorEvent) => {
28 | this.errorMsg = error.error.message;
29 | this.loading = false;
30 | });
31 | }
32 |
33 | cancelAppointment(id: string) {
34 | this.appointmentService.cancelAppointment(id)
35 | .pipe(
36 | mergeMap(() => this.appointmentService.getAppointments())
37 | )
38 | .subscribe((appointments: Appointment[]) => {
39 | this.appointments = appointments;
40 | this.successMsg = 'Successfully cancelled appointment';
41 | },
42 | (error: ErrorEvent) => {
43 | this.errorMsg = error.error.message;
44 | });
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/api/app.js:
--------------------------------------------------------------------------------
1 | var createError = require('http-errors');
2 | var express = require('express');
3 | var path = require('path');
4 | var cookieParser = require('cookie-parser');
5 | var logger = require('morgan');
6 |
7 | const config = require('./config');
8 | const MongoClient = require('mongodb').MongoClient;
9 | const cors = require('cors');
10 |
11 | var indexRouter = require('./routes/index');
12 | var usersRouter = require('./routes/users');
13 |
14 | var app = express();
15 |
16 | MongoClient.connect(`mongodb://${config.dbHost}`, { useNewUrlParser: true, useUnifiedTopology: true })
17 | .then(client => {
18 | const db = client.db(config.dbName);
19 | const collection = db.collection(config.dbCollection);
20 | app.locals[config.dbCollection] = collection;
21 | })
22 | .catch(error => {
23 | console.log(error);
24 | });
25 |
26 | // view engine setup
27 | app.set('views', path.join(__dirname, 'views'));
28 | app.set('view engine', 'jade');
29 |
30 | app.use(logger('dev'));
31 | app.use(express.json());
32 | app.use(express.urlencoded({ extended: false }));
33 | app.use(cookieParser());
34 | app.use(express.static(path.join(__dirname, 'public')));
35 | app.use(cors());
36 |
37 | app.use((req, res, next) => {
38 | const collection = req.app.locals[config.dbCollection];
39 | req.collection = collection;
40 | next();
41 | });
42 |
43 | app.use('/', indexRouter);
44 | app.use('/users', usersRouter);
45 |
46 | // catch 404 and forward to error handler
47 | app.use(function(req, res, next) {
48 | next(createError(404));
49 | });
50 |
51 | // error handler
52 | app.use(function(err, req, res, next) {
53 | // set locals, only providing error in development
54 | res.locals.message = err.message;
55 | res.locals.error = req.app.get('env') === 'development' ? err : {};
56 |
57 | // render the error page
58 | res.status(err.status || 500);
59 | res.render('error');
60 | });
61 |
62 | module.exports = app;
63 |
--------------------------------------------------------------------------------
/api/bin/www:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var app = require('../app');
8 | var debug = require('debug')('api:server');
9 | var http = require('http');
10 |
11 | /**
12 | * Get port from environment and store in Express.
13 | */
14 |
15 | var port = normalizePort(process.env.PORT || '3000');
16 | app.set('port', port);
17 |
18 | /**
19 | * Create HTTP server.
20 | */
21 |
22 | var server = http.createServer(app);
23 |
24 | /**
25 | * Listen on provided port, on all network interfaces.
26 | */
27 |
28 | server.listen(port);
29 | server.on('error', onError);
30 | server.on('listening', onListening);
31 |
32 | /**
33 | * Normalize a port into a number, string, or false.
34 | */
35 |
36 | function normalizePort(val) {
37 | var port = parseInt(val, 10);
38 |
39 | if (isNaN(port)) {
40 | // named pipe
41 | return val;
42 | }
43 |
44 | if (port >= 0) {
45 | // port number
46 | return port;
47 | }
48 |
49 | return false;
50 | }
51 |
52 | /**
53 | * Event listener for HTTP server "error" event.
54 | */
55 |
56 | function onError(error) {
57 | if (error.syscall !== 'listen') {
58 | throw error;
59 | }
60 |
61 | var bind = typeof port === 'string'
62 | ? 'Pipe ' + port
63 | : 'Port ' + port;
64 |
65 | // handle specific listen errors with friendly messages
66 | switch (error.code) {
67 | case 'EACCES':
68 | console.error(bind + ' requires elevated privileges');
69 | process.exit(1);
70 | break;
71 | case 'EADDRINUSE':
72 | console.error(bind + ' is already in use');
73 | process.exit(1);
74 | break;
75 | default:
76 | throw error;
77 | }
78 | }
79 |
80 | /**
81 | * Event listener for HTTP server "listening" event.
82 | */
83 |
84 | function onListening() {
85 | var addr = server.address();
86 | var bind = typeof addr === 'string'
87 | ? 'pipe ' + addr
88 | : 'port ' + addr.port;
89 | debug('Listening on ' + bind);
90 | }
91 |
--------------------------------------------------------------------------------
/app/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "array-type": false,
5 | "arrow-parens": false,
6 | "deprecation": {
7 | "severity": "warning"
8 | },
9 | "component-class-suffix": true,
10 | "contextual-lifecycle": true,
11 | "directive-class-suffix": true,
12 | "directive-selector": [
13 | true,
14 | "attribute",
15 | "app",
16 | "camelCase"
17 | ],
18 | "component-selector": [
19 | true,
20 | "element",
21 | "app",
22 | "kebab-case"
23 | ],
24 | "import-blacklist": [
25 | true,
26 | "rxjs/Rx"
27 | ],
28 | "interface-name": false,
29 | "max-classes-per-file": false,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-consecutive-blank-lines": false,
47 | "no-console": [
48 | true,
49 | "debug",
50 | "info",
51 | "time",
52 | "timeEnd",
53 | "trace"
54 | ],
55 | "no-empty": false,
56 | "no-inferrable-types": [
57 | true,
58 | "ignore-params"
59 | ],
60 | "no-non-null-assertion": true,
61 | "no-redundant-jsdoc": true,
62 | "no-switch-case-fall-through": true,
63 | "no-use-before-declare": true,
64 | "no-var-requires": false,
65 | "object-literal-key-quotes": [
66 | true,
67 | "as-needed"
68 | ],
69 | "object-literal-sort-keys": false,
70 | "ordered-imports": false,
71 | "quotemark": [
72 | true,
73 | "single"
74 | ],
75 | "trailing-comma": false,
76 | "no-conflicting-lifecycle": true,
77 | "no-host-metadata-property": true,
78 | "no-input-rename": true,
79 | "no-inputs-metadata-property": true,
80 | "no-output-native": true,
81 | "no-output-on-prefix": true,
82 | "no-output-rename": true,
83 | "no-outputs-metadata-property": true,
84 | "template-banana-in-box": true,
85 | "template-no-negated-async": true,
86 | "use-lifecycle-interface": true,
87 | "use-pipe-transform-interface": true
88 | },
89 | "rulesDirectory": [
90 | "codelyzer"
91 | ]
92 | }
--------------------------------------------------------------------------------
/app/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags.ts';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/app/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "appointments": {
7 | "projectType": "application",
8 | "schematics": {},
9 | "root": "",
10 | "sourceRoot": "src",
11 | "prefix": "app",
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/appointments",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": "src/polyfills.ts",
20 | "tsConfig": "tsconfig.app.json",
21 | "aot": false,
22 | "assets": [
23 | "src/favicon.ico",
24 | "src/assets"
25 | ],
26 | "styles": [
27 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
28 | "src/styles.css"
29 | ],
30 | "scripts": []
31 | },
32 | "configurations": {
33 | "production": {
34 | "fileReplacements": [
35 | {
36 | "replace": "src/environments/environment.ts",
37 | "with": "src/environments/environment.prod.ts"
38 | }
39 | ],
40 | "optimization": true,
41 | "outputHashing": "all",
42 | "sourceMap": false,
43 | "extractCss": true,
44 | "namedChunks": false,
45 | "aot": true,
46 | "extractLicenses": true,
47 | "vendorChunk": false,
48 | "buildOptimizer": true,
49 | "budgets": [
50 | {
51 | "type": "initial",
52 | "maximumWarning": "2mb",
53 | "maximumError": "5mb"
54 | }
55 | ]
56 | }
57 | }
58 | },
59 | "serve": {
60 | "builder": "@angular-devkit/build-angular:dev-server",
61 | "options": {
62 | "browserTarget": "appointments:build"
63 | },
64 | "configurations": {
65 | "production": {
66 | "browserTarget": "appointments:build:production"
67 | }
68 | }
69 | },
70 | "extract-i18n": {
71 | "builder": "@angular-devkit/build-angular:extract-i18n",
72 | "options": {
73 | "browserTarget": "appointments:build"
74 | }
75 | },
76 | "test": {
77 | "builder": "@angular-devkit/build-angular:karma",
78 | "options": {
79 | "main": "src/test.ts",
80 | "polyfills": "src/polyfills.ts",
81 | "tsConfig": "tsconfig.spec.json",
82 | "karmaConfig": "karma.conf.js",
83 | "assets": [
84 | "src/favicon.ico",
85 | "src/assets"
86 | ],
87 | "styles": [
88 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
89 | "src/styles.css"
90 | ],
91 | "scripts": []
92 | }
93 | },
94 | "lint": {
95 | "builder": "@angular-devkit/build-angular:tslint",
96 | "options": {
97 | "tsConfig": [
98 | "tsconfig.app.json",
99 | "tsconfig.spec.json",
100 | "e2e/tsconfig.json"
101 | ],
102 | "exclude": [
103 | "**/node_modules/**"
104 | ]
105 | }
106 | },
107 | "e2e": {
108 | "builder": "@angular-devkit/build-angular:protractor",
109 | "options": {
110 | "protractorConfig": "e2e/protractor.conf.js",
111 | "devServerTarget": "appointments:serve"
112 | },
113 | "configurations": {
114 | "production": {
115 | "devServerTarget": "appointments:serve:production"
116 | }
117 | }
118 | }
119 | }
120 | }
121 | },
122 | "defaultProject": "appointments"
123 | }
--------------------------------------------------------------------------------
/api/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "version": "0.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "accepts": {
8 | "version": "1.3.7",
9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
11 | "requires": {
12 | "mime-types": "~2.1.24",
13 | "negotiator": "0.6.2"
14 | }
15 | },
16 | "acorn": {
17 | "version": "2.7.0",
18 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
19 | "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc="
20 | },
21 | "acorn-globals": {
22 | "version": "1.0.9",
23 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
24 | "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=",
25 | "requires": {
26 | "acorn": "^2.1.0"
27 | }
28 | },
29 | "align-text": {
30 | "version": "0.1.4",
31 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
32 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
33 | "requires": {
34 | "kind-of": "^3.0.2",
35 | "longest": "^1.0.1",
36 | "repeat-string": "^1.5.2"
37 | }
38 | },
39 | "amdefine": {
40 | "version": "1.0.1",
41 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
42 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
43 | },
44 | "array-flatten": {
45 | "version": "1.1.1",
46 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
47 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
48 | },
49 | "asap": {
50 | "version": "1.0.0",
51 | "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz",
52 | "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0="
53 | },
54 | "basic-auth": {
55 | "version": "2.0.1",
56 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
57 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
58 | "requires": {
59 | "safe-buffer": "5.1.2"
60 | }
61 | },
62 | "body-parser": {
63 | "version": "1.18.3",
64 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
65 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
66 | "requires": {
67 | "bytes": "3.0.0",
68 | "content-type": "~1.0.4",
69 | "debug": "2.6.9",
70 | "depd": "~1.1.2",
71 | "http-errors": "~1.6.3",
72 | "iconv-lite": "0.4.23",
73 | "on-finished": "~2.3.0",
74 | "qs": "6.5.2",
75 | "raw-body": "2.3.3",
76 | "type-is": "~1.6.16"
77 | }
78 | },
79 | "bson": {
80 | "version": "1.1.1",
81 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz",
82 | "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg=="
83 | },
84 | "bytes": {
85 | "version": "3.0.0",
86 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
87 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
88 | },
89 | "camelcase": {
90 | "version": "1.2.1",
91 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
92 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
93 | },
94 | "center-align": {
95 | "version": "0.1.3",
96 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
97 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
98 | "requires": {
99 | "align-text": "^0.1.3",
100 | "lazy-cache": "^1.0.3"
101 | }
102 | },
103 | "character-parser": {
104 | "version": "1.2.1",
105 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz",
106 | "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY="
107 | },
108 | "clean-css": {
109 | "version": "3.4.28",
110 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
111 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
112 | "requires": {
113 | "commander": "2.8.x",
114 | "source-map": "0.4.x"
115 | },
116 | "dependencies": {
117 | "commander": {
118 | "version": "2.8.1",
119 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
120 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
121 | "requires": {
122 | "graceful-readlink": ">= 1.0.0"
123 | }
124 | }
125 | }
126 | },
127 | "cliui": {
128 | "version": "2.1.0",
129 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
130 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
131 | "requires": {
132 | "center-align": "^0.1.1",
133 | "right-align": "^0.1.1",
134 | "wordwrap": "0.0.2"
135 | },
136 | "dependencies": {
137 | "wordwrap": {
138 | "version": "0.0.2",
139 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
140 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
141 | }
142 | }
143 | },
144 | "commander": {
145 | "version": "2.6.0",
146 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
147 | "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0="
148 | },
149 | "constantinople": {
150 | "version": "3.0.2",
151 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz",
152 | "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE=",
153 | "requires": {
154 | "acorn": "^2.1.0"
155 | }
156 | },
157 | "content-disposition": {
158 | "version": "0.5.2",
159 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
160 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
161 | },
162 | "content-type": {
163 | "version": "1.0.4",
164 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
165 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
166 | },
167 | "cookie": {
168 | "version": "0.3.1",
169 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
170 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
171 | },
172 | "cookie-parser": {
173 | "version": "1.4.4",
174 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
175 | "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
176 | "requires": {
177 | "cookie": "0.3.1",
178 | "cookie-signature": "1.0.6"
179 | }
180 | },
181 | "cookie-signature": {
182 | "version": "1.0.6",
183 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
184 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
185 | },
186 | "cors": {
187 | "version": "2.8.5",
188 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
189 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
190 | "requires": {
191 | "object-assign": "^4",
192 | "vary": "^1"
193 | }
194 | },
195 | "css": {
196 | "version": "1.0.8",
197 | "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz",
198 | "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=",
199 | "requires": {
200 | "css-parse": "1.0.4",
201 | "css-stringify": "1.0.5"
202 | }
203 | },
204 | "css-parse": {
205 | "version": "1.0.4",
206 | "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz",
207 | "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90="
208 | },
209 | "css-stringify": {
210 | "version": "1.0.5",
211 | "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz",
212 | "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE="
213 | },
214 | "debug": {
215 | "version": "2.6.9",
216 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
217 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
218 | "requires": {
219 | "ms": "2.0.0"
220 | }
221 | },
222 | "decamelize": {
223 | "version": "1.2.0",
224 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
225 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
226 | },
227 | "depd": {
228 | "version": "1.1.2",
229 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
230 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
231 | },
232 | "destroy": {
233 | "version": "1.0.4",
234 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
235 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
236 | },
237 | "ee-first": {
238 | "version": "1.1.1",
239 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
240 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
241 | },
242 | "encodeurl": {
243 | "version": "1.0.2",
244 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
245 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
246 | },
247 | "escape-html": {
248 | "version": "1.0.3",
249 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
250 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
251 | },
252 | "etag": {
253 | "version": "1.8.1",
254 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
255 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
256 | },
257 | "express": {
258 | "version": "4.16.4",
259 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
260 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
261 | "requires": {
262 | "accepts": "~1.3.5",
263 | "array-flatten": "1.1.1",
264 | "body-parser": "1.18.3",
265 | "content-disposition": "0.5.2",
266 | "content-type": "~1.0.4",
267 | "cookie": "0.3.1",
268 | "cookie-signature": "1.0.6",
269 | "debug": "2.6.9",
270 | "depd": "~1.1.2",
271 | "encodeurl": "~1.0.2",
272 | "escape-html": "~1.0.3",
273 | "etag": "~1.8.1",
274 | "finalhandler": "1.1.1",
275 | "fresh": "0.5.2",
276 | "merge-descriptors": "1.0.1",
277 | "methods": "~1.1.2",
278 | "on-finished": "~2.3.0",
279 | "parseurl": "~1.3.2",
280 | "path-to-regexp": "0.1.7",
281 | "proxy-addr": "~2.0.4",
282 | "qs": "6.5.2",
283 | "range-parser": "~1.2.0",
284 | "safe-buffer": "5.1.2",
285 | "send": "0.16.2",
286 | "serve-static": "1.13.2",
287 | "setprototypeof": "1.1.0",
288 | "statuses": "~1.4.0",
289 | "type-is": "~1.6.16",
290 | "utils-merge": "1.0.1",
291 | "vary": "~1.1.2"
292 | }
293 | },
294 | "finalhandler": {
295 | "version": "1.1.1",
296 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
297 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
298 | "requires": {
299 | "debug": "2.6.9",
300 | "encodeurl": "~1.0.2",
301 | "escape-html": "~1.0.3",
302 | "on-finished": "~2.3.0",
303 | "parseurl": "~1.3.2",
304 | "statuses": "~1.4.0",
305 | "unpipe": "~1.0.0"
306 | }
307 | },
308 | "forwarded": {
309 | "version": "0.1.2",
310 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
311 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
312 | },
313 | "fresh": {
314 | "version": "0.5.2",
315 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
316 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
317 | },
318 | "graceful-readlink": {
319 | "version": "1.0.1",
320 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
321 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
322 | },
323 | "http-errors": {
324 | "version": "1.6.3",
325 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
326 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
327 | "requires": {
328 | "depd": "~1.1.2",
329 | "inherits": "2.0.3",
330 | "setprototypeof": "1.1.0",
331 | "statuses": ">= 1.4.0 < 2"
332 | }
333 | },
334 | "iconv-lite": {
335 | "version": "0.4.23",
336 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
337 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
338 | "requires": {
339 | "safer-buffer": ">= 2.1.2 < 3"
340 | }
341 | },
342 | "inherits": {
343 | "version": "2.0.3",
344 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
345 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
346 | },
347 | "ipaddr.js": {
348 | "version": "1.9.0",
349 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
350 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
351 | },
352 | "is-buffer": {
353 | "version": "1.1.6",
354 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
355 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
356 | },
357 | "is-promise": {
358 | "version": "2.1.0",
359 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
360 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
361 | },
362 | "jade": {
363 | "version": "1.11.0",
364 | "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz",
365 | "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0=",
366 | "requires": {
367 | "character-parser": "1.2.1",
368 | "clean-css": "^3.1.9",
369 | "commander": "~2.6.0",
370 | "constantinople": "~3.0.1",
371 | "jstransformer": "0.0.2",
372 | "mkdirp": "~0.5.0",
373 | "transformers": "2.1.0",
374 | "uglify-js": "^2.4.19",
375 | "void-elements": "~2.0.1",
376 | "with": "~4.0.0"
377 | }
378 | },
379 | "jstransformer": {
380 | "version": "0.0.2",
381 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz",
382 | "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs=",
383 | "requires": {
384 | "is-promise": "^2.0.0",
385 | "promise": "^6.0.1"
386 | }
387 | },
388 | "kind-of": {
389 | "version": "3.2.2",
390 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
391 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
392 | "requires": {
393 | "is-buffer": "^1.1.5"
394 | }
395 | },
396 | "lazy-cache": {
397 | "version": "1.0.4",
398 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
399 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
400 | },
401 | "longest": {
402 | "version": "1.0.1",
403 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
404 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
405 | },
406 | "media-typer": {
407 | "version": "0.3.0",
408 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
409 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
410 | },
411 | "merge-descriptors": {
412 | "version": "1.0.1",
413 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
414 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
415 | },
416 | "methods": {
417 | "version": "1.1.2",
418 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
419 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
420 | },
421 | "mime": {
422 | "version": "1.4.1",
423 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
424 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
425 | },
426 | "mime-db": {
427 | "version": "1.40.0",
428 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
429 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
430 | },
431 | "mime-types": {
432 | "version": "2.1.24",
433 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
434 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
435 | "requires": {
436 | "mime-db": "1.40.0"
437 | }
438 | },
439 | "minimist": {
440 | "version": "0.0.8",
441 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
442 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
443 | },
444 | "mkdirp": {
445 | "version": "0.5.1",
446 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
447 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
448 | "requires": {
449 | "minimist": "0.0.8"
450 | }
451 | },
452 | "mongodb": {
453 | "version": "3.3.0",
454 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.0.tgz",
455 | "integrity": "sha512-QYa8YEN5uiJyIFdnn1vmBtiSveyygmQghsaL/RDnHqUzjGvkYe0vRg6UikCKba06cg6El/Lu7qzOYnR3vMhwlA==",
456 | "requires": {
457 | "bson": "^1.1.1",
458 | "require_optional": "^1.0.1",
459 | "safe-buffer": "^5.1.2"
460 | }
461 | },
462 | "morgan": {
463 | "version": "1.9.1",
464 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
465 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
466 | "requires": {
467 | "basic-auth": "~2.0.0",
468 | "debug": "2.6.9",
469 | "depd": "~1.1.2",
470 | "on-finished": "~2.3.0",
471 | "on-headers": "~1.0.1"
472 | }
473 | },
474 | "ms": {
475 | "version": "2.0.0",
476 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
477 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
478 | },
479 | "negotiator": {
480 | "version": "0.6.2",
481 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
482 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
483 | },
484 | "object-assign": {
485 | "version": "4.1.1",
486 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
487 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
488 | },
489 | "on-finished": {
490 | "version": "2.3.0",
491 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
492 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
493 | "requires": {
494 | "ee-first": "1.1.1"
495 | }
496 | },
497 | "on-headers": {
498 | "version": "1.0.2",
499 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
500 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
501 | },
502 | "optimist": {
503 | "version": "0.3.7",
504 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
505 | "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
506 | "requires": {
507 | "wordwrap": "~0.0.2"
508 | }
509 | },
510 | "parseurl": {
511 | "version": "1.3.3",
512 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
513 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
514 | },
515 | "path-to-regexp": {
516 | "version": "0.1.7",
517 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
518 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
519 | },
520 | "promise": {
521 | "version": "6.1.0",
522 | "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
523 | "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=",
524 | "requires": {
525 | "asap": "~1.0.0"
526 | }
527 | },
528 | "proxy-addr": {
529 | "version": "2.0.5",
530 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
531 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
532 | "requires": {
533 | "forwarded": "~0.1.2",
534 | "ipaddr.js": "1.9.0"
535 | }
536 | },
537 | "qs": {
538 | "version": "6.5.2",
539 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
540 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
541 | },
542 | "range-parser": {
543 | "version": "1.2.1",
544 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
545 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
546 | },
547 | "raw-body": {
548 | "version": "2.3.3",
549 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
550 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
551 | "requires": {
552 | "bytes": "3.0.0",
553 | "http-errors": "1.6.3",
554 | "iconv-lite": "0.4.23",
555 | "unpipe": "1.0.0"
556 | }
557 | },
558 | "repeat-string": {
559 | "version": "1.6.1",
560 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
561 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
562 | },
563 | "require_optional": {
564 | "version": "1.0.1",
565 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
566 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
567 | "requires": {
568 | "resolve-from": "^2.0.0",
569 | "semver": "^5.1.0"
570 | }
571 | },
572 | "resolve-from": {
573 | "version": "2.0.0",
574 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
575 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
576 | },
577 | "right-align": {
578 | "version": "0.1.3",
579 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
580 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
581 | "requires": {
582 | "align-text": "^0.1.1"
583 | }
584 | },
585 | "safe-buffer": {
586 | "version": "5.1.2",
587 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
588 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
589 | },
590 | "safer-buffer": {
591 | "version": "2.1.2",
592 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
593 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
594 | },
595 | "semver": {
596 | "version": "5.7.1",
597 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
598 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
599 | },
600 | "send": {
601 | "version": "0.16.2",
602 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
603 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
604 | "requires": {
605 | "debug": "2.6.9",
606 | "depd": "~1.1.2",
607 | "destroy": "~1.0.4",
608 | "encodeurl": "~1.0.2",
609 | "escape-html": "~1.0.3",
610 | "etag": "~1.8.1",
611 | "fresh": "0.5.2",
612 | "http-errors": "~1.6.2",
613 | "mime": "1.4.1",
614 | "ms": "2.0.0",
615 | "on-finished": "~2.3.0",
616 | "range-parser": "~1.2.0",
617 | "statuses": "~1.4.0"
618 | }
619 | },
620 | "serve-static": {
621 | "version": "1.13.2",
622 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
623 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
624 | "requires": {
625 | "encodeurl": "~1.0.2",
626 | "escape-html": "~1.0.3",
627 | "parseurl": "~1.3.2",
628 | "send": "0.16.2"
629 | }
630 | },
631 | "setprototypeof": {
632 | "version": "1.1.0",
633 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
634 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
635 | },
636 | "source-map": {
637 | "version": "0.4.4",
638 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
639 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
640 | "requires": {
641 | "amdefine": ">=0.0.4"
642 | }
643 | },
644 | "statuses": {
645 | "version": "1.4.0",
646 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
647 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
648 | },
649 | "transformers": {
650 | "version": "2.1.0",
651 | "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz",
652 | "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=",
653 | "requires": {
654 | "css": "~1.0.8",
655 | "promise": "~2.0",
656 | "uglify-js": "~2.2.5"
657 | },
658 | "dependencies": {
659 | "is-promise": {
660 | "version": "1.0.1",
661 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz",
662 | "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU="
663 | },
664 | "promise": {
665 | "version": "2.0.0",
666 | "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz",
667 | "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=",
668 | "requires": {
669 | "is-promise": "~1"
670 | }
671 | },
672 | "source-map": {
673 | "version": "0.1.43",
674 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
675 | "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
676 | "requires": {
677 | "amdefine": ">=0.0.4"
678 | }
679 | },
680 | "uglify-js": {
681 | "version": "2.2.5",
682 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz",
683 | "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=",
684 | "requires": {
685 | "optimist": "~0.3.5",
686 | "source-map": "~0.1.7"
687 | }
688 | }
689 | }
690 | },
691 | "type-is": {
692 | "version": "1.6.18",
693 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
694 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
695 | "requires": {
696 | "media-typer": "0.3.0",
697 | "mime-types": "~2.1.24"
698 | }
699 | },
700 | "uglify-js": {
701 | "version": "2.8.29",
702 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
703 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
704 | "requires": {
705 | "source-map": "~0.5.1",
706 | "uglify-to-browserify": "~1.0.0",
707 | "yargs": "~3.10.0"
708 | },
709 | "dependencies": {
710 | "source-map": {
711 | "version": "0.5.7",
712 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
713 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
714 | }
715 | }
716 | },
717 | "uglify-to-browserify": {
718 | "version": "1.0.2",
719 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
720 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
721 | "optional": true
722 | },
723 | "unpipe": {
724 | "version": "1.0.0",
725 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
726 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
727 | },
728 | "utils-merge": {
729 | "version": "1.0.1",
730 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
731 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
732 | },
733 | "vary": {
734 | "version": "1.1.2",
735 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
736 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
737 | },
738 | "void-elements": {
739 | "version": "2.0.1",
740 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
741 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
742 | },
743 | "window-size": {
744 | "version": "0.1.0",
745 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
746 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
747 | },
748 | "with": {
749 | "version": "4.0.3",
750 | "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz",
751 | "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=",
752 | "requires": {
753 | "acorn": "^1.0.1",
754 | "acorn-globals": "^1.0.3"
755 | },
756 | "dependencies": {
757 | "acorn": {
758 | "version": "1.2.2",
759 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
760 | "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ="
761 | }
762 | }
763 | },
764 | "wordwrap": {
765 | "version": "0.0.3",
766 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
767 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
768 | },
769 | "yargs": {
770 | "version": "3.10.0",
771 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
772 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
773 | "requires": {
774 | "camelcase": "^1.0.2",
775 | "cliui": "^2.1.0",
776 | "decamelize": "^1.0.0",
777 | "window-size": "0.1.0"
778 | }
779 | }
780 | }
781 | }
782 |
--------------------------------------------------------------------------------