;
+ let modalSpy;
+ let modalCtrlSpy;
+ beforeEach(async(() => {
+ modalSpy = jasmine.createSpyObj('Modal', ['present']);
+ modalCtrlSpy = jasmine.createSpyObj('ModalController', ['create']);
+ modalCtrlSpy.create.and.callFake(function () {
+ return modalSpy;
+ });
+
+
+ TestBed.configureTestingModule({
+ providers: [
+ {
+ provide: ModalController,
+ useValue: modalCtrlSpy
+ }
+ ],
+ declarations: [ AuthMenuButtonComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AuthMenuButtonComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-button.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-button.component.ts
new file mode 100644
index 0000000..432e97b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-button.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit } from '@angular/core';
+import { ModalController } from '@ionic/angular';
+import { AuthMenuUserComponent } from './auth-menu-user/auth-menu-user.component';
+
+import { AuthService } from '../services/auth.service';
+import { AuthLoginComponent } from '../auth-login/auth-login.component';
+import { AuthRegisterComponent } from '../auth-register/auth-register.component';
+
+@Component({
+ selector: 'app-auth-menu-button',
+ templateUrl: './auth-menu-button.component.html',
+ styleUrls: ['./auth-menu-button.component.scss'],
+})
+export class AuthMenuButtonComponent implements OnInit {
+
+ constructor(
+ public auth: AuthService,
+ public modalController: ModalController
+ ) {}
+
+ async presentmodal(ev: any) {
+ const modal = await this.modalController.create({
+ component: AuthMenuUserComponent,
+ });
+ return await modal.present();
+ }
+
+ async presentLogin(ev: any) {
+ const modal = await this.modalController.create({
+ component: AuthLoginComponent,
+ });
+ return await modal.present();
+ }
+
+ async presentRegister(ev: any) {
+ const modal = await this.modalController.create({
+ component: AuthRegisterComponent,
+ });
+ return await modal.present();
+ }
+
+ logout() {
+ this.auth.logout();
+ }
+
+ ngOnInit() {}
+
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.html
new file mode 100644
index 0000000..e0eac1a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.html
@@ -0,0 +1,5 @@
+Dismiss
+
+
+ auth-menu-user works!
+
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.spec.ts
new file mode 100644
index 0000000..8aca5f4
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.spec.ts
@@ -0,0 +1,49 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AuthMenuUserComponent } from './auth-menu-user.component';
+import { ModalController } from '@ionic/angular';
+
+describe('AuthMenuUserPage', () => {
+ let component: AuthMenuUserComponent;
+ let fixture: ComponentFixture;
+ let modalSpy;
+ let modalCtrlSpy;
+
+ beforeEach(async(() => {
+ modalSpy = jasmine.createSpyObj('Modal', ['dismiss']);
+ modalCtrlSpy = jasmine.createSpyObj('ModalController', ['create']);
+ modalCtrlSpy.create.and.callFake(function () {
+ return modalSpy;
+ });
+
+
+ TestBed.configureTestingModule({
+ providers: [
+ {
+ provide: ModalController,
+ useValue: modalCtrlSpy
+ }
+ ],
+ declarations: [ AuthMenuUserComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AuthMenuUserComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ // it('#dismiss() should hide the modal', () => {
+ // .........
+ // expect(modalSpy.dismiss).toHaveBeenCalled();
+ // .........
+ // });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.ts
new file mode 100644
index 0000000..2f602a7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-menu-button/auth-menu-user/auth-menu-user.component.ts
@@ -0,0 +1,18 @@
+import { Component, OnInit } from '@angular/core';
+import { ModalController } from '@ionic/angular';
+
+@Component({
+ selector: 'app-auth-menu-user',
+ templateUrl: './auth-menu-user.component.html',
+ styleUrls: ['./auth-menu-user.component.scss'],
+})
+export class AuthMenuUserComponent implements OnInit {
+
+ constructor(private modalCtrl: ModalController) { }
+
+ ngOnInit() {}
+
+ dismissModal() {
+ this.modalCtrl.dismiss();
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.html
new file mode 100644
index 0000000..66d58ca
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.html
@@ -0,0 +1,25 @@
+
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.spec.ts
new file mode 100644
index 0000000..e45a285
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.spec.ts
@@ -0,0 +1,29 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
+import { AuthRegisterComponent } from './auth-register.component';
+
+describe('AuthRegisterPage', () => {
+ let component: AuthRegisterComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [ ReactiveFormsModule ],
+ declarations: [ AuthRegisterComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AuthRegisterComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.ts
new file mode 100644
index 0000000..7b20c93
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth-register/auth-register.component.ts
@@ -0,0 +1,61 @@
+import { Component, OnInit } from '@angular/core';
+import { Validators, FormBuilder, FormGroup, FormControl } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { User } from '../models/user.model';
+import { ModalController } from '@ionic/angular';
+
+@Component({
+ selector: 'app-auth-register',
+ templateUrl: './auth-register.component.html',
+ styleUrls: ['./auth-register.component.scss'],
+})
+export class AuthRegisterComponent implements OnInit {
+
+ registerForm: FormGroup;
+ error: string;
+
+ constructor(
+ private formBuilder: FormBuilder,
+ private auth: AuthService,
+ private modal: ModalController
+ ) { }
+
+ ngOnInit() {
+ this.registerForm = this.formBuilder.group({
+ password_confirm: new FormControl('', Validators.required),
+ password: new FormControl('', Validators.required),
+ email: new FormControl('', Validators.compose([
+ Validators.required,
+ Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
+ ])),
+ name: new FormControl('', Validators.compose([
+ Validators.required,
+ Validators.pattern('^[a-zA-Z0-9_.+-]+$')
+ ]))
+ }, { validators: this.passwordsMatch });
+ }
+
+ onSubmit($event) {
+ $event.preventDefault();
+
+ if (!this.registerForm.valid) { return; }
+
+ const newuser: User = {
+ email: this.registerForm.controls.email.value,
+ name: this.registerForm.controls.name.value
+ };
+
+ this.auth.register(newuser, this.registerForm.controls.password.value)
+ .then((user) => {
+ this.modal.dismiss();
+ })
+ .catch((e) => {
+ this.error = e.statusText;
+ throw e;
+ });
+ }
+
+ passwordsMatch(group: FormGroup) {
+ return group.controls.password.value === group.controls.password_confirm.value ? null : { passwordsMisMatch: true };
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth.module.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth.module.ts
new file mode 100644
index 0000000..b26076b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/auth.module.ts
@@ -0,0 +1,31 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { IonicModule } from '@ionic/angular';
+import { RouterModule } from '@angular/router';
+
+import { AuthMenuButtonComponent } from './auth-menu-button/auth-menu-button.component';
+import { AuthLoginComponent } from './auth-login/auth-login.component';
+import { AuthRegisterComponent } from './auth-register/auth-register.component';
+import { AuthMenuUserComponent } from './auth-menu-button/auth-menu-user/auth-menu-user.component';
+
+import { ApiModule } from '../api/api.module';
+import { ApiService } from '../api/api.service';
+
+const entryComponents = [AuthMenuUserComponent, AuthMenuButtonComponent, AuthLoginComponent, AuthRegisterComponent];
+const components = [...entryComponents];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ IonicModule,
+ ReactiveFormsModule,
+ ApiModule
+ ],
+ entryComponents: entryComponents,
+ declarations: components,
+ exports: components,
+ providers: []
+})
+export class AuthModule {}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/models/user.model.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/models/user.model.ts
new file mode 100644
index 0000000..135078d
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/models/user.model.ts
@@ -0,0 +1,4 @@
+export interface User {
+ email: string;
+ name: string;
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.spec.ts
new file mode 100644
index 0000000..459c042
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.spec.ts
@@ -0,0 +1,15 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthGuardService } from './auth.guard.service';
+import { RouterTestingModule } from '@angular/router/testing';
+
+describe('AuthGuardService', () => {
+ beforeEach(() => TestBed.configureTestingModule({
+ imports: [ RouterTestingModule ]
+ }));
+
+ it('should be created', () => {
+ const service: AuthGuardService = TestBed.get(AuthGuardService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.ts
new file mode 100644
index 0000000..be88a97
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.guard.service.ts
@@ -0,0 +1,90 @@
+import { Injectable } from '@angular/core';
+import { Router, CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot, UrlTree } from '@angular/router';
+import { AuthService } from './auth.service';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthGuardService implements CanActivate {
+
+ constructor(
+ private auth: AuthService,
+ private router: Router
+ ) {}
+
+ canActivate(route: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot): boolean
+ | UrlTree
+ | Observable
+ | Promise {
+ if (!this.auth.currentUser$.value) {
+ this.router.navigateByUrl('/login');
+ }
+
+ return this.auth.currentUser$.value !== null;
+ }
+
+}
+
+// import { Injectable } from '@angular/core';
+// import { Router, CanActivate } from '@angular/router';
+// import { Events } from '@ionic/angular';
+
+// import { AmplifyService } from 'aws-amplify-angular';
+// import { CognitoUser } from 'amazon-cognito-identity-js';
+// import { AuthState } from 'aws-amplify-angular/dist/src/providers/auth.state';
+// import { BehaviorSubject } from 'rxjs';
+// import { Auth } from 'aws-amplify';
+
+// @Injectable({
+// providedIn: 'root'
+// })
+// export class AuthGuardService implements CanActivate {
+// authState: AuthState;
+// loggedIn = false;
+// loggedInChanged$: BehaviorSubject = new BehaviorSubject (this.loggedIn);
+// currentUser: CognitoUser;
+
+// constructor(
+// public router: Router,
+// public events: Events,
+// public amplify: AmplifyService
+// ) {
+// this.amplify.authStateChange$
+// .subscribe(async (authState) => {
+// if (authState) {
+// this.loggedIn = authState.state === 'signedIn';
+// this.loggedInChanged$.next(this.loggedIn);
+// this.authState = authState;
+// this.events.publish('data:AuthState', this.authState);
+
+
+// this.currentUser = await Auth.currentAuthenticatedUser();
+// }
+// });
+// }
+
+// retry() {
+// }
+
+// canActivate() {
+// if (!this.loggedIn) {
+// this.router.navigateByUrl('/signin');
+// }
+
+// return this.loggedIn;
+// }
+
+// signOut() {
+// return this.amplify.auth().signOut().then(() => {
+// window.location.href = '/#/signin';
+// // TODO maybe additional cleanup
+// });
+// }
+
+// init() {
+// return;
+// }
+// }
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.spec.ts
new file mode 100644
index 0000000..f3d964d
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: AuthService = TestBed.get(AuthService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.ts
new file mode 100644
index 0000000..7f8eaf3
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/auth/services/auth.service.ts
@@ -0,0 +1,59 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { User } from '../models/user.model';
+import { ApiService } from 'src/app/api/api.service';
+import { catchError, tap } from 'rxjs/operators';
+
+const JWT_LOCALSTORE_KEY = 'jwt';
+const USER_LOCALSTORE_KEY = 'user';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+ currentUser$: BehaviorSubject = new BehaviorSubject(null);
+ constructor( private api: ApiService ) {
+ this.initToken();
+ }
+
+ initToken() {
+ const token = localStorage.getItem(JWT_LOCALSTORE_KEY);
+ const user = JSON.parse(localStorage.getItem(USER_LOCALSTORE_KEY));
+ if (token && user) {
+ this.setTokenAndUser(token, user);
+ }
+ }
+
+ setTokenAndUser(token: string, user: User) {
+ localStorage.setItem(JWT_LOCALSTORE_KEY, token);
+ localStorage.setItem(USER_LOCALSTORE_KEY, JSON.stringify(user));
+ this.api.setAuthToken(token);
+ this.currentUser$.next(user);
+ }
+
+ async login(email: string, password: string): Promise {
+ return this.api.post('/users/auth/login',
+ {email: email, password: password})
+ .then((res) => {
+ this.setTokenAndUser(res.token, res.user);
+ return res;
+ })
+ .catch((e) => { throw e; });
+ // return user !== undefined;
+ }
+
+ logout(): boolean {
+ this.setTokenAndUser(null, null);
+ return true;
+ }
+
+ register(user: User, password: string): Promise {
+ return this.api.post('/users/auth/',
+ {email: user.email, password: password})
+ .then((res) => {
+ this.setTokenAndUser(res.token, res.user);
+ return res;
+ })
+ .catch((e) => { throw e; });
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.html
new file mode 100644
index 0000000..b614210
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.html
@@ -0,0 +1,10 @@
+
+
+
+
+ {{feedItem.caption}}
+
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.scss
new file mode 100644
index 0000000..8ec6d96
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.scss
@@ -0,0 +1,14 @@
+.photo-card{
+ max-width: 500px;
+ overflow: hidden;
+ background: var(--ion-color-primary-contrast);
+ margin: 30px 0px;
+ }
+
+.photo-card ion-img {
+ max-height: 532px;
+ overflow: hidden;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.spec.ts
new file mode 100644
index 0000000..73c6b59
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.spec.ts
@@ -0,0 +1,57 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FeedItemComponent } from './feed-item.component';
+import { feedItemMocks } from '../models/feed-item.model';
+import { FeedProviderService } from '../services/feed.provider.service';
+
+describe('FeedItemComponent', () => {
+ let component: FeedItemComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FeedItemComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FeedItemComponent);
+ component = fixture.componentInstance;
+ component.feedItem = feedItemMocks[0];
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should set the image url to the feedItem', () => {
+ const app = fixture.nativeElement;
+ const img = app.querySelectorAll('ion-img');
+ expect(img.length).toEqual(1);
+ expect(img[0].src).toEqual(feedItemMocks[0].url);
+ });
+
+ it('should display the caption', () => {
+ const app = fixture.nativeElement;
+ const paragraphs = app.querySelectorAll('p');
+ expect(([].slice.call(paragraphs)).map((x) => x.innerText)).toContain(feedItemMocks[0].caption);
+ });
+
+ // it('should open a modal when clicked', () => {
+ // de = fixture.debugElement.query(By.css('ion-buttons button'));
+ // de.triggerEventHandler('click', null);
+ // expect(navCtrl.push).toHaveBeenCalledWith(WishlistPage);
+ // });
+
+ // it('should open a modal when clicked', () => {
+ // let navCtrl = fixture.debugElement.injector.get(NavController);
+ // spyOn(navCtrl, 'push');
+ // de = fixture.debugElement.query(By.css('ion-buttons button'));
+ // de.triggerEventHandler('click', null);
+ // expect(navCtrl.push).toHaveBeenCalledWith(WishlistPage);
+ // });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.ts
new file mode 100644
index 0000000..64dd434
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-item/feed-item.component.ts
@@ -0,0 +1,17 @@
+import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
+import { FeedItem } from '../models/feed-item.model';
+
+@Component({
+ selector: 'app-feed-item',
+ templateUrl: './feed-item.component.html',
+ styleUrls: ['./feed-item.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class FeedItemComponent implements OnInit {
+ @Input() feedItem: FeedItem;
+
+ constructor() { }
+
+ ngOnInit() {}
+
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.html
new file mode 100644
index 0000000..6c10337
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.scss
new file mode 100644
index 0000000..f12b046
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.scss
@@ -0,0 +1,7 @@
+
+ .feed {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background: var(--ion-color-light-tint);
+ }
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.spec.ts
new file mode 100644
index 0000000..6713af1
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.spec.ts
@@ -0,0 +1,47 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FeedListComponent } from './feed-list.component';
+import { FeedProviderService } from '../services/feed.provider.service';
+import { feedItemMocks } from '../models/feed-item.model';
+
+describe('FeedListComponent', () => {
+ let component: FeedListComponent;
+ let fixture: ComponentFixture;
+ let feedProvider: FeedProviderService;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FeedListComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FeedListComponent);
+
+ // SET UP SPIES AND MOCKS
+ feedProvider = fixture.debugElement.injector.get(FeedProviderService);
+ // spyOn(feedProvider, 'fetch').and.returnValue(Promise.resolve(feedItemMocks));
+
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should fetch on load', () => {
+ expect(feedProvider.getFeed).toHaveBeenCalled();
+ });
+
+ it('should display all of the fetched items', () => {
+ component.feedItems = feedItemMocks;
+ fixture.detectChanges();
+ const app = fixture.nativeElement;
+ const items = app.querySelectorAll('app-feed-item');
+ expect(items.length).toEqual(feedItemMocks.length);
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.ts
new file mode 100644
index 0000000..a0e5f72
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-list/feed-list.component.ts
@@ -0,0 +1,34 @@
+import { Component, OnInit, ChangeDetectionStrategy, Input, OnDestroy } from '@angular/core';
+import { environment } from '../../../environments/environment';
+import { FeedItem } from '../models/feed-item.model';
+import { FeedProviderService } from '../services/feed.provider.service';
+import { Subscription } from 'rxjs';
+
+@Component({
+ selector: 'app-feed-list',
+ templateUrl: './feed-list.component.html',
+ styleUrls: ['./feed-list.component.scss'],
+ // changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class FeedListComponent implements OnInit, OnDestroy {
+ @Input() feedItems: FeedItem[];
+ subscriptions: Subscription[] = [];
+ constructor( private feed: FeedProviderService ) { }
+
+ async ngOnInit() {
+ this.subscriptions.push(
+ this.feed.currentFeed$.subscribe((items) => {
+ this.feedItems = items;
+ }));
+
+ await this.feed.getFeed();
+ }
+
+ ngOnDestroy(): void {
+ for (const subscription of this.subscriptions) {
+ subscription.unsubscribe();
+ }
+ }
+
+
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.html
new file mode 100644
index 0000000..64197d2
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.html
@@ -0,0 +1,7 @@
+
+ Create a New Post
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.spec.ts
new file mode 100644
index 0000000..d418676
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.spec.ts
@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FeedUploadButtonComponent } from './feed-upload-button.component';
+
+describe('FeedUploadButtonPage', () => {
+ let component: FeedUploadButtonComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FeedUploadButtonComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FeedUploadButtonComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.ts
new file mode 100644
index 0000000..4491307
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload-button/feed-upload-button.component.ts
@@ -0,0 +1,38 @@
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { ModalController } from '@ionic/angular';
+import { FeedUploadComponent } from '../feed-upload.component';
+import { AuthService } from 'src/app/auth/services/auth.service';
+import { Subscription } from 'rxjs';
+
+@Component({
+ selector: 'app-feed-upload-button',
+ templateUrl: './feed-upload-button.component.html',
+ styleUrls: ['./feed-upload-button.component.scss'],
+})
+export class FeedUploadButtonComponent implements OnInit, OnDestroy {
+
+ isLoggedIn: Boolean;
+ loginSub: Subscription;
+
+ constructor(private modalController: ModalController, private auth: AuthService) { }
+
+ ngOnInit() {
+ this.auth.currentUser$.subscribe((user) => {
+ this.isLoggedIn = user !== null;
+ });
+ }
+
+ ngOnDestroy(): void {
+ if (this.loginSub) {
+ this.loginSub.unsubscribe();
+ }
+ }
+
+ async presentUploadForm(ev: any) {
+ const modal = await this.modalController.create({
+ component: FeedUploadComponent,
+ });
+ return await modal.present();
+ }
+
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.html
new file mode 100644
index 0000000..0268f0f
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.html
@@ -0,0 +1,19 @@
+
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.spec.ts
new file mode 100644
index 0000000..c0fd4c8
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.spec.ts
@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FeedUploadComponent } from './feed-upload.component';
+
+describe('FeedUploadPage', () => {
+ let component: FeedUploadComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FeedUploadComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FeedUploadComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.ts
new file mode 100644
index 0000000..68c9e1a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed-upload/feed-upload.component.ts
@@ -0,0 +1,68 @@
+import { Component, OnInit } from '@angular/core';
+import { ApiService } from 'src/app/api/api.service';
+
+import { Validators, FormBuilder, FormGroup, FormControl } from '@angular/forms';
+import { FeedProviderService } from '../services/feed.provider.service';
+
+import { LoadingController, ModalController } from '@ionic/angular';
+
+
+@Component({
+ selector: 'app-feed-upload',
+ templateUrl: './feed-upload.component.html',
+ styleUrls: ['./feed-upload.component.scss'],
+})
+export class FeedUploadComponent implements OnInit {
+ previewDataUrl;
+ file: File;
+ uploadForm: FormGroup;
+
+ constructor(
+ private feed: FeedProviderService,
+ private formBuilder: FormBuilder,
+ private loadingController: LoadingController,
+ private modalController: ModalController
+ ) { }
+
+ ngOnInit() {
+ this.uploadForm = this.formBuilder.group({
+ caption: new FormControl('', Validators.required)
+ });
+ }
+
+ setPreviewDataUrl(file: Blob) {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ this.previewDataUrl = reader.result;
+ };
+
+ reader.readAsDataURL(file);
+ }
+
+ selectImage(event) {
+ const file = event.srcElement.files;
+
+ if (!file) {
+ return;
+ }
+ this.file = file[0];
+ this.setPreviewDataUrl(this.file);
+
+ }
+
+ onSubmit($event) {
+ $event.preventDefault();
+ this.loadingController.create();
+
+ if (!this.uploadForm.valid || !this.file) { return; }
+ this.feed.uploadFeedItem(this.uploadForm.controls.caption.value, this.file)
+ .then((result) => {
+ this.modalController.dismiss();
+ this.loadingController.dismiss();
+ });
+ }
+
+ cancel() {
+ this.modalController.dismiss();
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed.module.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed.module.ts
new file mode 100644
index 0000000..900a078
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/feed.module.ts
@@ -0,0 +1,29 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { IonicModule } from '@ionic/angular';
+import { RouterModule } from '@angular/router';
+
+import { FeedListComponent } from './feed-list/feed-list.component';
+import { FeedItemComponent } from './feed-item/feed-item.component';
+import { FeedUploadComponent } from './feed-upload/feed-upload.component';
+import { FeedUploadButtonComponent } from './feed-upload/feed-upload-button/feed-upload-button.component';
+
+import { FeedProviderService } from './services/feed.provider.service';
+
+const entryComponents = [FeedUploadComponent];
+const components = [FeedListComponent, FeedItemComponent, FeedUploadComponent, FeedUploadButtonComponent];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ IonicModule,
+ ReactiveFormsModule
+ ],
+ declarations: components,
+ exports: components,
+ entryComponents: entryComponents,
+ providers: [FeedProviderService]
+})
+export class FeedModule {}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/models/feed-item.model.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/models/feed-item.model.ts
new file mode 100644
index 0000000..5ac4633
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/models/feed-item.model.ts
@@ -0,0 +1,23 @@
+export interface FeedItem {
+ id: number;
+ url: string;
+ caption: string;
+}
+
+export const feedItemMocks: FeedItem[] = [
+ {
+ id: 0,
+ url: '/assets/mock/xander0.jpg',
+ caption: 'Such a cute pup'
+ },
+ {
+ id: 0,
+ url: '/assets/mock/xander1.jpg',
+ caption: 'Who\'s a good boy?'
+ },
+ {
+ id: 0,
+ url: '/assets/mock/xander2.jpg',
+ caption: 'Majestic.'
+ }
+];
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.spec.ts
new file mode 100644
index 0000000..39f6b12
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { FeedProviderService } from './feed.provider.service';
+
+describe('Feed.ProviderService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: FeedProviderService = TestBed.get(FeedProviderService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.ts
new file mode 100644
index 0000000..9491f1e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/feed/services/feed.provider.service.ts
@@ -0,0 +1,39 @@
+import { Injectable } from '@angular/core';
+import { FeedItem, feedItemMocks } from '../models/feed-item.model';
+import { BehaviorSubject } from 'rxjs';
+
+import { ApiService } from '../../api/api.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FeedProviderService {
+ currentFeed$: BehaviorSubject = new BehaviorSubject([]);
+
+ constructor(private api: ApiService) { }
+
+ async getFeed(): Promise> {
+ const req = await this.api.get('/feed');
+ const items = req.rows;
+ this.currentFeed$.next(items);
+ return Promise.resolve(this.currentFeed$);
+ }
+
+ async uploadFeedItem(caption: string, file: File): Promise {
+ const res = await this.api.upload('/feed', file, {caption: caption, url: file.name});
+ const feed = [res, ...this.currentFeed$.value];
+ this.currentFeed$.next(feed);
+ return res;
+ }
+
+}
+
+// async getFeed() {
+// const url = `${API_HOST}/feed`;
+
+// const req = this.http.get(url, this.httpOptions).pipe(
+// map(this.extractData));
+// // catchError(this.handleError));
+// const resp = (await req.toPromise());
+// return resp.rows;
+// }
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.module.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.module.ts
new file mode 100644
index 0000000..cacd46a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.module.ts
@@ -0,0 +1,24 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { IonicModule } from '@ionic/angular';
+import { RouterModule } from '@angular/router';
+import { FeedModule } from '../feed/feed.module';
+import { HomePage } from './home.page';
+
+@NgModule({
+ imports: [
+ FeedModule,
+ CommonModule,
+ FormsModule,
+ IonicModule,
+ RouterModule.forChild([
+ {
+ path: '',
+ component: HomePage
+ }
+ ])
+ ],
+ declarations: [HomePage]
+})
+export class HomePageModule {}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.html
new file mode 100644
index 0000000..b8934ae
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.scss
new file mode 100644
index 0000000..e69de29
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.spec.ts
new file mode 100644
index 0000000..6e695f7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.spec.ts
@@ -0,0 +1,29 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HomePage } from './home.page';
+import { environment } from '../../environments/environment';
+
+describe('HomePage', () => {
+ let component: HomePage;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ HomePage ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HomePage);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.ts
new file mode 100644
index 0000000..ff86e81
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/home/home.page.ts
@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+import { environment } from '../../environments/environment';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: 'home.page.html',
+ styleUrls: ['home.page.scss'],
+})
+export class HomePage {
+ appName = environment.appName;
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.html b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.html
new file mode 100644
index 0000000..68dc329
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ {{ appName }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.scss b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.scss
new file mode 100644
index 0000000..4dcab3e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.scss
@@ -0,0 +1,5 @@
+ion-title {
+ font-weight: bold;
+ font-family: 'Dancing Script', cursive;
+ font-size: 180%;
+ }
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.spec.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.spec.ts
new file mode 100644
index 0000000..b9a82ea
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.spec.ts
@@ -0,0 +1,36 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MenubarComponent } from './menubar.component';
+import { environment } from '../../environments/environment';
+
+
+describe('MenubarPage', () => {
+ let component: MenubarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ MenubarComponent ],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MenubarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('title should be enviornment.AppTitle', () => {
+ const app = fixture.nativeElement;
+ const title = app.querySelectorAll('ion-title');
+ expect(title.length).toEqual(1);
+ expect(title[0].innerText).toEqual(environment.appName);
+ });
+});
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.ts b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.ts
new file mode 100644
index 0000000..41fcbe5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/app/menubar/menubar.component.ts
@@ -0,0 +1,16 @@
+import { Component, OnInit } from '@angular/core';
+import { environment } from '../../environments/environment';
+
+@Component({
+ selector: 'app-menubar',
+ templateUrl: './menubar.component.html',
+ styleUrls: ['./menubar.component.scss'],
+})
+export class MenubarComponent implements OnInit {
+ public appName = environment.appName;
+
+ constructor() { }
+
+ ngOnInit() {}
+
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/assets/icon/favicon.png b/project3-microservices-udagram/udacity-c2-frontend/src/assets/icon/favicon.png
new file mode 100644
index 0000000..51888a7
Binary files /dev/null and b/project3-microservices-udagram/udacity-c2-frontend/src/assets/icon/favicon.png differ
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/assets/shapes.svg b/project3-microservices-udagram/udacity-c2-frontend/src/assets/shapes.svg
new file mode 100644
index 0000000..d370b4d
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/assets/shapes.svg
@@ -0,0 +1 @@
+
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.prod.ts b/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.prod.ts
new file mode 100644
index 0000000..2f47299
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.prod.ts
@@ -0,0 +1,18 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: true,
+ appName: 'Udagram',
+ apiHost: 'http://udagram-kjm-dev-dev.eu-west-3.elasticbeanstalk.com/api/v0'
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.ts b/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.ts
new file mode 100644
index 0000000..183b725
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/environments/environment.ts
@@ -0,0 +1,18 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: false,
+ appName: 'Udagram',
+ apiHost: 'http://localhost:8080/api/v0'
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/global.scss b/project3-microservices-udagram/udacity-c2-frontend/src/global.scss
new file mode 100644
index 0000000..cd3e674
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/global.scss
@@ -0,0 +1,14 @@
+// http://ionicframework.com/docs/theming/
+@import '~@ionic/angular/css/core.css';
+@import '~@ionic/angular/css/normalize.css';
+@import '~@ionic/angular/css/structure.css';
+@import '~@ionic/angular/css/typography.css';
+@import '~@ionic/angular/css/display.css';
+@import '~@ionic/angular/css/padding.css';
+@import '~@ionic/angular/css/float-elements.css';
+@import '~@ionic/angular/css/text-alignment.css';
+@import '~@ionic/angular/css/text-transformation.css';
+@import '~@ionic/angular/css/flex-utils.css';
+
+// Fancy Fonts
+@import url('https://fonts.googleapis.com/css?family=Dancing+Script:700');
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/index.html b/project3-microservices-udagram/udacity-c2-frontend/src/index.html
new file mode 100644
index 0000000..6b3ce45
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/karma.conf.js b/project3-microservices-udagram/udacity-c2-frontend/src/karma.conf.js
new file mode 100644
index 0000000..ffd7c16
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/karma.conf.js
@@ -0,0 +1,31 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../coverage'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false
+ });
+};
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/main.ts b/project3-microservices-udagram/udacity-c2-frontend/src/main.ts
new file mode 100644
index 0000000..91ec6da
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.log(err));
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/polyfills.ts b/project3-microservices-udagram/udacity-c2-frontend/src/polyfills.ts
new file mode 100644
index 0000000..a6d34ea
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/polyfills.ts
@@ -0,0 +1,85 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10, IE11, and Chrome <55 requires all of the following polyfills.
+ * This also includes Android Emulators with older versions of Chrome and Google Search/Googlebot
+ */
+
+// import 'core-js/es6/symbol';
+// import 'core-js/es6/object';
+// import 'core-js/es6/function';
+// import 'core-js/es6/parse-int';
+// import 'core-js/es6/parse-float';
+// import 'core-js/es6/number';
+// import 'core-js/es6/math';
+// import 'core-js/es6/string';
+// import 'core-js/es6/date';
+// import 'core-js/es6/array';
+// import 'core-js/es6/regexp';
+// import 'core-js/es6/map';
+// import 'core-js/es6/weak-map';
+// import 'core-js/es6/set';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+// import 'core-js/es6/reflect';
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ */
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags.ts';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ * (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/test.ts b/project3-microservices-udagram/udacity-c2-frontend/src/test.ts
new file mode 100644
index 0000000..1631789
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/test.ts
@@ -0,0 +1,20 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/theme/variables.scss b/project3-microservices-udagram/udacity-c2-frontend/src/theme/variables.scss
new file mode 100644
index 0000000..460e055
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/theme/variables.scss
@@ -0,0 +1,77 @@
+// Ionic Variables and Theming. For more info, please see:
+// http://ionicframework.com/docs/theming/
+
+/** Ionic CSS Variables **/
+:root {
+ /** primary **/
+ --ion-color-primary: #3880ff;
+ --ion-color-primary-rgb: 56, 128, 255;
+ --ion-color-primary-contrast: #ffffff;
+ --ion-color-primary-contrast-rgb: 255, 255, 255;
+ --ion-color-primary-shade: #3171e0;
+ --ion-color-primary-tint: #4c8dff;
+
+ /** secondary **/
+ --ion-color-secondary: #0cd1e8;
+ --ion-color-secondary-rgb: 12, 209, 232;
+ --ion-color-secondary-contrast: #ffffff;
+ --ion-color-secondary-contrast-rgb: 255, 255, 255;
+ --ion-color-secondary-shade: #0bb8cc;
+ --ion-color-secondary-tint: #24d6ea;
+
+ /** tertiary **/
+ --ion-color-tertiary: #7044ff;
+ --ion-color-tertiary-rgb: 112, 68, 255;
+ --ion-color-tertiary-contrast: #ffffff;
+ --ion-color-tertiary-contrast-rgb: 255, 255, 255;
+ --ion-color-tertiary-shade: #633ce0;
+ --ion-color-tertiary-tint: #7e57ff;
+
+ /** success **/
+ --ion-color-success: #10dc60;
+ --ion-color-success-rgb: 16, 220, 96;
+ --ion-color-success-contrast: #ffffff;
+ --ion-color-success-contrast-rgb: 255, 255, 255;
+ --ion-color-success-shade: #0ec254;
+ --ion-color-success-tint: #28e070;
+
+ /** warning **/
+ --ion-color-warning: #ffce00;
+ --ion-color-warning-rgb: 255, 206, 0;
+ --ion-color-warning-contrast: #ffffff;
+ --ion-color-warning-contrast-rgb: 255, 255, 255;
+ --ion-color-warning-shade: #e0b500;
+ --ion-color-warning-tint: #ffd31a;
+
+ /** danger **/
+ --ion-color-danger: #f04141;
+ --ion-color-danger-rgb: 245, 61, 61;
+ --ion-color-danger-contrast: #ffffff;
+ --ion-color-danger-contrast-rgb: 255, 255, 255;
+ --ion-color-danger-shade: #d33939;
+ --ion-color-danger-tint: #f25454;
+
+ /** dark **/
+ --ion-color-dark: #222428;
+ --ion-color-dark-rgb: 34, 34, 34;
+ --ion-color-dark-contrast: #ffffff;
+ --ion-color-dark-contrast-rgb: 255, 255, 255;
+ --ion-color-dark-shade: #1e2023;
+ --ion-color-dark-tint: #383a3e;
+
+ /** medium **/
+ --ion-color-medium: #989aa2;
+ --ion-color-medium-rgb: 152, 154, 162;
+ --ion-color-medium-contrast: #ffffff;
+ --ion-color-medium-contrast-rgb: 255, 255, 255;
+ --ion-color-medium-shade: #86888f;
+ --ion-color-medium-tint: #a2a4ab;
+
+ /** light **/
+ --ion-color-light: #f4f5f8;
+ --ion-color-light-rgb: 244, 244, 244;
+ --ion-color-light-contrast: #000000;
+ --ion-color-light-contrast-rgb: 0, 0, 0;
+ --ion-color-light-shade: #d7d8da;
+ --ion-color-light-tint: #FAFAFA;
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.app.json b/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.app.json
new file mode 100644
index 0000000..190fd30
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.app.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/app",
+ "types": []
+ },
+ "exclude": [
+ "test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.spec.json b/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.spec.json
new file mode 100644
index 0000000..de77336
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/src/tsconfig.spec.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "test.ts",
+ "polyfills.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/tsconfig.json b/project3-microservices-udagram/udacity-c2-frontend/tsconfig.json
new file mode 100644
index 0000000..b271fd9
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "baseUrl": "./",
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "module": "es2015",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "importHelpers": true,
+ "target": "es5",
+ "typeRoots": [
+ "node_modules/@types"
+ ],
+ "lib": [
+ "es2018",
+ "dom"
+ ]
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/tslint.json b/project3-microservices-udagram/udacity-c2-frontend/tslint.json
new file mode 100644
index 0000000..104686e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/tslint.json
@@ -0,0 +1,130 @@
+{
+ "rulesDirectory": [
+ "codelyzer"
+ ],
+ "rules": {
+ "arrow-return-shorthand": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "deprecation": {
+ "severity": "warn"
+ },
+ "eofline": true,
+ "forin": true,
+ "import-blacklist": [
+ true,
+ "rxjs/Rx"
+ ],
+ "import-spacing": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "interface-over-type-literal": true,
+ "label-position": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-empty": false,
+ "no-empty-interface": true,
+ "no-eval": true,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-misused-new": true,
+ "no-non-null-assertion": true,
+ "no-redundant-jsdoc": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-string-throw": true,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-initializer": true,
+ "no-unused-expression": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "prefer-const": true,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "unified-signatures": true,
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+ "no-output-on-prefix": true,
+ "use-input-property-decorator": true,
+ "use-output-property-decorator": true,
+ "use-host-property-decorator": true,
+ "no-input-rename": true,
+ "no-output-rename": true,
+ "use-life-cycle-interface": true,
+ "use-pipe-transform-interface": true,
+ "directive-class-suffix": true
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c2-frontend/udacity_tests/git_test.sh b/project3-microservices-udagram/udacity-c2-frontend/udacity_tests/git_test.sh
new file mode 100644
index 0000000..f62840a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c2-frontend/udacity_tests/git_test.sh
@@ -0,0 +1,4 @@
+@ TODO
+Verify dev, staging, and master exist
+verify working on feature branch or similar
+verify cannot push to staging or master (protected branches)
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-deployment/docker/README.md b/project3-microservices-udagram/udacity-c3-deployment/docker/README.md
new file mode 100644
index 0000000..8baf9d5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/docker/README.md
@@ -0,0 +1,17 @@
+# Docker compose usage
+
+Open a new terminal within the project directory and run:
+
+1. Build the images: `docker-compose -f docker-compose-build.yaml build --parallel --pull --force-rm`
+
+![dockercomposebuild](../../screenshots/dockercomposebuild.png)
+
+2. Check images available : `docker images`
+
+![dockerimages](../../screenshots/dockerimages.png)
+
+3. Push the images: `docker-compose -f docker-compose-build.yaml push`
+
+4. Run the containers: `docker-compose up`
+
+![dockercomposeup](../../screenshots/dockercomposeup.png)
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose-build.yaml b/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose-build.yaml
new file mode 100644
index 0000000..4c7796f
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose-build.yaml
@@ -0,0 +1,18 @@
+version: "3.8"
+services:
+ reverseproxy:
+ build:
+ context: ../../udacity-c3-nginx-reverseproxy
+ image: kendyjm/udacity-nginx-reverseproxy
+ backend_user:
+ build:
+ context: ../../udacity-c3-restapi-user
+ image: kendyjm/udacity-restapi-user
+ backend_feed:
+ build:
+ context: ../../udacity-c3-restapi-feed
+ image: kendyjm/udacity-restapi-feed
+ frontend:
+ build:
+ context: ../../udacity-c2-frontend
+ image: kendyjm/udacity-frontend
diff --git a/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose.yaml b/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose.yaml
new file mode 100644
index 0000000..f5fc5ba
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/docker/docker-compose.yaml
@@ -0,0 +1,49 @@
+version: "3.8"
+services:
+ reverseproxy:
+ image: kendyjm/udacity-nginx-reverseproxy
+ ports:
+ - 8080:8080
+ restart: always
+ depends_on:
+ - backend-user
+ - backend-feed
+ backend-user:
+ image: kendyjm/udacity-restapi-user
+ volumes:
+ - $HOME/.aws:/root/.aws
+ environment:
+ DB_USERNAME: $DB_USERNAME
+ DB_PASSWORD: $DB_PASSWORD
+ DB_NAME: $DB_NAME
+ DB_HOST: $DB_HOST
+ AWS_REGION: $AWS_REGION
+ AWS_PROFILE: $AWS_PROFILE
+ AWS_MEDIA_BUCKET: $AWS_MEDIA_BUCKET
+ JWT_SECRET: $JWT_SECRET
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
+ ACCESS_CONTROL_ALLOW_ORIGIN: $ACCESS_CONTROL_ALLOW_ORIGIN
+ SENTRY_DNS_FEED: $SENTRY_DNS_FEED
+ backend-feed:
+ image: kendyjm/udacity-restapi-feed
+ volumes:
+ - $HOME/.aws:/root/.aws
+ environment:
+ DB_USERNAME: $DB_USERNAME
+ DB_PASSWORD: $DB_PASSWORD
+ DB_NAME: $DB_NAME
+ DB_HOST: $DB_HOST
+ AWS_REGION: $AWS_REGION
+ AWS_PROFILE: $AWS_PROFILE
+ AWS_MEDIA_BUCKET: $AWS_MEDIA_BUCKET
+ JWT_SECRET: $JWT_SECRET
+ AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
+ AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
+ ACCESS_CONTROL_ALLOW_ORIGIN: $ACCESS_CONTROL_ALLOW_ORIGIN
+ SENTRY_DNS_USER: $SENTRY_DNS_USER
+ frontend:
+ image: kendyjm/udacity-frontend
+ ports:
+ - "8100:80"
diff --git a/project3-microservices-udagram/udacity-c3-deployment/eks/README.md b/project3-microservices-udagram/udacity-c3-deployment/eks/README.md
new file mode 100644
index 0000000..3a3ef47
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/eks/README.md
@@ -0,0 +1,15 @@
+# Elastic Kubernetes Service (Amazon EKS) - Creation guide
+
+Create your cluster with `eksctl` by running the running the following script or the [official guide](https://eksctl.io/usage/creating-and-managing-clusters/).
+
+```bash
+eksctl create cluster -f eksclusterconfig.yaml
+```
+
+`eksclusterconfig.yaml` follows the [schema described here](https://eksctl.io/usage/schema/)
+
+You get this output:
+![eksclustercreation](../../screenshots/eksclustercreation.png)
+
+Your cluster is created and visible in the [AWS Console/EKS](https://eu-west-3.console.aws.amazon.com/eks/home#/clusters):
+![eksclusterconsole](../../screenshots/eksclusterconsole.png)
diff --git a/project3-microservices-udagram/udacity-c3-deployment/eks/eksclusterconfig.yaml b/project3-microservices-udagram/udacity-c3-deployment/eks/eksclusterconfig.yaml
new file mode 100644
index 0000000..3f1fbfa
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/eks/eksclusterconfig.yaml
@@ -0,0 +1,23 @@
+apiVersion: eksctl.io/v1alpha5
+kind: ClusterConfig
+
+metadata:
+ name: udagram
+ region: eu-west-3
+ version: "1.17"
+
+managedNodeGroups:
+ - name: udagram-ng
+ instanceType: t3.medium
+ desiredCapacity: 3
+ minSize: 1
+ maxSize: 4
+ ssh:
+ allow: true
+
+cloudWatch:
+ clusterLogging:
+ # enable specific types of cluster control plane logs
+ enableTypes: ["audit"]
+ # all supported types: "api", "audit", "authenticator", "controllerManager", "scheduler"
+ # supported special values: "*" and "all"
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/README.md b/project3-microservices-udagram/udacity-c3-deployment/k8s/README.md
new file mode 100644
index 0000000..df8f1a5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/README.md
@@ -0,0 +1,56 @@
+# Setup Kubernetes Environment
+
+## Edit Kubernetes Configmaps and Secrets
+
+Encrypt your database username and password using base64 and running this commands:
+
+```bash
+echo -n $DB_PASSWORD | base64
+echo -n $DB_USERNAME | base64
+```
+
+Encrypt your aws file using base64 and running this command:
+
+```bash
+cat ~/.aws/credentials | base64
+```
+
+Add these values in the coresponding empty fiels in `env-secret.yaml`, `aws-secret.yaml` and `env-configmap.yaml`.
+
+## Load Kubernetes Environment
+
+Load secret files:
+
+```bash
+kubectl apply -f aws-secret.yaml
+kubectl apply -f env-secret.yaml
+kubectl apply -f env-configmap.yaml
+```
+
+Apply all other yaml files:
+
+```bash
+kubectl apply -f .
+```
+
+![kubernetescomponentsloading](../../screenshots/kubernetescomponentsloading.png)
+
+## Enable Horizontal Scaling In Kubernetes
+
+This optional, enable [Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) on deployments.
+
+## Check status of all resources (services, delpoyments, pods, hpa)
+
+```bash
+kubectl get all
+```
+
+![kubernetesresourcesstatus](../../screenshots/kubernetesresourcesstatus.png)
+
+## Check pods logs
+
+```bash
+kubectl logs
+```
+
+![kubernetespodslogs](../../screenshots/kubernetespodslogs.png)
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/aws-secret.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/aws-secret.yaml
new file mode 100644
index 0000000..bf819e7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/aws-secret.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-secret
+type: Opaque
+data:
+ credentials: ___INSERT_AWS_CREDENTIALS_FILE__BASE64____
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-deployment.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-deployment.yaml
new file mode 100644
index 0000000..914c9e2
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-deployment.yaml
@@ -0,0 +1,82 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ service: backend-feed
+ name: backend-feed
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ service: backend-feed
+ template:
+ metadata:
+ labels:
+ service: backend-feed
+ spec:
+ containers:
+ - image: kendyjm/udacity-restapi-feed
+ name: backend-feed
+ imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1536Mi"
+ cpu: "500m"
+ env:
+ - name: ACCESS_CONTROL_ALLOW_ORIGIN
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: ACCESS_CONTROL_ALLOW_ORIGIN
+ - name: AWS_MEDIA_BUCKET
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_MEDIA_BUCKET
+ - name: AWS_PROFILE
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_PROFILE
+ - name: AWS_REGION
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_REGION
+ - name: JWT_SECRET
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: JWT_SECRET
+ - name: DB_NAME
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_NAME
+ - name: DB_HOST
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_HOST
+ - name: DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_PASSWORD
+ - name: DB_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_USERNAME
+ volumeMounts:
+ - name: aws-secret
+ mountPath: "/root/.aws/"
+ readOnly: true
+ restartPolicy: Always
+ volumes:
+ - name: aws-secret
+ secret:
+ secretName: aws-secret
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-service.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-service.yaml
new file mode 100644
index 0000000..35c95ee
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-feed-service.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ service: backend-feed
+ name: backend-feed
+spec:
+ ports:
+ - name: "8080"
+ port: 8080
+ targetPort: 8080
+ selector:
+ service: backend-feed
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-deployment.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-deployment.yaml
new file mode 100644
index 0000000..a2774e2
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-deployment.yaml
@@ -0,0 +1,61 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ service: backend-user
+ name: backend-user
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ service: backend-user
+ template:
+ metadata:
+ labels:
+ service: backend-user
+ spec:
+ containers:
+ - image: kendyjm/udacity-restapi-user
+ name: backend-user
+ imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1536Mi"
+ cpu: "500m"
+ env:
+ - name: ACCESS_CONTROL_ALLOW_ORIGIN
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: ACCESS_CONTROL_ALLOW_ORIGIN
+ - name: JWT_SECRET
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: JWT_SECRET
+ - name: DB_NAME
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_NAME
+ - name: DB_HOST
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_HOST
+ - name: DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_PASSWORD
+ - name: DB_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_USERNAME
+ restartPolicy: Always
+
+
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-service.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-service.yaml
new file mode 100644
index 0000000..c2c8836
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/backend-user-service.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ service: backend-user
+ name: backend-user
+spec:
+ ports:
+ - name: "8080"
+ port: 8080
+ targetPort: 8080
+ selector:
+ service: backend-user
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/env-configmap.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/env-configmap.yaml
new file mode 100644
index 0000000..2ab077e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/env-configmap.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+data:
+ AWS_MEDIA_BUCKET: ___INSERT_AWS_MEDIA_BUCKET___
+ AWS_PROFILE: ___INSERT_AWS_PROFILE___
+ AWS_REGION: ___INSERT_AWS_REGION___
+ JWT_SECRET: ___INSERT_JWT_SECRET___
+ DB_NAME: ___INSERT_DB_NAME___
+ DB_HOST: ___INSERT_DB_HOST___
+ ACCESS_CONTROL_ALLOW_ORIGIN: ___INSERT_ACCESS_CONTROL_ALLOW_ORIGIN___
+metadata:
+ name: env-config
+
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/env-secret.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/env-secret.yaml
new file mode 100644
index 0000000..b234993
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/env-secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: env-secret
+type: Opaque
+data:
+ DB_USERNAME: ___INSERT_POSTGRESS_USERNAME__BASE64___
+ DB_PASSWORD: ___INSERT_POSTGRESS_PASSWORD__BASE64___
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-deployment.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-deployment.yaml
new file mode 100644
index 0000000..8c3d26b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-deployment.yaml
@@ -0,0 +1,32 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ service: frontend
+ name: frontend
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ service: frontend
+ template:
+ metadata:
+ labels:
+ service: frontend
+ api: external
+ spec:
+ containers:
+ - image: kendyjm/udacity-frontend
+ name: frontend
+ imagePullPolicy: Always
+ ports:
+ - containerPort: 80
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1024Mi"
+ cpu: "500m"
+ restartPolicy: Always
+
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-service.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-service.yaml
new file mode 100644
index 0000000..8f5b6c5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/frontend-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ service: frontend
+ name: frontend
+spec:
+ ports:
+ - name: "8100"
+ port: 8100
+ targetPort: 80
+ selector:
+ service: frontend
+# type: LoadBalancer
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/README.md b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/README.md
new file mode 100644
index 0000000..3677a40
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/README.md
@@ -0,0 +1,4 @@
+# Deployment of an microservice application as pod
+
+Use command:
+`kubectl apply -f pod.yaml`
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/backend-feed-pod.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/backend-feed-pod.yaml
new file mode 100644
index 0000000..6cc4d7b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/backend-feed-pod.yaml
@@ -0,0 +1,72 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: backend-feed
+spec:
+ containers:
+ - image: kendyjm/udacity-restapi-feed
+ name: backend-feed
+ imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1024Mi"
+ cpu: "500m"
+ env:
+ - name: ACCESS_CONTROL_ALLOW_ORIGIN
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: ACCESS_CONTROL_ALLOW_ORIGIN
+ - name: AWS_MEDIA_BUCKET
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_MEDIA_BUCKET
+ - name: AWS_PROFILE
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_PROFILE
+ - name: AWS_REGION
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: AWS_REGION
+ - name: JWT_SECRET
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: JWT_SECRET
+ - name: DB_NAME
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_NAME
+ - name: DB_HOST
+ valueFrom:
+ configMapKeyRef:
+ name: env-config
+ key: DB_HOST
+ - name: DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_PASSWORD
+ - name: DB_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: env-secret
+ key: DB_USERNAME
+ volumeMounts:
+ - name: aws-secret
+ mountPath: "/root/.aws/"
+ readOnly: true
+ restartPolicy: Always
+ volumes:
+ - name: aws-secret
+ secret:
+ secretName: aws-secret
+
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/pod.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/pod.yaml
new file mode 100644
index 0000000..b79ab0b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/pod-example/pod.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: pod-example
+spec:
+ containers:
+ - image: kendyjm/udacity-nginx-reverseproxy
+ name: reverseproxy
+ imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1024Mi"
+ cpu: "500m"
+ ports:
+ - containerPort: 8080
+ restartPolicy: Always
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-deployment.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-deployment.yaml
new file mode 100644
index 0000000..8af4b1b
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-deployment.yaml
@@ -0,0 +1,32 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ service: reverseproxy
+ name: reverseproxy
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ service: reverseproxy
+ template:
+ metadata:
+ labels:
+ service: reverseproxy
+ spec:
+ containers:
+ - image: kendyjm/udacity-nginx-reverseproxy
+ name: reverseproxy
+ imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "1024Mi"
+ cpu: "500m"
+ ports:
+ - containerPort: 8080
+ restartPolicy: Always
+
+
diff --git a/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-service.yaml b/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-service.yaml
new file mode 100644
index 0000000..e2ecf04
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-deployment/k8s/reverseproxy-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ service: reverseproxy
+ name: reverseproxy
+spec:
+ ports:
+ - name: "8080"
+ port: 8080
+ targetPort: 8080
+ selector:
+ service: reverseproxy
+# type: LoadBalancer
diff --git a/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/Dockerfile b/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/Dockerfile
new file mode 100644
index 0000000..9c54268
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/Dockerfile
@@ -0,0 +1,3 @@
+FROM nginx:alpine
+
+COPY nginx.conf /etc/nginx/nginx.conf
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/nginx.conf b/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/nginx.conf
new file mode 100644
index 0000000..8fa8377
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-nginx-reverseproxy/nginx.conf
@@ -0,0 +1,33 @@
+worker_processes 1;
+
+events { worker_connections 1024; }
+error_log /dev/stdout debug;
+
+http {
+
+ sendfile on;
+
+ upstream user {
+ server backend-user:8080;
+ }
+
+ upstream feed {
+ server backend-feed:8080;
+ }
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Host $server_name;
+
+ server {
+ listen 8080;
+ location /api/v0/feed {
+ proxy_pass http://feed;
+ }
+ location /api/v0/users {
+ proxy_pass http://user;
+ }
+ }
+
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/.dockerignore b/project3-microservices-udagram/udacity-c3-restapi-feed/.dockerignore
new file mode 100644
index 0000000..5171c54
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/.dockerignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/.gitignore b/project3-microservices-udagram/udacity-c3-restapi-feed/.gitignore
new file mode 100644
index 0000000..46b3664
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/.gitignore
@@ -0,0 +1,42 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+*~
+*.sw[mnpcod]
+*.log
+*.tmp
+*.tmp.*
+log.txt
+*.sublime-project
+*.sublime-workspace
+.vscode/
+npm-debug.log*
+
+.idea/
+.ionic/
+.sourcemaps/
+.sass-cache/
+.tmp/
+.versions/
+coverage/
+www/
+node_modules/
+tmp/
+temp/
+platforms/
+plugins/
+plugins/android.json
+plugins/ios.json
+$RECYCLE.BIN/
+postgres_dev/
+logfile
+
+.DS_Store
+Thumbs.db
+UserInterfaceState.xcuserstate
+node_modules
+venv/
+# Elastic Beanstalk Files
+.elasticbeanstalk/*
+!.elasticbeanstalk/*.cfg.yml
+!.elasticbeanstalk/*.global.yml
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/.npmrc b/project3-microservices-udagram/udacity-c3-restapi-feed/.npmrc
new file mode 100644
index 0000000..3364a17
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/.npmrc
@@ -0,0 +1 @@
+unsafe-perm=true
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/Dockerfile b/project3-microservices-udagram/udacity-c3-restapi-feed/Dockerfile
new file mode 100644
index 0000000..b657653
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/Dockerfile
@@ -0,0 +1,11 @@
+# latest LTS (long term support) version 12 of node available from the Docker hub
+FROM node:12
+# Create app directory
+WORKDIR /usr/src/app
+# Bundle app source
+COPY . .
+RUN npm install
+# If you are building your code for production
+# RUN npm ci --only=production
+EXPOSE 8080
+CMD [ "npm", "run", "prod" ]
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/README.md b/project3-microservices-udagram/udacity-c3-restapi-feed/README.md
new file mode 100644
index 0000000..4ec8fe7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/README.md
@@ -0,0 +1,60 @@
+# Udagram REST API
+
+Udagram is a simple cloud application developed alongside the Udacity Cloud Engineering Nanodegree. It allows users to register and log into a web client, post photos to the feed, and process photos using an image filtering microservice.
+
+The project is split into three parts:
+
+1. [The Simple Frontend](../udacity-c2-frontend)
+A basic Ionic client web application which consumes the RestAPI Backend.
+2. [The RestAPI Backend](.), a Node-Express server which can be deployed to a cloud service.
+3. [The Image Filtering Microservice](../../../project2-image-filter), the final project for the course. It is a Node-Express application which runs a simple script to process images.
+
+***
+
+## Getting Setup
+
+### Installing project dependencies
+
+This project uses NPM to manage software dependencies. NPM Relies on the package.json file located in the root of this repository. After cloning, open your terminal and run:
+
+```bash
+npm install
+```
+
+>_tip_: **npm i** is shorthand for **npm install**
+
+### Installing useful tools
+
+#### 1. [Postbird](https://github.com/paxa/postbird)
+
+Postbird is a useful client GUI (graphical user interface) to interact with our provisioned Postgres database. We can establish a remote connection and complete actions like viewing data and changing schema (tables, columns, ect).
+
+#### 2. [Postman](https://www.getpostman.com/downloads/)
+
+Postman is a useful tool to issue and save requests. Postman can create GET, PUT, POST, etc. requests complete with bodies. It can also be used to test endpoints automatically. We've included a collection (`./udacity-c2-restapi.postman_collection.json`) which contains example requsts.
+
+***
+
+## Running the Server Locally
+
+To run the server locally in developer mode, open terminal and run:
+
+```bash
+npm run dev
+```
+
+Developer mode runs off the TypeScript source. Any saves will reset the server and run the latest version of the codebase.
+
+***
+
+## Build & run docker image
+
+### Build your image
+
+`docker build -t {dockerid}/udacity-restapi-feed .`
+Replace {dockerid} with your docker user's id.
+The -t flag lets you tag your image so it's easier to find later using the docker images command.
+
+### Run your image
+
+`docker run --rm --publish 8080:8080 -v "%userprofile%\.aws:/root/.aws" --env DB_USERNAME=%DB_USERNAME% --env DB_PASSWORD=%DB_PASSWORD% --env DB_NAME=%DB_NAME% --env DB_HOST=%DB_HOST% --env AWS_REGION=%AWS_REGION% --env AWS_PROFILE=%AWS_PROFILE% --env AWS_MEDIA_BUCKET=%AWS_MEDIA_BUCKET% --env AWS_ACCESS_KEY_ID=%AWS_ACCESS_KEY_ID% --env AWS_SECRET_ACCESS_KEY=%AWS_SECRET_ACCESS_KEY% --env JWT_SECRET=%JWT_SECRET% --env ACCESS_CONTROL_ALLOW_ORIGIN=%ACCESS_CONTROL_ALLOW_ORIGIN% --env SENTRY_DNS=%SENTRY_DNS% --env IMAGEFILTER_SENTRY_DNS=%IMAGEFILTER_SENTRY_DNS% --env IMAGEFILTER_MORGAN_FORMAT="%IMAGEFILTER_MORGAN_FORMAT%" --env SENTRY_DNS_FEED=%SENTRY_DNS_FEED% --env SENTRY_DNS_USER=%SENTRY_DNS_USER% --env PORT_FEED_SERVICE=8080 --env PORT_USER_SERVICE=8080 --name feed kendyjm/udacity-restapi-feed`
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander0.jpg b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander0.jpg
new file mode 100644
index 0000000..751c171
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander0.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander1.jpg b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander1.jpg
new file mode 100644
index 0000000..75ab66d
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander1.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander2.jpg b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander2.jpg
new file mode 100644
index 0000000..326fbed
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-feed/mock/xander2.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/package-lock.json b/project3-microservices-udagram/udacity-c3-restapi-feed/package-lock.json
new file mode 100644
index 0000000..e306944
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/package-lock.json
@@ -0,0 +1,3444 @@
+{
+ "name": "udacity-c2-restapi",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@sentry/apm": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/apm/-/apm-5.19.2.tgz",
+ "integrity": "sha512-V7p5niqG/Nn1OSMAyreChiIrQFYzFHKADKNaDEvIXqC4hxFnMG8lPRqEFJH49fNjsFBFfIG9iY1rO1ZFg3S42Q==",
+ "requires": {
+ "@sentry/browser": "5.19.2",
+ "@sentry/hub": "5.19.2",
+ "@sentry/minimal": "5.19.2",
+ "@sentry/types": "5.19.2",
+ "@sentry/utils": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/browser": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.19.2.tgz",
+ "integrity": "sha512-o6Z532n+0N5ANDzgR9GN+Q6CU7zVlIJvBEW234rBiB+ZZj6XwTLS1dD+JexGr8lCo8PeXI2rypKcj1jUGLVW8w==",
+ "requires": {
+ "@sentry/core": "5.19.2",
+ "@sentry/types": "5.19.2",
+ "@sentry/utils": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/core": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.19.2.tgz",
+ "integrity": "sha512-sfbBsVXpA0WYJUichz5IhvqKD8xJUfQvsszrTsUKa7PQAMAboOmuh6bo8KquaVQnAZyZWZU08UduvlSV3tA7tw==",
+ "requires": {
+ "@sentry/hub": "5.19.2",
+ "@sentry/minimal": "5.19.2",
+ "@sentry/types": "5.19.2",
+ "@sentry/utils": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/hub": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.19.2.tgz",
+ "integrity": "sha512-2KkEYX4q9TDCOiaVEo2kQ1W0IXyZxJxZtIjDdFQyes9T4ubYlKHAbvCjTxHSQv37lDO4t7sOIApWG9rlkHzlEA==",
+ "requires": {
+ "@sentry/types": "5.19.2",
+ "@sentry/utils": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/minimal": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.19.2.tgz",
+ "integrity": "sha512-rApEOkjy+ZmkeqEItgFvUFxe5l+dht9AumuUzq74pWp+HJqxxv9IVTusKppBsE1adjtmyhwK4O3Wr8qyc75xlw==",
+ "requires": {
+ "@sentry/hub": "5.19.2",
+ "@sentry/types": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/node": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.19.2.tgz",
+ "integrity": "sha512-gbww3iTWkdvYIAhOmULbv8znKwkIpklGJ0SPtAh0orUMuaa0lVht+6HQIhRgeXp50lMzNaYC3fuzkbFfYgpS7A==",
+ "requires": {
+ "@sentry/apm": "5.19.2",
+ "@sentry/core": "5.19.2",
+ "@sentry/hub": "5.19.2",
+ "@sentry/types": "5.19.2",
+ "@sentry/utils": "5.19.2",
+ "cookie": "^0.3.1",
+ "https-proxy-agent": "^5.0.0",
+ "lru_map": "^0.3.3",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/types": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.19.2.tgz",
+ "integrity": "sha512-O6zkW8oM1qK5Uma9+B/UMlmlm9/gkw9MooqycWuEhIaKfDBj/yVbwb/UTiJmNkGc5VJQo0v1uXUZZQt6/Xq1GA=="
+ },
+ "@sentry/utils": {
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.19.2.tgz",
+ "integrity": "sha512-gEPkC0CJwvIWqcTcPSdIzqJkJa9N5vZzUZyBvdu1oiyJu7MfazpJEvj3whfJMysSfXJQxoJ+a1IPrA73VY23VA==",
+ "requires": {
+ "@sentry/types": "5.19.2",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@types/bcrypt": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-3.0.0.tgz",
+ "integrity": "sha512-nohgNyv+1ViVcubKBh0+XiNJ3dO8nYu///9aJ4cgSqv70gBL+94SNy/iC2NLzKPT2Zt/QavrOkBVbZRLZmw6NQ=="
+ },
+ "@types/bluebird": {
+ "version": "3.5.26",
+ "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.26.tgz",
+ "integrity": "sha512-aj2mrBLn5ky0GmAg6IPXrQjnN0iB/ulozuJ+oZdrHRAzRbXjGmu4UXsNCjFvPbSaaPZmniocdOzsM392qLOlmQ=="
+ },
+ "@types/body-parser": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz",
+ "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
+ "dev": true,
+ "requires": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/chai": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz",
+ "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==",
+ "dev": true
+ },
+ "@types/connect": {
+ "version": "3.4.32",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
+ "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/continuation-local-storage": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz",
+ "integrity": "sha1-oz4N+dzptCTRyY/E/evYV43O7H4=",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/cookiejar": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz",
+ "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==",
+ "dev": true
+ },
+ "@types/express": {
+ "version": "4.16.1",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz",
+ "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==",
+ "dev": true,
+ "requires": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "@types/express-serve-static-core": {
+ "version": "4.16.2",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.2.tgz",
+ "integrity": "sha512-qgc8tjnDrc789rAQed8NoiFLV5VGcItA4yWNFphqGU0RcuuQngD00g3LHhWIK3HQ2XeDgVCmlNPDlqi3fWBHnQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "@types/jsonwebtoken": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.2.tgz",
+ "integrity": "sha512-Mkjljd9DTpkPlrmGfTJvcP4aBU7yO2QmW7wNVhV4/6AEUxYoacqU7FJU/N0yFEHTsIrE4da3rUrjrR5ejicFmA==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/lodash": {
+ "version": "4.14.123",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz",
+ "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q=="
+ },
+ "@types/mime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
+ "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "11.11.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz",
+ "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ=="
+ },
+ "@types/range-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
+ "dev": true
+ },
+ "@types/sequelize": {
+ "version": "4.27.44",
+ "resolved": "https://registry.npmjs.org/@types/sequelize/-/sequelize-4.27.44.tgz",
+ "integrity": "sha512-GrM7/rxosbskkToSORCona1D1YMJcJ9O9gCSlobr0hdFn6v0QyvMD/2YRVO/lRXrqHVRFwtZkf0mO0BBbyspEw==",
+ "dev": true,
+ "requires": {
+ "@types/bluebird": "*",
+ "@types/continuation-local-storage": "*",
+ "@types/lodash": "*",
+ "@types/validator": "*"
+ }
+ },
+ "@types/serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==",
+ "dev": true,
+ "requires": {
+ "@types/express-serve-static-core": "*",
+ "@types/mime": "*"
+ }
+ },
+ "@types/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+ "dev": true
+ },
+ "@types/strip-json-comments": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "dev": true
+ },
+ "@types/superagent": {
+ "version": "3.8.7",
+ "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.8.7.tgz",
+ "integrity": "sha512-9KhCkyXv268A2nZ1Wvu7rQWM+BmdYUVkycFeNnYrUL5Zwu7o8wPQ3wBfW59dDP+wuoxw0ww8YKgTNv8j/cgscA==",
+ "dev": true,
+ "requires": {
+ "@types/cookiejar": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/validator": {
+ "version": "10.9.0",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.9.0.tgz",
+ "integrity": "sha512-mf0VpXk+NoTmkUmuJCsdwBYxjYZW41amCSzd4t/fABMKl+qGMViwFP0pR7ukFdZRXWI1LIkca3VIbXVBmWZ4kQ=="
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "accepts": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+ "requires": {
+ "mime-types": "~2.1.18",
+ "negotiator": "0.6.1"
+ }
+ },
+ "agent-base": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
+ "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
+ "requires": {
+ "debug": "4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "ansi-colors": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
+ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "ansicolors": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+ "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=",
+ "dev": true
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "arg": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
+ "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "aws-sdk": {
+ "version": "2.714.2",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.714.2.tgz",
+ "integrity": "sha512-R79E/790Wr7GzPQtkUIUlh7H1GGMvgCSdQ/9c79QTVKEKTkVAbcYE678pwP7nzRk5PTzU/ECvbH2p9hWXNa4UA==",
+ "requires": {
+ "buffer": "4.9.2",
+ "events": "1.1.1",
+ "ieee754": "1.1.13",
+ "jmespath": "0.15.0",
+ "querystring": "0.2.0",
+ "sax": "1.2.1",
+ "url": "0.10.3",
+ "uuid": "3.3.2",
+ "xml2js": "0.4.19"
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+ },
+ "bcrypt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.6.tgz",
+ "integrity": "sha512-taA5bCTfXe7FUjKroKky9EXpdhkVvhE5owfxfLYodbrAR1Ul3juLmIQmIQBK4L9a5BuUcE6cqmwT+Da20lF9tg==",
+ "requires": {
+ "nan": "2.13.2",
+ "node-pre-gyp": "0.12.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "body-parser": {
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+ "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+ "requires": {
+ "bytes": "3.0.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "~1.6.3",
+ "iconv-lite": "0.4.23",
+ "on-finished": "~2.3.0",
+ "qs": "6.5.2",
+ "raw-body": "2.3.3",
+ "type-is": "~1.6.16"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "buffer-writer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
+ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ }
+ },
+ "cardinal": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
+ "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=",
+ "dev": true,
+ "requires": {
+ "ansicolors": "~0.3.2",
+ "redeyed": "~2.1.0"
+ }
+ },
+ "chai": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+ "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "pathval": "^1.1.0",
+ "type-detect": "^4.0.5"
+ }
+ },
+ "chai-http": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.2.1.tgz",
+ "integrity": "sha512-S2Ezy5uSVuOYleeXppfUKtTU/xbHCZyKkwjheNJ/76SGFTUPDpDkkpVdPNgC3sAO1Ap5J5LJ+/rXdLG8EGhCDA==",
+ "dev": true,
+ "requires": {
+ "@types/chai": "4",
+ "@types/superagent": "^3.8.3",
+ "cookiejar": "^2.1.1",
+ "is-ip": "^2.0.0",
+ "methods": "^1.1.2",
+ "qs": "^6.5.1",
+ "superagent": "^3.7.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+ "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
+ },
+ "cli-table": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
+ "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
+ "dev": true,
+ "requires": {
+ "colors": "1.0.3"
+ }
+ },
+ "cli-usage": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.9.tgz",
+ "integrity": "sha512-MIJJnLu89KTRoGN1ix9dwvKYUPUP7tUL+YGKNH/7mFmy8n3aWNznQKK8FU7PsFVQxePW5rxBp0lupzeSjRiXTA==",
+ "dev": true,
+ "requires": {
+ "marked": "^0.6.2",
+ "marked-terminal": "^3.2.0"
+ },
+ "dependencies": {
+ "marked": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.2.tgz",
+ "integrity": "sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA==",
+ "dev": true
+ }
+ }
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cls-bluebird": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
+ "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
+ "requires": {
+ "is-bluebird": "^1.0.2",
+ "shimmer": "^1.1.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
+ "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+ "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "cookiejar": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
+ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "meow": "^3.3.0"
+ }
+ },
+ "debounce": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz",
+ "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
+ },
+ "dottie": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
+ "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
+ },
+ "dynamic-dedupe": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+ "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+ "dev": true,
+ "requires": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "email-validator": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz",
+ "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ=="
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-shim": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.3.tgz",
+ "integrity": "sha1-m/tzY/7//4emzbbNk+QF7DxLbyY="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "express": {
+ "version": "4.16.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+ "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+ "requires": {
+ "accepts": "~1.3.5",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.18.3",
+ "content-disposition": "0.5.2",
+ "content-type": "~1.0.4",
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.1.1",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.4",
+ "qs": "6.5.2",
+ "range-parser": "~1.2.0",
+ "safe-buffer": "5.1.2",
+ "send": "0.16.2",
+ "serve-static": "1.13.2",
+ "setprototypeof": "1.1.0",
+ "statuses": "~1.4.0",
+ "type-is": "~1.6.16",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "filewatcher": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/filewatcher/-/filewatcher-3.0.1.tgz",
+ "integrity": "sha1-9KGVc1Xdr0Q8zXiolfPVXiPIoDQ=",
+ "dev": true,
+ "requires": {
+ "debounce": "^1.0.0"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+ "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.4.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "flat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
+ "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "~2.0.3"
+ }
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "formidable": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+ "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "fs-minipass": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
+ "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.15",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+ "requires": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
+ "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inflection": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
+ "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+ "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bluebird": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
+ "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
+ },
+ "is-buffer": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+ "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "is-ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz",
+ "integrity": "sha1-aO6gfooKCpTC0IDdZ0xzGrKkYas=",
+ "dev": true,
+ "requires": {
+ "ip-regex": "^2.0.0"
+ }
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "jmespath": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
+ "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.17.11",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+ "dev": true
+ },
+ "lodash._arraycopy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz",
+ "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=",
+ "dev": true
+ },
+ "lodash._arrayeach": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz",
+ "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=",
+ "dev": true
+ },
+ "lodash._baseassign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "^3.0.0",
+ "lodash.keys": "^3.0.0"
+ }
+ },
+ "lodash._baseclone": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz",
+ "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=",
+ "dev": true,
+ "requires": {
+ "lodash._arraycopy": "^3.0.0",
+ "lodash._arrayeach": "^3.0.0",
+ "lodash._baseassign": "^3.0.0",
+ "lodash._basefor": "^3.0.0",
+ "lodash.isarray": "^3.0.0",
+ "lodash.keys": "^3.0.0"
+ }
+ },
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basefor": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
+ "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=",
+ "dev": true
+ },
+ "lodash._bindcallback": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz",
+ "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash.clonedeep": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz",
+ "integrity": "sha1-oKHkDYKl6on/WxR7hETtY9koJ9s=",
+ "dev": true,
+ "requires": {
+ "lodash._baseclone": "^3.0.0",
+ "lodash._bindcallback": "^3.0.0"
+ }
+ },
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "^3.0.0",
+ "lodash.isarguments": "^3.0.0",
+ "lodash.isarray": "^3.0.0"
+ }
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "lodash.toarray": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+ "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g=="
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "marked-terminal": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-3.2.0.tgz",
+ "integrity": "sha512-Yr1yVS0BbDG55vx7be1D0mdv+jGs9AW563o/Tt/7FTsId2J0yqhrTeXAqq/Q0DyyXltIn6CSxzesQuFqXgafjQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.1.0",
+ "cardinal": "^2.1.1",
+ "chalk": "^2.4.1",
+ "cli-table": "^0.3.1",
+ "node-emoji": "^1.4.1",
+ "supports-hyperlinks": "^1.0.1"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+ },
+ "mime-db": {
+ "version": "1.38.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
+ "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
+ },
+ "mime-types": {
+ "version": "2.1.22",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
+ "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+ "requires": {
+ "mime-db": "~1.38.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
+ "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
+ "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "mocha": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz",
+ "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "3.2.3",
+ "browser-stdout": "1.3.1",
+ "debug": "3.2.6",
+ "diff": "3.5.0",
+ "escape-string-regexp": "1.0.5",
+ "find-up": "3.0.0",
+ "glob": "7.1.3",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "3.13.1",
+ "log-symbols": "2.2.0",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "ms": "2.1.1",
+ "node-environment-flags": "1.0.5",
+ "object.assign": "4.1.0",
+ "strip-json-comments": "2.0.1",
+ "supports-color": "6.0.0",
+ "which": "1.3.1",
+ "wide-align": "1.1.3",
+ "yargs": "13.2.2",
+ "yargs-parser": "13.0.0",
+ "yargs-unparser": "1.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
+ "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "moment": {
+ "version": "2.27.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+ "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
+ },
+ "moment-timezone": {
+ "version": "0.5.31",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
+ "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "nan": {
+ "version": "2.13.2",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
+ "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw=="
+ },
+ "needle": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
+ "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==",
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ }
+ }
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node-emoji": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz",
+ "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==",
+ "dev": true,
+ "requires": {
+ "lodash.toarray": "^4.4.0"
+ }
+ },
+ "node-environment-flags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
+ "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
+ "dev": true,
+ "requires": {
+ "object.getownpropertydescriptors": "^2.0.3",
+ "semver": "^5.7.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "dev": true
+ }
+ }
+ },
+ "node-notifier": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz",
+ "integrity": "sha1-BW0UJE89zBzq3+aK+c/wxUc6M/M=",
+ "dev": true,
+ "requires": {
+ "cli-usage": "^0.1.1",
+ "growly": "^1.2.0",
+ "lodash.clonedeep": "^3.0.0",
+ "minimist": "^1.1.1",
+ "semver": "^5.1.0",
+ "shellwords": "^0.1.0",
+ "which": "^1.0.5"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz",
+ "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==",
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+ "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
+ "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g=="
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz",
+ "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==",
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.1"
+ }
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "packet-reader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
+ "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pathval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+ "dev": true
+ },
+ "pg": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-7.9.0.tgz",
+ "integrity": "sha512-GkzteBFpsIoIBCSuomqik3IGvhqAtTr32jclR24RmUg170Jrn6ypwR97YalFHrsE1iaW8T0aAH13dmij8QUQ0g==",
+ "requires": {
+ "buffer-writer": "2.0.0",
+ "packet-reader": "1.0.0",
+ "pg-connection-string": "0.1.3",
+ "pg-pool": "^2.0.4",
+ "pg-types": "~2.0.0",
+ "pgpass": "1.x",
+ "semver": "4.3.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
+ "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
+ }
+ }
+ },
+ "pg-connection-string": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
+ "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
+ },
+ "pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
+ },
+ "pg-pool": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz",
+ "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g=="
+ },
+ "pg-types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.0.tgz",
+ "integrity": "sha512-THUD7gQll5tys+5eQ8Rvs7DjHiIC3bLqixk3gMN9Hu8UrCBAOjf35FoI39rTGGc3lM2HU/R+Knpxvd11mCwOMA==",
+ "requires": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.0",
+ "postgres-interval": "^1.1.0"
+ }
+ },
+ "pgpass": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz",
+ "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
+ "requires": {
+ "split": "^1.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
+ },
+ "postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
+ },
+ "postgres-date": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz",
+ "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g="
+ },
+ "postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "requires": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+ },
+ "proxy-addr": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+ "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.8.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "raw-body": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+ "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.3",
+ "iconv-lite": "0.4.23",
+ "unpipe": "1.0.0"
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "redeyed": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
+ "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=",
+ "dev": true,
+ "requires": {
+ "esprima": "~4.0.0"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
+ "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "retry-as-promised": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz",
+ "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==",
+ "requires": {
+ "any-promise": "^1.3.0"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sax": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
+ },
+ "send": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+ "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.0",
+ "statuses": "~1.4.0"
+ }
+ },
+ "sequelize": {
+ "version": "5.22.3",
+ "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.3.tgz",
+ "integrity": "sha512-+nxf4TzdrB+PRmoWhR05TP9ukLAurK7qtKcIFv5Vhxm5Z9v+d2PcTT6Ea3YAoIQVkZ47QlT9XWAIUevMT/3l8Q==",
+ "requires": {
+ "bluebird": "^3.5.0",
+ "cls-bluebird": "^2.1.0",
+ "debug": "^4.1.1",
+ "dottie": "^2.0.0",
+ "inflection": "1.12.0",
+ "lodash": "^4.17.15",
+ "moment": "^2.24.0",
+ "moment-timezone": "^0.5.21",
+ "retry-as-promised": "^3.2.0",
+ "semver": "^6.3.0",
+ "sequelize-pool": "^2.3.0",
+ "toposort-class": "^1.0.1",
+ "uuid": "^3.3.3",
+ "validator": "^10.11.0",
+ "wkx": "^0.4.8"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "lodash": {
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ }
+ }
+ },
+ "sequelize-pool": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
+ "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
+ },
+ "sequelize-typescript": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-0.6.9.tgz",
+ "integrity": "sha512-8A5gi8BpKx4Gk9BjD3Dxrv7Ps/7PpZuYfoVkQXNMuL9a4M2d2fKZiBLurSA/5KmNgdVrLKKRkyJxghBpFR7tNg==",
+ "requires": {
+ "@types/bluebird": "3.5.26",
+ "@types/node": "11.12.2",
+ "@types/sequelize": "4.27.46",
+ "es6-shim": "0.35.3",
+ "glob": "7.1.2"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "11.12.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.12.2.tgz",
+ "integrity": "sha512-c82MtnqWB/CqqK7/zit74Ob8H1dBdV7bK+BcErwtXbe0+nUGkgzq5NTDmRW/pAv2lFtmeNmW95b0zK2hxpeklg=="
+ },
+ "@types/sequelize": {
+ "version": "4.27.46",
+ "resolved": "https://registry.npmjs.org/@types/sequelize/-/sequelize-4.27.46.tgz",
+ "integrity": "sha512-hqosowwLJsLrR+A8IOVgGQaToaBAZE54WLJmjxARaoHC4hl4lmfzXPNY/JGn3hmxNIhb6klHs7skQ2uJPrlXSA==",
+ "requires": {
+ "@types/bluebird": "*",
+ "@types/continuation-local-storage": "*",
+ "@types/lodash": "*",
+ "@types/validator": "*"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.2",
+ "send": "0.16.2"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true
+ },
+ "shimmer": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
+ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "source-map-support": {
+ "version": "0.5.11",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz",
+ "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz",
+ "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==",
+ "dev": true
+ },
+ "split": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
+ "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+ "requires": {
+ "through": "2"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+ },
+ "superagent": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
+ "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "^1.2.0",
+ "cookiejar": "^2.1.0",
+ "debug": "^3.1.0",
+ "extend": "^3.0.0",
+ "form-data": "^2.3.1",
+ "formidable": "^1.2.0",
+ "methods": "^1.1.1",
+ "mime": "^1.4.1",
+ "qs": "^6.5.1",
+ "readable-stream": "^2.3.5"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "supports-hyperlinks": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz",
+ "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^2.0.0",
+ "supports-color": "^5.0.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "tar": {
+ "version": "4.4.10",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz",
+ "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.5",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "toposort-class": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
+ "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "ts-node": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.3.tgz",
+ "integrity": "sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA==",
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^3.1.0",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^3.0.0"
+ }
+ },
+ "ts-node-dev": {
+ "version": "1.0.0-pre.32",
+ "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.0.0-pre.32.tgz",
+ "integrity": "sha512-hOy2mp5ncnKAJFjuQtfHOk6tqG7FfTnuARDsV5WGSQz0ldPG9iTQLbDn+q2wwNuvjbCfsAeGWwDMJc/73EraPQ==",
+ "dev": true,
+ "requires": {
+ "dateformat": "~1.0.4-1.2.3",
+ "dynamic-dedupe": "^0.3.0",
+ "filewatcher": "~3.0.0",
+ "minimist": "^1.1.3",
+ "mkdirp": "^0.5.1",
+ "node-notifier": "^4.0.2",
+ "resolve": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "ts-node": "*",
+ "tsconfig": "^7.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "tsconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+ "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+ "dev": true,
+ "requires": {
+ "@types/strip-bom": "^3.0.0",
+ "@types/strip-json-comments": "0.0.30",
+ "strip-bom": "^3.0.0",
+ "strip-json-comments": "^2.0.0"
+ },
+ "dependencies": {
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+ },
+ "tslint": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz",
+ "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.22.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.7.0",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.16",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+ "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.18"
+ }
+ },
+ "typescript": {
+ "version": "3.3.4000",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz",
+ "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "url": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
+ "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wkx": {
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz",
+ "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "xml2js": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
+ "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~9.0.1"
+ }
+ },
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
+ },
+ "yargs": {
+ "version": "13.2.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
+ "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
+ "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ }
+ }
+ },
+ "yargs-unparser": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
+ "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
+ "dev": true,
+ "requires": {
+ "flat": "^4.1.0",
+ "lodash": "^4.17.11",
+ "yargs": "^12.0.5"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "yn": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz",
+ "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q=="
+ }
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/package.json b/project3-microservices-udagram/udacity-c3-restapi-feed/package.json
new file mode 100644
index 0000000..5ece607
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "udacity-c2-restapi",
+ "version": "1.0.0",
+ "description": "",
+ "main": "server.js",
+ "scripts": {
+ "start": "node .",
+ "tsc": "tsc",
+ "dev": "ts-node-dev --respawn --transpileOnly ./src/server.ts",
+ "prod": "tsc && node ./www/server.js",
+ "clean": "rm -rf www/ || true",
+ "build": "npm run clean && tsc && cp -rf src/config www/config && cp .npmrc www/.npmrc && cp package.json www/package.json && cd www && zip -r Archive.zip . && cd ..",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "Gabriel Ruttner",
+ "license": "ISC",
+ "dependencies": {
+ "@sentry/node": "^5.17.0",
+ "@types/bcrypt": "^3.0.0",
+ "@types/jsonwebtoken": "^8.3.2",
+ "aws-sdk": "^2.697.0",
+ "bcrypt": "^3.0.6",
+ "body-parser": "^1.18.3",
+ "email-validator": "^2.0.4",
+ "express": "^4.16.4",
+ "jsonwebtoken": "^8.5.1",
+ "pg": "^7.9.0",
+ "reflect-metadata": "^0.1.13",
+ "sequelize": "^5.22.3",
+ "sequelize-typescript": "^0.6.9",
+ "ts-node": "^8.0.3"
+ },
+ "devDependencies": {
+ "@types/bluebird": "^3.5.26",
+ "@types/express": "^4.16.1",
+ "@types/node": "^11.11.6",
+ "@types/sequelize": "^4.27.44",
+ "@types/validator": "^10.9.0",
+ "chai": "^4.2.0",
+ "chai-http": "^4.2.1",
+ "mocha": "^6.1.4",
+ "ts-node-dev": "^1.0.0-pre.32",
+ "tslint": "^5.14.0",
+ "typescript": "^3.3.4000"
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/aws.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/aws.ts
new file mode 100644
index 0000000..90ae35e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/aws.ts
@@ -0,0 +1,66 @@
+import AWS = require('aws-sdk');
+import { config } from './config/config';
+
+const c = config.aws;
+
+//Configure AWS
+
+var credentials = new AWS.SharedIniFileCredentials({profile: c.aws_profile});
+AWS.config.credentials = credentials;
+
+// fixed "CredentialsError: Missing credentials in config"
+// https://stackoverflow.com/questions/26284181/aws-missing-credentials-when-i-try-send-something-to-my-s3-bucket-node-js
+AWS.config.update({
+ accessKeyId: c.aws_access_key_id,
+ secretAccessKey: c.aws_secret_access_key,
+ region: c.aws_region
+}); // for simplicity. In prod, use loadConfigFromFile, or env variables
+
+export const s3 = new AWS.S3({
+ signatureVersion: 'v4',
+ region: c.aws_region,
+ params: {Bucket: c.aws_media_bucket}
+});
+
+
+/* getGetSignedUrl generates an aws signed url to retreive an item
+ * @Params
+ * key: string - the filename to be put into the s3 bucket
+ * @Returns:
+ * a url as a string
+ */
+export function getGetSignedUrl( key: string ): string{
+ console.info('Processing getGetSignedUrl for ', key);
+ const signedUrlExpireSeconds = 60 * 5
+
+ const url = s3.getSignedUrl('getObject', {
+ Bucket: c.aws_media_bucket,
+ Key: key,
+ Expires: signedUrlExpireSeconds
+ });
+
+ return url;
+}
+
+/* getPutSignedUrl generates an aws signed url to put an item
+ * @Params
+ * key: string - the filename to be retreived from s3 bucket
+ * @Returns:
+ * a url as a string
+ */
+export async function getPutSignedUrl( key: string ): Promise {
+ console.info('Processing getPutSignedUrl for ', key);
+ const signedUrlExpireSeconds = 60 * 5
+
+ // fix "https://s3..amazonaws.com/" returned as a response
+ // see https://github.com/aws/aws-sdk-js/issues/2918
+ // https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md#25200
+ // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrlPromise-property
+ const url = await s3.getSignedUrlPromise('putObject', {
+ Bucket: c.aws_media_bucket,
+ Key: key,
+ Expires: signedUrlExpireSeconds
+ });
+
+ return url;
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/config/config.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/config/config.ts
new file mode 100644
index 0000000..8955dfb
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/config/config.ts
@@ -0,0 +1,24 @@
+export const config = {
+ "db": {
+ "username": process.env.DB_USERNAME,
+ "password": process.env.DB_PASSWORD,
+ "database": process.env.DB_NAME,
+ "host": process.env.DB_HOST
+ },
+ "aws": {
+ "aws_region": process.env.AWS_REGION,
+ "aws_profile": process.env.AWS_PROFILE,
+ "aws_media_bucket": process.env.AWS_MEDIA_BUCKET,
+ "aws_access_key_id": process.env.AWS_ACCESS_KEY_ID,
+ "aws_secret_access_key": process.env.AWS_SECRET_ACCESS_KEY
+ },
+ "jwt" : {
+ "secret" : process.env.JWT_SECRET
+ },
+ "cors" : {
+ "access_control_allow_origin": process.env.ACCESS_CONTROL_ALLOW_ORIGIN
+ },
+ "sentry" : {
+ "dsn" : process.env.SENTRY_DNS_FEED
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/models/FeedItem.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/models/FeedItem.ts
new file mode 100644
index 0000000..afed7ea
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/models/FeedItem.ts
@@ -0,0 +1,18 @@
+import {Table, Column, Model, HasMany, PrimaryKey, CreatedAt, UpdatedAt, ForeignKey} from 'sequelize-typescript';
+
+@Table
+export class FeedItem extends Model {
+ @Column
+ public caption!: string;
+
+ @Column
+ public url!: string;
+
+ @Column
+ @CreatedAt
+ public createdAt: Date = new Date();
+
+ @Column
+ @UpdatedAt
+ public updatedAt: Date = new Date();
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/routes/feed.router.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/routes/feed.router.ts
new file mode 100644
index 0000000..15450a6
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/feed/routes/feed.router.ts
@@ -0,0 +1,99 @@
+import { Router, Request, Response } from 'express';
+import { FeedItem } from '../models/FeedItem';
+import * as AWS from '../../../../aws';
+
+const router: Router = Router();
+
+// Get all feed items
+router.get('/', async (req: Request, res: Response) => {
+ console.info('Processing feed request GET /', req.params, req.body);
+ const items = await FeedItem.findAndCountAll({ order: [['id', 'DESC']] });
+ items.rows.map((item) => {
+ if (item.url) {
+ item.url = AWS.getGetSignedUrl(item.url);
+ }
+ });
+ res.send(items);
+});
+
+// Endpoint to GET a specific resource by Primary Key
+// Get all feed items
+router.get('/:id', async (req: Request, res: Response) => {
+ let { id } = req.params;
+ console.info('Processing feed request GET /:id', req.params, req.body);
+ if (!id) {
+ return res.status(400)
+ .send(`id is required`);
+ }
+
+ const item = await FeedItem.findByPk(id);
+
+ res.send(item);
+});
+
+// update a specific resource
+router.patch('/:id',
+ async (req: Request, res: Response) => {
+ console.info('Processing feed request PATCH /:id', req.params, req.body);
+ let { id } = req.params;
+ console.log("PATCH FeedItem #" + id);
+
+ if (!id) {
+ return res.status(400)
+ .send(`id is required`);
+ }
+
+ let body = req.body;
+ console.log("body = " + JSON.stringify(body));
+
+ const item = await FeedItem.findByPk(id);
+ console.log("item found = " + item);
+
+ const result = item.update(body, {returning: true, where: id});
+ console.log("result = " + result);
+
+ res.send(result)
+ });
+
+
+// Get a signed url to put a new item in the bucket
+router.get('/signed-url/:fileName',
+ async (req: Request, res: Response) => {
+ console.info('Processing feed request GET /signed-url/:fileName', req.params, req.body);
+ let { fileName } = req.params;
+ const url = await AWS.getPutSignedUrl(fileName);
+ console.info('Processing feed request GET /signed-url/:fileName',", signed_url:", url);
+ res.status(201).send({ url: url });
+ });
+
+// Post meta data and the filename after a file is uploaded
+// NOTE the file name is they key name in the s3 bucket.
+// body : {caption: string, fileName: string};
+router.post('/',
+ async (req: Request, res: Response) => {
+ console.info('Processing feed request POST /', req.params, req.body);
+ const caption = req.body.caption;
+ const fileName = req.body.url;
+
+ // check Caption is valid
+ if (!caption) {
+ return res.status(400).send({ message: 'Caption is required or malformed' });
+ }
+
+ // check Filename is valid
+ if (!fileName) {
+ return res.status(400).send({ message: 'File url is required' });
+ }
+
+ const item = await new FeedItem({
+ caption: caption,
+ url: fileName
+ });
+
+ const saved_item = await item.save();
+
+ saved_item.url = AWS.getGetSignedUrl(saved_item.url);
+ res.status(201).send(saved_item);
+ });
+
+export const FeedRouter: Router = router;
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/index.router.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/index.router.ts
new file mode 100644
index 0000000..92d710f
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/index.router.ts
@@ -0,0 +1,12 @@
+import { Router, Request, Response } from 'express';
+import { FeedRouter } from './feed/routes/feed.router';
+
+const router: Router = Router();
+
+router.use('/feed', FeedRouter);
+
+router.get('/', async (req: Request, res: Response) => {
+ res.send(`V0`);
+});
+
+export const IndexRouter: Router = router;
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/model.index.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/model.index.ts
new file mode 100644
index 0000000..95b9dc6
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/controllers/v0/model.index.ts
@@ -0,0 +1,3 @@
+import { FeedItem } from './feed/models/FeedItem';
+
+export const V0MODELS = [ FeedItem ];
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190325-create-feed-item.js b/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190325-create-feed-item.js
new file mode 100644
index 0000000..1f3c0e7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190325-create-feed-item.js
@@ -0,0 +1,30 @@
+'use strict';
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('FeedItem', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ caption: {
+ type: Sequelize.STRING
+ },
+ url: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ });
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('FeedItem');
+ }
+};
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190328-create-user.js b/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190328-create-user.js
new file mode 100644
index 0000000..c40e8b6
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/migrations/20190328-create-user.js
@@ -0,0 +1,30 @@
+'use strict';
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('User', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ type: Sequelize.INTEGER
+ },
+ email: {
+ type: Sequelize.STRING,
+ primaryKey: true
+ },
+ password_hash: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ });
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('User');
+ }
+};
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/sequelize.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/sequelize.ts
new file mode 100644
index 0000000..da3255a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/sequelize.ts
@@ -0,0 +1,17 @@
+import {Sequelize} from 'sequelize-typescript';
+import { config } from './config/config';
+
+
+const c = config.db;
+
+// Instantiate new Sequelize instance!
+export const sequelize = new Sequelize({
+ "username": c.username,
+ "password": c.password,
+ "database": c.database,
+ "host": c.host,
+
+ dialect: 'postgres',
+ storage: ':memory:',
+});
+
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/src/server.ts b/project3-microservices-udagram/udacity-c3-restapi-feed/src/server.ts
new file mode 100644
index 0000000..bc68791
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/src/server.ts
@@ -0,0 +1,46 @@
+import express from 'express';
+import { sequelize } from './sequelize';
+
+import { IndexRouter } from './controllers/v0/index.router';
+
+import bodyParser from 'body-parser';
+
+import { V0MODELS } from './controllers/v0/model.index';
+
+import { config } from './config/config';
+
+// Sentry: automatically catch errors and provide a stack trace to developers so we can quickly find and fix bugs
+import * as Sentry from '@sentry/node';
+
+(async () => {
+ await sequelize.addModels(V0MODELS);
+ await sequelize.sync();
+
+ Sentry.init({ dsn: config.sentry.dsn });
+
+ const app = express();
+ const port = process.env.PORT_FEED_SERVICE || 8080; // default port to listen
+
+ app.use(bodyParser.json());
+
+ //CORS Should be restricted
+ app.use(function(req, res, next) {
+ res.header("Access-Control-Allow-Origin", config.cors.access_control_allow_origin);
+ res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
+ next();
+ });
+
+ app.use('/api/v0/', IndexRouter)
+
+ // Root URI call
+ app.get( "/", async ( req, res ) => {
+ res.send( "/api/v0/" );
+ } );
+
+
+ // Start the Server
+ app.listen( port, () => {
+ console.log( `server running http://localhost:${ port }` );
+ console.log( `press CTRL+C to stop server` );
+ } );
+})();
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/tsconfig.json b/project3-microservices-udagram/udacity-c3-restapi-feed/tsconfig.json
new file mode 100644
index 0000000..92fd0f5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/tsconfig.json
@@ -0,0 +1,67 @@
+{
+ "compilerOptions": {
+ /* Basic Options */
+ "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
+ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+ // "lib": [], /* Specify library files to be included in the compilation. */
+ // "allowJs": true, /* Allow javascript files to be compiled. */
+ // "checkJs": true, /* Report errors in .js files. */
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+ // "declaration": true, /* Generates corresponding '.d.ts' file. */
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
+ "sourceMap": true, /* Generates corresponding '.map' file. */
+ // "outFile": "./", /* Concatenate and emit output to single file. */
+ "outDir": "./www", /* Redirect output structure to the directory. */
+ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+ // "composite": true, /* Enable project compilation */
+ // "removeComments": true, /* Do not emit comments to output. */
+ // "noEmit": true, /* Do not emit outputs. */
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+ /* Strict Type-Checking Options */
+ "strict": true, /* Enable all strict type-checking options. */
+ "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
+ "strictNullChecks": false, /* Enable strict null checks. */
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
+
+ /* Additional Checks */
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+
+ /* Module Resolution Options */
+ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+ "baseUrl": "/", /* Base directory to resolve non-absolute module names. */
+ "paths": {
+ "*": [
+ "node_modules/*"
+ ]
+ }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
+ // "typeRoots": [], /* List of folders to include type definitions from. */
+ // "types": [], /* Type declaration files to be included in compilation. */
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
+
+ /* Source Map Options */
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+ /* Experimental Options */
+ "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/tslint.json b/project3-microservices-udagram/udacity-c3-restapi-feed/tslint.json
new file mode 100644
index 0000000..05e6a30
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/tslint.json
@@ -0,0 +1,139 @@
+{
+ "rulesDirectory": [
+ "node_modules/codelyzer"
+ ],
+ "rules": {
+ "arrow-return-shorthand": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "deprecation": {
+ "severity": "warn"
+ },
+ "eofline": true,
+ "forin": true,
+ "import-spacing": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "interface-over-type-literal": true,
+ "label-position": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-empty": false,
+ "no-empty-interface": true,
+ "no-eval": true,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-misused-new": true,
+ "no-non-null-assertion": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-string-throw": true,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-initializer": true,
+ "no-unused-expression": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "prefer-const": true,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "unified-signatures": true,
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "page",
+ "kebab-case"
+ ],
+ "no-output-on-prefix": true,
+ "use-input-property-decorator": true,
+ "use-output-property-decorator": true,
+ "use-host-property-decorator": true,
+ "no-input-rename": true,
+ "no-output-rename": true,
+ "use-life-cycle-interface": true,
+ "use-pipe-transform-interface": true,
+ "directive-class-suffix": true
+ }
+ }
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-feed/udacity-c3-restapi.postman_collection.json b/project3-microservices-udagram/udacity-c3-restapi-feed/udacity-c3-restapi.postman_collection.json
new file mode 100644
index 0000000..ddf94c9
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-feed/udacity-c3-restapi.postman_collection.json
@@ -0,0 +1,870 @@
+{
+ "info": {
+ "_postman_id": "ab6a67e0-1406-4a1b-aee8-a40906e123a2",
+ "name": "udacity-c2-restapi",
+ "description": "Requests that should work!",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "Public",
+ "item": [
+ {
+ "name": "/api/v0/feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "1ca4d5f0-f73c-4d7e-95d1-4f97bf49369d",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"The count is equal to the number of items rx\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.count).to.eql(jsonData.rows.length);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 600ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(600);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Get all the items in the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed/:id",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "0f86726d-0a45-463c-a775-e34430735155",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ },
+ "description": "Request a specific feed item detail"
+ },
+ "response": [
+ {
+ "name": "/api/v0/feed/:id",
+ "originalRequest": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ }
+ },
+ "status": "OK",
+ "code": 200,
+ "_postman_previewlanguage": "json",
+ "header": [
+ {
+ "key": "X-Powered-By",
+ "value": "Express"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json; charset=utf-8"
+ },
+ {
+ "key": "Content-Length",
+ "value": "133"
+ },
+ {
+ "key": "ETag",
+ "value": "W/\"85-gic7UchUXbyxmSqNsq7nx4+Eaas\""
+ },
+ {
+ "key": "Date",
+ "value": "Tue, 26 Mar 2019 15:07:32 GMT"
+ },
+ {
+ "key": "Connection",
+ "value": "keep-alive"
+ }
+ ],
+ "cookie": [],
+ "body": "{\n \"id\": 3,\n \"caption\": \"hello0.5278862272947393\",\n \"url\": null,\n \"createdAt\": \"2019-03-26T14:16:58.442Z\",\n \"updatedAt\": \"2019-03-26T14:16:58.443Z\"\n}"
+ }
+ ]
+ },
+ {
+ "name": "/api/v0/feed/:id",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "671b15c9-4498-413f-b7e2-3a5bec6ca0f4",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n\t\"id\": 3,\r\n \"caption\": \"GoodbyeUPDATEDBIS\",\r\n \"url\": \"test.jpg\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed/2",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ "2"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ]
+ },
+ "description": "Request a specific feed item detail"
+ },
+ "response": [
+ {
+ "name": "/api/v0/feed/:id",
+ "originalRequest": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ }
+ },
+ "status": "OK",
+ "code": 200,
+ "_postman_previewlanguage": "json",
+ "header": [
+ {
+ "key": "X-Powered-By",
+ "value": "Express"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json; charset=utf-8"
+ },
+ {
+ "key": "Content-Length",
+ "value": "133"
+ },
+ {
+ "key": "ETag",
+ "value": "W/\"85-gic7UchUXbyxmSqNsq7nx4+Eaas\""
+ },
+ {
+ "key": "Date",
+ "value": "Tue, 26 Mar 2019 15:07:32 GMT"
+ },
+ {
+ "key": "Connection",
+ "value": "keep-alive"
+ }
+ ],
+ "cookie": [],
+ "body": "{\n \"id\": 3,\n \"caption\": \"hello0.5278862272947393\",\n \"url\": null,\n \"createdAt\": \"2019-03-26T14:16:58.442Z\",\n \"updatedAt\": \"2019-03-26T14:16:58.443Z\"\n}"
+ }
+ ]
+ },
+ {
+ "name": "/api/v0/user/auth valid registration",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "e43fba10-e5c3-48c5-912c-4e954ad6366e",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n\t\"email\":\"hello@gmail.com\",\n\t\"password\":\"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth invalid registration",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "ec80bf59-c7e1-47e8-89ef-da5e8cf8a088",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"auth is false and a message is included in the error body\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ " pm.expect(jsonData.message).to.not.eql(null)",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"password\": \"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth/login valid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "680c7fcc-7e63-424f-af32-9aaa629b44d6",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"body includes an email and token\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.auth).to.eql(true);",
+ " pm.expect(jsonData.user).to.not.eql(null);",
+ " pm.expect(jsonData.token).to.not.eql(null)",
+ " ",
+ " pm.environment.set(\"token\", jsonData.token);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 500ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(500);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n\t\"email\":\"hello@gmail.com\",\n\t\"password\":\"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth/login",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth",
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth/login invalid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "4460e048-e276-4ce1-90de-590e2bd97d8a",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"auth is false and a message is included in the error body\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ " pm.expect(jsonData.message).to.not.eql(null)",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth/login",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth",
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "upload file with the generated aws signed-url",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "PUT",
+ "header": [],
+ "body": {
+ "mode": "file",
+ "file": {
+ "src": "/P:/personnel/pollux.png"
+ }
+ },
+ "url": {
+ "raw": "https://udagram-kjm-dev.s3.eu-west-3.amazonaws.com/pollux.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZISZGJJ7POB32J6L%2F20200603%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20200603T144712Z&X-Amz-Expires=300&X-Amz-Signature=4e5a7b5ca3c4eee63d5abdccad782e91f0df0f52620e5b1be30912c82c50f7de&X-Amz-SignedHeaders=host",
+ "protocol": "https",
+ "host": [
+ "udagram-kjm-dev",
+ "s3",
+ "eu-west-3",
+ "amazonaws",
+ "com"
+ ],
+ "path": [
+ "pollux.png"
+ ],
+ "query": [
+ {
+ "key": "X-Amz-Algorithm",
+ "value": "AWS4-HMAC-SHA256"
+ },
+ {
+ "key": "X-Amz-Credential",
+ "value": "AKIAZISZGJJ7POB32J6L%2F20200603%2Feu-west-3%2Fs3%2Faws4_request"
+ },
+ {
+ "key": "X-Amz-Date",
+ "value": "20200603T144712Z"
+ },
+ {
+ "key": "X-Amz-Expires",
+ "value": "300"
+ },
+ {
+ "key": "X-Amz-Signature",
+ "value": "4e5a7b5ca3c4eee63d5abdccad782e91f0df0f52620e5b1be30912c82c50f7de"
+ },
+ {
+ "key": "X-Amz-SignedHeaders",
+ "value": "host"
+ }
+ ]
+ },
+ "description": "Upload the file using the signed url received as a response to /feed/signed-url request"
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ },
+ {
+ "name": "Unauthorized",
+ "item": [
+ {
+ "name": "/api/v0/feed unauthorized",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "be0a08a6-209a-467f-8cf3-11702bb4a8df",
+ "exec": [
+ "pm.test(\"Status code is 401\", function () {",
+ " pm.response.to.have.status(401);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ },
+ {
+ "name": "Authorized",
+ "item": [
+ {
+ "name": "/api/v0/feed invalid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "34606858-be42-447e-a935-409a8e05d87f",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"body includes a message\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.message).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 500ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(500);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed authorized",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "b4a1781a-cb0d-462f-aab6-0ce88e96c2b2",
+ "exec": [
+ "pm.test(\"Status code is 201\", function () {",
+ " pm.response.to.have.status(201);",
+ "});",
+ "",
+ "pm.test(\"The post returns a new item with an id\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"caption\": \"Hello\",\n \"url\": \"test.jpg\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed/signed-url/:fileName",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "0f7ff773-58f0-47de-8657-a1fb7eb8311d",
+ "exec": [
+ "pm.test(\"Status code is 201\", function () {",
+ " pm.response.to.have.status(201);",
+ "});",
+ "",
+ "pm.test(\"The post returns a new item with an id\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"caption\": \"Hello\",\n \"url\": \"test.jpg\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed/signed-url/pollux.png",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ "signed-url",
+ "pollux.png"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ }
+ ],
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{token}}",
+ "type": "string"
+ }
+ ]
+ },
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "52aed6e2-667a-40ec-adc2-0a96307c5d33",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "f402b58e-86e1-4f42-ab30-5cd07b4822d4",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "protocolProfileBehavior": {}
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "5a019e7f-bc38-4ae8-9a8c-d64d79ad1903",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "7f504948-40fe-450d-8479-93ef51d1ee49",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "variable": [
+ {
+ "id": "3e3ea131-5328-4f50-8fe1-516e3995917d",
+ "key": "host",
+ "value": "http://localhost:8080",
+ "type": "string"
+ }
+ ],
+ "protocolProfileBehavior": {}
+}
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/.dockerignore b/project3-microservices-udagram/udacity-c3-restapi-user/.dockerignore
new file mode 100644
index 0000000..5171c54
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/.dockerignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/.gitignore b/project3-microservices-udagram/udacity-c3-restapi-user/.gitignore
new file mode 100644
index 0000000..46b3664
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/.gitignore
@@ -0,0 +1,42 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+*~
+*.sw[mnpcod]
+*.log
+*.tmp
+*.tmp.*
+log.txt
+*.sublime-project
+*.sublime-workspace
+.vscode/
+npm-debug.log*
+
+.idea/
+.ionic/
+.sourcemaps/
+.sass-cache/
+.tmp/
+.versions/
+coverage/
+www/
+node_modules/
+tmp/
+temp/
+platforms/
+plugins/
+plugins/android.json
+plugins/ios.json
+$RECYCLE.BIN/
+postgres_dev/
+logfile
+
+.DS_Store
+Thumbs.db
+UserInterfaceState.xcuserstate
+node_modules
+venv/
+# Elastic Beanstalk Files
+.elasticbeanstalk/*
+!.elasticbeanstalk/*.cfg.yml
+!.elasticbeanstalk/*.global.yml
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/.npmrc b/project3-microservices-udagram/udacity-c3-restapi-user/.npmrc
new file mode 100644
index 0000000..3364a17
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/.npmrc
@@ -0,0 +1 @@
+unsafe-perm=true
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/Dockerfile b/project3-microservices-udagram/udacity-c3-restapi-user/Dockerfile
new file mode 100644
index 0000000..b657653
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/Dockerfile
@@ -0,0 +1,11 @@
+# latest LTS (long term support) version 12 of node available from the Docker hub
+FROM node:12
+# Create app directory
+WORKDIR /usr/src/app
+# Bundle app source
+COPY . .
+RUN npm install
+# If you are building your code for production
+# RUN npm ci --only=production
+EXPOSE 8080
+CMD [ "npm", "run", "prod" ]
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/README.md b/project3-microservices-udagram/udacity-c3-restapi-user/README.md
new file mode 100644
index 0000000..163296f
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/README.md
@@ -0,0 +1,58 @@
+# Udagram REST API
+
+Udagram is a simple cloud application developed alongside the Udacity Cloud Engineering Nanodegree. It allows users to register and log into a web client, post photos to the feed, and process photos using an image filtering microservice.
+
+The project is split into three parts:
+
+1. [The Simple Frontend](../udacity-c2-frontend)
+A basic Ionic client web application which consumes the RestAPI Backend.
+2. [The RestAPI Backend](.), a Node-Express server which can be deployed to a cloud service.
+3. [The Image Filtering Microservice](../../../project2-image-filter), the final project for the course. It is a Node-Express application which runs a simple script to process images.
+
+***
+
+## Getting Setup
+
+### Installing project dependencies
+
+This project uses NPM to manage software dependencies. NPM Relies on the package.json file located in the root of this repository. After cloning, open your terminal and run:
+
+```bash
+npm install
+```
+
+>_tip_: **npm i** is shorthand for **npm install**
+
+### Installing useful tools
+
+#### 1. [Postbird](https://github.com/paxa/postbird)
+
+Postbird is a useful client GUI (graphical user interface) to interact with our provisioned Postgres database. We can establish a remote connection and complete actions like viewing data and changing schema (tables, columns, ect).
+
+#### 2. [Postman](https://www.getpostman.com/downloads/)
+
+Postman is a useful tool to issue and save requests. Postman can create GET, PUT, POST, etc. requests complete with bodies. It can also be used to test endpoints automatically. We've included a collection (`./udacity-c2-restapi.postman_collection.json`) which contains example requsts.
+
+***
+
+## Running the Server Locally
+
+To run the server locally in developer mode, open terminal and run:
+
+```bash
+npm run dev
+```
+
+Developer mode runs off the TypeScript source. Any saves will reset the server and run the latest version of the codebase.
+
+## Build & run docker image
+
+### Build your image
+
+`docker build -t kendyjm/udacity-restapi-user .`
+Replace {dockerid} with your docker user's id.
+The -t flag lets you tag your image so it's easier to find later using the docker images command.
+
+### Run your image
+
+`docker run --rm --publish 8080:8080 -v "%userprofile%\.aws:/root/.aws" --env DB_USERNAME=%DB_USERNAME% --env DB_PASSWORD=%DB_PASSWORD% --env DB_NAME=%DB_NAME% --env DB_HOST=%DB_HOST% --env AWS_REGION=%AWS_REGION% --env AWS_PROFILE=%AWS_PROFILE% --env AWS_MEDIA_BUCKET=%AWS_MEDIA_BUCKET% --env AWS_ACCESS_KEY_ID=%AWS_ACCESS_KEY_ID% --env AWS_SECRET_ACCESS_KEY=%AWS_SECRET_ACCESS_KEY% --env JWT_SECRET=%JWT_SECRET% --env ACCESS_CONTROL_ALLOW_ORIGIN=%ACCESS_CONTROL_ALLOW_ORIGIN% --env SENTRY_DNS=%SENTRY_DNS% --env IMAGEFILTER_SENTRY_DNS=%IMAGEFILTER_SENTRY_DNS% --env IMAGEFILTER_MORGAN_FORMAT="%IMAGEFILTER_MORGAN_FORMAT%" --env SENTRY_DNS_FEED=%SENTRY_DNS_FEED% --env SENTRY_DNS_USER=%SENTRY_DNS_USER% --env PORT_FEED_SERVICE=8080 --env PORT_USER_SERVICE=8080 --name feed kendyjm/udacity-restapi-user`
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander0.jpg b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander0.jpg
new file mode 100644
index 0000000..751c171
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander0.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander1.jpg b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander1.jpg
new file mode 100644
index 0000000..75ab66d
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander1.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander2.jpg b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander2.jpg
new file mode 100644
index 0000000..326fbed
Binary files /dev/null and b/project3-microservices-udagram/udacity-c3-restapi-user/mock/xander2.jpg differ
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/package-lock.json b/project3-microservices-udagram/udacity-c3-restapi-user/package-lock.json
new file mode 100644
index 0000000..961efe8
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/package-lock.json
@@ -0,0 +1,3234 @@
+{
+ "name": "udacity-c2-restapi",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+ "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.0.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
+ "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@sentry/apm": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/apm/-/apm-5.17.0.tgz",
+ "integrity": "sha512-raJcPa04TP8mVocSTHe0PdULpRWhw0NaLq9Rk8KCTFBJvLsgzY2krph5/LgEfBBX78vWt70FrwSw+DdIfYIJ6g==",
+ "requires": {
+ "@sentry/browser": "5.17.0",
+ "@sentry/hub": "5.17.0",
+ "@sentry/minimal": "5.17.0",
+ "@sentry/types": "5.17.0",
+ "@sentry/utils": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/browser": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.17.0.tgz",
+ "integrity": "sha512-++pXpCHtdek1cRUwVeLvlxUJ2w1s+eiC9qN1N+7+HdAjHpBz2/tA1sKBCqwwVQZ490Cf2GLll9Ao7fuPPmveRQ==",
+ "requires": {
+ "@sentry/core": "5.17.0",
+ "@sentry/types": "5.17.0",
+ "@sentry/utils": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/core": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.17.0.tgz",
+ "integrity": "sha512-Kfx4rGKDC7V1YJjTGJXyl12VVHxM8Cjpu61YOyF8kXoXXg9u06C3n0G1dmfzLQERKXasUVMtXRBdKx/OjYpl1g==",
+ "requires": {
+ "@sentry/hub": "5.17.0",
+ "@sentry/minimal": "5.17.0",
+ "@sentry/types": "5.17.0",
+ "@sentry/utils": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/hub": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.17.0.tgz",
+ "integrity": "sha512-lyUbEmshwaMYdAzy4iwgizgvKODVVloB2trnefpq90AuWCdvzcxMLIGULx1ou+KohccqdNorYICKWeuRscKq5A==",
+ "requires": {
+ "@sentry/types": "5.17.0",
+ "@sentry/utils": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/minimal": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.17.0.tgz",
+ "integrity": "sha512-v8xfkySXKrliZO6er6evlVe/ViUcqN0O8BhGyauK28Mf+KnKEOs5W6oWbt4qCDIttw9ynKIYyRrkAl/9oUR76A==",
+ "requires": {
+ "@sentry/hub": "5.17.0",
+ "@sentry/types": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@sentry/node": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.17.0.tgz",
+ "integrity": "sha512-gaM+LNjQc7Wm+RG4f7KGZ/+An8RQ9/8CkJDB/DP4qwufsaIrcg1dZa6KeAUnh3KaXZ+ZuPji+agCIV/AQU4x8g==",
+ "requires": {
+ "@sentry/apm": "5.17.0",
+ "@sentry/core": "5.17.0",
+ "@sentry/hub": "5.17.0",
+ "@sentry/types": "5.17.0",
+ "@sentry/utils": "5.17.0",
+ "cookie": "^0.3.1",
+ "https-proxy-agent": "^4.0.0",
+ "lru_map": "^0.3.3",
+ "tslib": "^1.9.3"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ }
+ }
+ },
+ "@sentry/types": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.17.0.tgz",
+ "integrity": "sha512-1z8EXzvg8GcsBNnSXgB5/G7mz2PwmMt9mjOrVG1jhtSGH1c7WvB32F5boqoMcjIJmy5MrBGaaXwrF/RRJrwUQg=="
+ },
+ "@sentry/utils": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.17.0.tgz",
+ "integrity": "sha512-qn8WgZcSkV/rx0ezp9q/xFjP7aMaYZO1/JYLXV4o6pYrQ9tvMmmwAZT39FpJunhhbkR36WNEuRB9C2K250cb/A==",
+ "requires": {
+ "@sentry/types": "5.17.0",
+ "tslib": "^1.9.3"
+ }
+ },
+ "@types/bcrypt": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-3.0.0.tgz",
+ "integrity": "sha512-nohgNyv+1ViVcubKBh0+XiNJ3dO8nYu///9aJ4cgSqv70gBL+94SNy/iC2NLzKPT2Zt/QavrOkBVbZRLZmw6NQ==",
+ "dev": true
+ },
+ "@types/bluebird": {
+ "version": "3.5.27",
+ "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.27.tgz",
+ "integrity": "sha512-6BmYWSBea18+tSjjSC3QIyV93ZKAeNWGM7R6aYt1ryTZXrlHF+QLV0G2yV0viEGVyRkyQsWfMoJ0k/YghBX5sQ==",
+ "dev": true
+ },
+ "@types/body-parser": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz",
+ "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
+ "dev": true,
+ "requires": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/chai": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz",
+ "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==",
+ "dev": true
+ },
+ "@types/connect": {
+ "version": "3.4.32",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
+ "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/continuation-local-storage": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz",
+ "integrity": "sha1-oz4N+dzptCTRyY/E/evYV43O7H4=",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/cookiejar": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz",
+ "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==",
+ "dev": true
+ },
+ "@types/express": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.0.tgz",
+ "integrity": "sha512-CjaMu57cjgjuZbh9DpkloeGxV45CnMGlVd+XpG7Gm9QgVrd7KFq+X4HY0vM+2v0bczS48Wg7bvnMY5TN+Xmcfw==",
+ "dev": true,
+ "requires": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "@types/express-serve-static-core": {
+ "version": "4.16.7",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.7.tgz",
+ "integrity": "sha512-847KvL8Q1y3TtFLRTXcVakErLJQgdpFSaq+k043xefz9raEf0C7HalpSY7OW5PyjCnY8P7bPW5t/Co9qqp+USg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "@types/jsonwebtoken": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.2.tgz",
+ "integrity": "sha512-Mkjljd9DTpkPlrmGfTJvcP4aBU7yO2QmW7wNVhV4/6AEUxYoacqU7FJU/N0yFEHTsIrE4da3rUrjrR5ejicFmA==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/lodash": {
+ "version": "4.14.136",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.136.tgz",
+ "integrity": "sha512-0GJhzBdvsW2RUccNHOBkabI8HZVdOXmXbXhuKlDEd5Vv12P7oAVGfomGp3Ne21o5D/qu1WmthlNKFaoZJJeErA=="
+ },
+ "@types/mime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
+ "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "11.13.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.17.tgz",
+ "integrity": "sha512-7W3kSMa8diVH6s24a8Qrmvwu+vG3ahOC/flMHFdWSdnPYoQI0yPO84h5zOWYXAha2Npn3Pw3SSuQSwBUfaniyQ=="
+ },
+ "@types/range-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
+ "dev": true
+ },
+ "@types/sequelize": {
+ "version": "4.28.3",
+ "resolved": "https://registry.npmjs.org/@types/sequelize/-/sequelize-4.28.3.tgz",
+ "integrity": "sha512-Z+gbWsLmGnqnAz91I8Wtfbe+4D1aUyQ4aawYfohpvar4Azr8aSNwzS1rFQYO2dk6zcClt5k9n0qCek/YAq4WNw==",
+ "dev": true,
+ "requires": {
+ "@types/bluebird": "*",
+ "@types/continuation-local-storage": "*",
+ "@types/lodash": "*",
+ "@types/validator": "*"
+ }
+ },
+ "@types/serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==",
+ "dev": true,
+ "requires": {
+ "@types/express-serve-static-core": "*",
+ "@types/mime": "*"
+ }
+ },
+ "@types/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+ "dev": true
+ },
+ "@types/strip-json-comments": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "dev": true
+ },
+ "@types/superagent": {
+ "version": "3.8.7",
+ "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.8.7.tgz",
+ "integrity": "sha512-9KhCkyXv268A2nZ1Wvu7rQWM+BmdYUVkycFeNnYrUL5Zwu7o8wPQ3wBfW59dDP+wuoxw0ww8YKgTNv8j/cgscA==",
+ "dev": true,
+ "requires": {
+ "@types/cookiejar": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/validator": {
+ "version": "10.11.1",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.1.tgz",
+ "integrity": "sha512-bVhLqvb+5xUNWRFnuuecRVISTvsG6AdhrB2kb/tChgtuTTqARqlQ3rLhOPy8cINZEUB8PkR+goyWF6fWxg4iSw=="
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "agent-base": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
+ "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
+ },
+ "ansi-colors": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
+ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "arg": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
+ "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "aws-sdk": {
+ "version": "2.697.0",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.697.0.tgz",
+ "integrity": "sha512-aNrwiPRHQyzjJxpfgLwVOevuGTOMkU5uiP4VDIngfc/k4s2kQgLSyhLSKmNTjbubHCHfs1sQQkP3RXK2Oi8Rbw==",
+ "requires": {
+ "buffer": "4.9.2",
+ "events": "1.1.1",
+ "ieee754": "1.1.13",
+ "jmespath": "0.15.0",
+ "querystring": "0.2.0",
+ "sax": "1.2.1",
+ "url": "0.10.3",
+ "uuid": "3.3.2",
+ "xml2js": "0.4.19"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+ },
+ "bcrypt": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.8.tgz",
+ "integrity": "sha512-jKV6RvLhI36TQnPDvUFqBEnGX9c8dRRygKxCZu7E+MgLfKZbmmXL8a7/SFFOyHoPNX9nV81cKRC5tbQfvEQtpw==",
+ "requires": {
+ "nan": "2.14.0",
+ "node-pre-gyp": "0.14.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "buffer-writer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
+ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ }
+ }
+ },
+ "chai": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
+ "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "pathval": "^1.1.0",
+ "type-detect": "^4.0.5"
+ }
+ },
+ "chai-http": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.3.0.tgz",
+ "integrity": "sha512-zFTxlN7HLMv+7+SPXZdkd5wUlK+KxH6Q7bIEMiEx0FK3zuuMqL7cwICAQ0V1+yYRozBburYuxN1qZstgHpFZQg==",
+ "dev": true,
+ "requires": {
+ "@types/chai": "4",
+ "@types/superagent": "^3.8.3",
+ "cookiejar": "^2.1.1",
+ "is-ip": "^2.0.0",
+ "methods": "^1.1.2",
+ "qs": "^6.5.1",
+ "superagent": "^3.7.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "cls-bluebird": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
+ "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
+ "requires": {
+ "is-bluebird": "^1.0.2",
+ "shimmer": "^1.1.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "cookiejar": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
+ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "meow": "^3.3.0"
+ }
+ },
+ "debounce": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz",
+ "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "dottie": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz",
+ "integrity": "sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw=="
+ },
+ "dynamic-dedupe": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+ "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+ "dev": true,
+ "requires": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "email-validator": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz",
+ "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ=="
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-shim": {
+ "version": "0.35.3",
+ "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.3.tgz",
+ "integrity": "sha1-m/tzY/7//4emzbbNk+QF7DxLbyY="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "filewatcher": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/filewatcher/-/filewatcher-3.0.1.tgz",
+ "integrity": "sha1-9KGVc1Xdr0Q8zXiolfPVXiPIoDQ=",
+ "dev": true,
+ "requires": {
+ "debounce": "^1.0.0"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "flat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
+ "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "~2.0.3"
+ }
+ },
+ "form-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.0.tgz",
+ "integrity": "sha512-WXieX3G/8side6VIqx44ablyULoGruSde5PNTxoUyo5CeyAMX6nVWUd0rgist/EuX655cjhUhTo1Fo3tRYqbcA==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "formidable": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+ "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+ "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
+ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "https-proxy-agent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
+ "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
+ "requires": {
+ "agent-base": "5",
+ "debug": "4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+ "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inflection": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
+ "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bluebird": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
+ "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
+ },
+ "is-buffer": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+ "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz",
+ "integrity": "sha1-aO6gfooKCpTC0IDdZ0xzGrKkYas=",
+ "dev": true,
+ "requires": {
+ "ip-regex": "^2.0.0"
+ }
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "jmespath": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
+ "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.14",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
+ "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
+ },
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+ "dev": true
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+ "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+ "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "mocha": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz",
+ "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "3.2.3",
+ "browser-stdout": "1.3.1",
+ "debug": "3.2.6",
+ "diff": "3.5.0",
+ "escape-string-regexp": "1.0.5",
+ "find-up": "3.0.0",
+ "glob": "7.1.3",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "3.13.1",
+ "log-symbols": "2.2.0",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "ms": "2.1.1",
+ "node-environment-flags": "1.0.5",
+ "object.assign": "4.1.0",
+ "strip-json-comments": "2.0.1",
+ "supports-color": "6.0.0",
+ "which": "1.3.1",
+ "wide-align": "1.1.3",
+ "yargs": "13.2.2",
+ "yargs-parser": "13.0.0",
+ "yargs-unparser": "1.5.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ },
+ "moment-timezone": {
+ "version": "0.5.26",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz",
+ "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
+ },
+ "needle": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz",
+ "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==",
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ }
+ }
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node-environment-flags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
+ "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
+ "dev": true,
+ "requires": {
+ "object.getownpropertydescriptors": "^2.0.3",
+ "semver": "^5.7.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "dev": true
+ }
+ }
+ },
+ "node-notifier": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz",
+ "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==",
+ "dev": true,
+ "requires": {
+ "growly": "^1.3.0",
+ "is-wsl": "^1.1.0",
+ "semver": "^5.5.0",
+ "shellwords": "^0.1.1",
+ "which": "^1.3.0"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz",
+ "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
+ }
+ },
+ "nopt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+ "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+ "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+ },
+ "npm-packlist": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+ "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.1"
+ }
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "packet-reader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
+ "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pathval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+ "dev": true
+ },
+ "pg": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-7.11.0.tgz",
+ "integrity": "sha512-YO4V7vCmEMGoF390LJaFaohWNKaA2ayoQOEZmiHVcAUF+YsRThpf/TaKCgSvsSE7cDm37Q/Cy3Gz41xiX/XjTw==",
+ "requires": {
+ "buffer-writer": "2.0.0",
+ "packet-reader": "1.0.0",
+ "pg-connection-string": "0.1.3",
+ "pg-pool": "^2.0.4",
+ "pg-types": "~2.0.0",
+ "pgpass": "1.x",
+ "semver": "4.3.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
+ "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
+ }
+ }
+ },
+ "pg-connection-string": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
+ "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
+ },
+ "pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
+ },
+ "pg-pool": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz",
+ "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g=="
+ },
+ "pg-types": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.1.tgz",
+ "integrity": "sha512-b7y6QM1VF5nOeX9ukMQ0h8a9z89mojrBHXfJeSug4mhL0YpxNBm83ot2TROyoAmX/ZOX3UbwVO4EbH7i1ZZNiw==",
+ "requires": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ }
+ },
+ "pgpass": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz",
+ "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
+ "requires": {
+ "split": "^1.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
+ },
+ "postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
+ },
+ "postgres-date": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.4.tgz",
+ "integrity": "sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA=="
+ },
+ "postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "requires": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
+ "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "retry-as-promised": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz",
+ "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==",
+ "requires": {
+ "any-promise": "^1.3.0"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sax": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
+ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "sequelize": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.10.0.tgz",
+ "integrity": "sha512-hceVQKM9WmdB1aM+F+Ach8aZrU7RMyPeXFol7de0HRo+GkAqSl054WB4a00CRVnZ/73/EdpXRJMKNLIjraSmOg==",
+ "requires": {
+ "bluebird": "^3.5.0",
+ "cls-bluebird": "^2.1.0",
+ "debug": "^4.1.1",
+ "dottie": "^2.0.0",
+ "inflection": "1.12.0",
+ "lodash": "^4.17.11",
+ "moment": "^2.24.0",
+ "moment-timezone": "^0.5.21",
+ "retry-as-promised": "^3.1.0",
+ "semver": "^6.1.1",
+ "sequelize-pool": "^2.3.0",
+ "toposort-class": "^1.0.1",
+ "uuid": "^3.2.1",
+ "validator": "^10.11.0",
+ "wkx": "^0.4.6"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "semver": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
+ "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A=="
+ }
+ }
+ },
+ "sequelize-pool": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
+ "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
+ },
+ "sequelize-typescript": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-0.6.11.tgz",
+ "integrity": "sha512-O9Rmb9F+3Wsn5dkN6dJWSFGh8XUiSIteZsF7e95OdJG73f7KMoc+OTYzvtl/wDHA2HhdFqF9b6OzkxFFdaKVhw==",
+ "requires": {
+ "@types/bluebird": "3.5.26",
+ "@types/node": "11.12.2",
+ "@types/sequelize": "4.28.1",
+ "es6-shim": "0.35.3",
+ "glob": "7.1.2"
+ },
+ "dependencies": {
+ "@types/bluebird": {
+ "version": "3.5.26",
+ "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.26.tgz",
+ "integrity": "sha512-aj2mrBLn5ky0GmAg6IPXrQjnN0iB/ulozuJ+oZdrHRAzRbXjGmu4UXsNCjFvPbSaaPZmniocdOzsM392qLOlmQ=="
+ },
+ "@types/node": {
+ "version": "11.12.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.12.2.tgz",
+ "integrity": "sha512-c82MtnqWB/CqqK7/zit74Ob8H1dBdV7bK+BcErwtXbe0+nUGkgzq5NTDmRW/pAv2lFtmeNmW95b0zK2hxpeklg=="
+ },
+ "@types/sequelize": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/@types/sequelize/-/sequelize-4.28.1.tgz",
+ "integrity": "sha512-fitAlHqmoZ2rn7KJOo+1lF+uC7zeUSoW2kTiEaEzgVSFD03nPkkKIZss4XrL34KCn+7wtKvmBO1Kb6NCmLF1Fw==",
+ "requires": {
+ "@types/bluebird": "*",
+ "@types/continuation-local-storage": "*",
+ "@types/lodash": "*",
+ "@types/validator": "*"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true
+ },
+ "shimmer": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
+ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.12",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
+ "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "split": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
+ "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
+ "requires": {
+ "through": "2"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+ },
+ "superagent": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
+ "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "^1.2.0",
+ "cookiejar": "^2.1.0",
+ "debug": "^3.1.0",
+ "extend": "^3.0.0",
+ "form-data": "^2.3.1",
+ "formidable": "^1.2.0",
+ "methods": "^1.1.1",
+ "mime": "^1.4.1",
+ "qs": "^6.5.1",
+ "readable-stream": "^2.3.5"
+ }
+ },
+ "supports-color": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
+ "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "tar": {
+ "version": "4.4.13",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+ "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "toposort-class": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
+ "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
+ },
+ "tree-kill": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz",
+ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==",
+ "dev": true
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "ts-node": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.3.0.tgz",
+ "integrity": "sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^3.0.0"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
+ "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
+ "dev": true
+ }
+ }
+ },
+ "ts-node-dev": {
+ "version": "1.0.0-pre.40",
+ "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.0.0-pre.40.tgz",
+ "integrity": "sha512-78CptStf6oA5wKkRXQPEMBR5zowhnw2bvCETRMhkz2DsuussA56s6lKgUX4EiMMiPkyYdSm8jkJ875j4eo4nkQ==",
+ "dev": true,
+ "requires": {
+ "dateformat": "~1.0.4-1.2.3",
+ "dynamic-dedupe": "^0.3.0",
+ "filewatcher": "~3.0.0",
+ "minimist": "^1.1.3",
+ "mkdirp": "^0.5.1",
+ "node-notifier": "^5.4.0",
+ "resolve": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "source-map-support": "^0.5.12",
+ "tree-kill": "^1.2.1",
+ "ts-node": "*",
+ "tsconfig": "^7.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "tsconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+ "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+ "dev": true,
+ "requires": {
+ "@types/strip-bom": "^3.0.0",
+ "@types/strip-json-comments": "0.0.30",
+ "strip-bom": "^3.0.0",
+ "strip-json-comments": "^2.0.0"
+ },
+ "dependencies": {
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ },
+ "tslint": {
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz",
+ "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typescript": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
+ "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "url": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
+ "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wkx": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.7.tgz",
+ "integrity": "sha512-pHf546L96TK8RradLt1cWaIffstgv/zXZ14CGz5KnBs1AxBX0wm+IDphjJw0qrEqRv8P9W9CdTt8Z1unMRZ19A==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "xml2js": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
+ "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~9.0.1"
+ }
+ },
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ },
+ "yargs": {
+ "version": "13.2.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
+ "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
+ "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yargs-unparser": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
+ "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
+ "dev": true,
+ "requires": {
+ "flat": "^4.1.0",
+ "lodash": "^4.17.11",
+ "yargs": "^12.0.5"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "yn": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz",
+ "integrity": "sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==",
+ "dev": true
+ }
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/package.json b/project3-microservices-udagram/udacity-c3-restapi-user/package.json
new file mode 100644
index 0000000..6bf30f0
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "udacity-c2-restapi",
+ "version": "1.0.0",
+ "description": "",
+ "main": "server.js",
+ "scripts": {
+ "start": "node .",
+ "tsc": "tsc",
+ "dev": "ts-node-dev --respawn --transpileOnly ./src/server.ts",
+ "prod": "tsc && node ./www/server.js",
+ "clean": "rmdir -rf www/",
+ "build": "tsc ; cp -r -Force src/config www/config ; cp .npmrc www/.npmrc ; cp package.json www/package.json ; cd www ; 7z a -r Archive.zip ; cd ..",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "Gabriel Ruttner",
+ "license": "ISC",
+ "dependencies": {
+ "@sentry/node": "^5.17.0",
+ "@types/jsonwebtoken": "^8.3.2",
+ "aws-sdk": "^2.697.0",
+ "bcrypt": "^3.0.8",
+ "body-parser": "^1.19.0",
+ "email-validator": "^2.0.4",
+ "express": "^4.17.1",
+ "jsonwebtoken": "^8.5.1",
+ "pg": "^7.11.0",
+ "reflect-metadata": "^0.1.13",
+ "sequelize": "^5.10.0",
+ "sequelize-typescript": "^0.6.11"
+ },
+ "devDependencies": {
+ "@types/bcrypt": "^3.0.0",
+ "@types/bluebird": "^3.5.27",
+ "@types/express": "^4.17.0",
+ "@types/node": "^11.13.17",
+ "@types/sequelize": "^4.28.3",
+ "@types/validator": "^10.11.1",
+ "chai": "^4.2.0",
+ "chai-http": "^4.3.0",
+ "mocha": "^6.1.4",
+ "ts-node-dev": "^1.0.0-pre.40",
+ "tslint": "^5.18.0",
+ "typescript": "^3.5.3"
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/aws.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/aws.ts
new file mode 100644
index 0000000..90ae35e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/aws.ts
@@ -0,0 +1,66 @@
+import AWS = require('aws-sdk');
+import { config } from './config/config';
+
+const c = config.aws;
+
+//Configure AWS
+
+var credentials = new AWS.SharedIniFileCredentials({profile: c.aws_profile});
+AWS.config.credentials = credentials;
+
+// fixed "CredentialsError: Missing credentials in config"
+// https://stackoverflow.com/questions/26284181/aws-missing-credentials-when-i-try-send-something-to-my-s3-bucket-node-js
+AWS.config.update({
+ accessKeyId: c.aws_access_key_id,
+ secretAccessKey: c.aws_secret_access_key,
+ region: c.aws_region
+}); // for simplicity. In prod, use loadConfigFromFile, or env variables
+
+export const s3 = new AWS.S3({
+ signatureVersion: 'v4',
+ region: c.aws_region,
+ params: {Bucket: c.aws_media_bucket}
+});
+
+
+/* getGetSignedUrl generates an aws signed url to retreive an item
+ * @Params
+ * key: string - the filename to be put into the s3 bucket
+ * @Returns:
+ * a url as a string
+ */
+export function getGetSignedUrl( key: string ): string{
+ console.info('Processing getGetSignedUrl for ', key);
+ const signedUrlExpireSeconds = 60 * 5
+
+ const url = s3.getSignedUrl('getObject', {
+ Bucket: c.aws_media_bucket,
+ Key: key,
+ Expires: signedUrlExpireSeconds
+ });
+
+ return url;
+}
+
+/* getPutSignedUrl generates an aws signed url to put an item
+ * @Params
+ * key: string - the filename to be retreived from s3 bucket
+ * @Returns:
+ * a url as a string
+ */
+export async function getPutSignedUrl( key: string ): Promise {
+ console.info('Processing getPutSignedUrl for ', key);
+ const signedUrlExpireSeconds = 60 * 5
+
+ // fix "https://s3..amazonaws.com/" returned as a response
+ // see https://github.com/aws/aws-sdk-js/issues/2918
+ // https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md#25200
+ // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrlPromise-property
+ const url = await s3.getSignedUrlPromise('putObject', {
+ Bucket: c.aws_media_bucket,
+ Key: key,
+ Expires: signedUrlExpireSeconds
+ });
+
+ return url;
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/config/config.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/config/config.ts
new file mode 100644
index 0000000..e12c88a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/config/config.ts
@@ -0,0 +1,24 @@
+export const config = {
+ "db": {
+ "username": process.env.DB_USERNAME,
+ "password": process.env.DB_PASSWORD,
+ "database": process.env.DB_NAME,
+ "host": process.env.DB_HOST
+ },
+ "aws": {
+ "aws_region": process.env.AWS_REGION,
+ "aws_profile": process.env.AWS_PROFILE,
+ "aws_media_bucket": process.env.AWS_MEDIA_BUCKET,
+ "aws_access_key_id": process.env.AWS_ACCESS_KEY_ID,
+ "aws_secret_access_key": process.env.AWS_SECRET_ACCESS_KEY
+ },
+ "jwt" : {
+ "secret" : process.env.JWT_SECRET
+ },
+ "cors" : {
+ "access_control_allow_origin": process.env.ACCESS_CONTROL_ALLOW_ORIGIN
+ },
+ "sentry" : {
+ "dsn" : process.env.SENTRY_DNS_USER
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/index.router.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/index.router.ts
new file mode 100644
index 0000000..dbc9adb
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/index.router.ts
@@ -0,0 +1,12 @@
+import { Router, Request, Response } from 'express';
+import { UserRouter } from './users/routes/user.router';
+
+const router: Router = Router();
+
+router.use('/users', UserRouter);
+
+router.get('/', async (req: Request, res: Response) => {
+ res.send(`V0`);
+});
+
+export const IndexRouter: Router = router;
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/model.index.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/model.index.ts
new file mode 100644
index 0000000..8b5ff3e
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/model.index.ts
@@ -0,0 +1,3 @@
+import { User } from './users/models/User';
+
+export const V0MODELS = [ User ];
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/models/User.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/models/User.ts
new file mode 100644
index 0000000..5e62a3d
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/models/User.ts
@@ -0,0 +1,26 @@
+import {Table, Column, Model, HasMany, PrimaryKey, CreatedAt, UpdatedAt} from 'sequelize-typescript';
+
+@Table
+export class User extends Model {
+
+ @PrimaryKey
+ @Column
+ public email!: string;
+
+ @Column
+ public password_hash!: string; // for nullable fields
+
+ @Column
+ @CreatedAt
+ public createdAt: Date = new Date();
+
+ @Column
+ @UpdatedAt
+ public updatedAt: Date = new Date();
+
+ short() {
+ return {
+ email: this.email
+ }
+ }
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/auth.router.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/auth.router.ts
new file mode 100644
index 0000000..e6f8b51
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/auth.router.ts
@@ -0,0 +1,135 @@
+import { Router, Request, Response } from 'express';
+
+import { User } from '../models/User';
+
+import * as bcrypt from 'bcrypt';
+import * as jwt from 'jsonwebtoken';
+import { NextFunction } from 'connect';
+
+import * as EmailValidator from 'email-validator';
+import { config } from '../../../../config/config';
+
+const router: Router = Router();
+const saltRounds: number = 10;
+
+async function generatePassword(plainTextPassword: string): Promise {
+ const salt: string = await bcrypt.genSalt(saltRounds);
+ const hash: string = await bcrypt.hash(plainTextPassword, salt);
+ return hash;
+}
+
+async function comparePasswords(plainTextPassword: string, hash: string): Promise {
+ const result: boolean = await bcrypt.compare(plainTextPassword, hash);
+ return result;
+}
+
+function generateJWT(user: User): string {
+ return jwt.sign(user.dataValues, config.jwt.secret);
+}
+
+export function requireAuth(req: Request, res: Response, next: NextFunction) {
+ if (!req.headers || !req.headers.authorization){
+ return res.status(401).send({ message: 'No authorization headers.' });
+ }
+
+
+ const token_bearer = req.headers.authorization.split(' ');
+ if(token_bearer.length != 2){
+ return res.status(401).send({ message: 'Malformed token.' });
+ }
+
+ // Bearer mytoken......
+ const token = token_bearer[1];
+
+ return jwt.verify(token, config.jwt.secret, (err, decoded) => {
+ if (err) {
+ return res.status(500).send({ auth: false, message: 'Failed to authenticate.' });
+ }
+ return next();
+ });
+}
+
+router.get('/verification',
+ requireAuth,
+ async (req: Request, res: Response) => {
+ return res.status(200).send({ auth: true, message: 'Authenticated.' });
+});
+
+router.post('/login', async (req: Request, res: Response) => {
+ const email = req.body.email;
+ const password = req.body.password;
+ // check email is valid
+ if (!email || !EmailValidator.validate(email)) {
+ return res.status(400).send({ auth: false, message: 'Email is required or malformed' });
+ }
+
+ // check email password valid
+ if (!password) {
+ return res.status(400).send({ auth: false, message: 'Password is required' });
+ }
+
+ const user = await User.findByPk(email);
+ // check that user exists
+ if(!user) {
+ return res.status(401).send({ auth: false, message: 'Unauthorized' });
+ }
+
+ // check that the password matches
+ const authValid = await comparePasswords(password, user.password_hash)
+
+ if(!authValid) {
+ return res.status(401).send({ auth: false, message: 'Unauthorized' });
+ }
+
+ // Generate JWT
+ const jwt = generateJWT(user);
+
+ res.status(200).send({ auth: true, token: jwt, user: user.short()});
+});
+
+//register a new user
+router.post('/', async (req: Request, res: Response) => {
+ const email = req.body.email;
+ const plainTextPassword = req.body.password;
+ // check email is valid
+ if (!email || !EmailValidator.validate(email)) {
+ return res.status(400).send({ auth: false, message: 'Email is required or malformed' });
+ }
+
+ // check email password valid
+ if (!plainTextPassword) {
+ return res.status(400).send({ auth: false, message: 'Password is required' });
+ }
+
+ // find the user
+ const user = await User.findByPk(email);
+ // check that user doesnt exists
+ if(user) {
+ return res.status(422).send({ auth: false, message: 'User may already exist' });
+ }
+
+ const password_hash = await generatePassword(plainTextPassword);
+
+ const newUser = await new User({
+ email: email,
+ password_hash: password_hash
+ });
+
+ let savedUser;
+ try {
+ savedUser = await newUser.save();
+ } catch (e) {
+ throw e;
+ }
+
+ // Generate JWT
+ const jwt = generateJWT(savedUser);
+
+ res.status(201).send({token: jwt, user: savedUser.short()});
+});
+
+router.get('/', async (req: Request, res: Response) => {
+ res.send('auth')
+});
+
+export const AuthRouter: Router = router;
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/user.router.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/user.router.ts
new file mode 100644
index 0000000..62f0c30
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/controllers/v0/users/routes/user.router.ts
@@ -0,0 +1,19 @@
+import { Router, Request, Response } from 'express';
+
+import { User } from '../models/User';
+import { AuthRouter, requireAuth } from './auth.router';
+
+const router: Router = Router();
+
+router.use('/auth', AuthRouter);
+
+router.get('/', async (req: Request, res: Response) => {
+});
+
+router.get('/:id', async (req: Request, res: Response) => {
+ let { id } = req.params;
+ const item = await User.findByPk(id);
+ res.send(item);
+});
+
+export const UserRouter: Router = router;
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190325-create-feed-item.js b/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190325-create-feed-item.js
new file mode 100644
index 0000000..1f3c0e7
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190325-create-feed-item.js
@@ -0,0 +1,30 @@
+'use strict';
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('FeedItem', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ caption: {
+ type: Sequelize.STRING
+ },
+ url: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ });
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('FeedItem');
+ }
+};
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190328-create-user.js b/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190328-create-user.js
new file mode 100644
index 0000000..c40e8b6
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/migrations/20190328-create-user.js
@@ -0,0 +1,30 @@
+'use strict';
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('User', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ type: Sequelize.INTEGER
+ },
+ email: {
+ type: Sequelize.STRING,
+ primaryKey: true
+ },
+ password_hash: {
+ type: Sequelize.STRING
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ });
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('User');
+ }
+};
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/sequelize.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/sequelize.ts
new file mode 100644
index 0000000..da3255a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/sequelize.ts
@@ -0,0 +1,17 @@
+import {Sequelize} from 'sequelize-typescript';
+import { config } from './config/config';
+
+
+const c = config.db;
+
+// Instantiate new Sequelize instance!
+export const sequelize = new Sequelize({
+ "username": c.username,
+ "password": c.password,
+ "database": c.database,
+ "host": c.host,
+
+ dialect: 'postgres',
+ storage: ':memory:',
+});
+
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/src/server.ts b/project3-microservices-udagram/udacity-c3-restapi-user/src/server.ts
new file mode 100644
index 0000000..78ac64a
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/src/server.ts
@@ -0,0 +1,46 @@
+import express from 'express';
+import { sequelize } from './sequelize';
+
+import { IndexRouter } from './controllers/v0/index.router';
+
+import bodyParser from 'body-parser';
+
+import { V0MODELS } from './controllers/v0/model.index';
+
+import { config } from './config/config';
+
+// Sentry: automatically catch errors and provide a stack trace to developers so we can quickly find and fix bugs
+import * as Sentry from '@sentry/node';
+
+(async () => {
+ await sequelize.addModels(V0MODELS);
+ await sequelize.sync();
+
+ Sentry.init({ dsn: config.sentry.dsn });
+
+ const app = express();
+ const port = process.env.PORT_USER_SERVICE || 8080; // default port to listen
+
+ app.use(bodyParser.json());
+
+ //CORS Should be restricted
+ app.use(function(req, res, next) {
+ res.header("Access-Control-Allow-Origin", config.cors.access_control_allow_origin);
+ res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
+ next();
+ });
+
+ app.use('/api/v0/', IndexRouter)
+
+ // Root URI call
+ app.get( "/", async ( req, res ) => {
+ res.send( "/api/v0/" );
+ } );
+
+
+ // Start the Server
+ app.listen( port, () => {
+ console.log( `server running http://localhost:${ port }` );
+ console.log( `press CTRL+C to stop server` );
+ } );
+})();
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/tsconfig.json b/project3-microservices-udagram/udacity-c3-restapi-user/tsconfig.json
new file mode 100644
index 0000000..92fd0f5
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/tsconfig.json
@@ -0,0 +1,67 @@
+{
+ "compilerOptions": {
+ /* Basic Options */
+ "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
+ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+ // "lib": [], /* Specify library files to be included in the compilation. */
+ // "allowJs": true, /* Allow javascript files to be compiled. */
+ // "checkJs": true, /* Report errors in .js files. */
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+ // "declaration": true, /* Generates corresponding '.d.ts' file. */
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
+ "sourceMap": true, /* Generates corresponding '.map' file. */
+ // "outFile": "./", /* Concatenate and emit output to single file. */
+ "outDir": "./www", /* Redirect output structure to the directory. */
+ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+ // "composite": true, /* Enable project compilation */
+ // "removeComments": true, /* Do not emit comments to output. */
+ // "noEmit": true, /* Do not emit outputs. */
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+ /* Strict Type-Checking Options */
+ "strict": true, /* Enable all strict type-checking options. */
+ "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
+ "strictNullChecks": false, /* Enable strict null checks. */
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
+
+ /* Additional Checks */
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+
+ /* Module Resolution Options */
+ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+ "baseUrl": "/", /* Base directory to resolve non-absolute module names. */
+ "paths": {
+ "*": [
+ "node_modules/*"
+ ]
+ }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
+ // "typeRoots": [], /* List of folders to include type definitions from. */
+ // "types": [], /* Type declaration files to be included in compilation. */
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
+
+ /* Source Map Options */
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+ /* Experimental Options */
+ "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+ },
+ "include": [
+ "src/**/*"
+ ]
+}
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/tslint.json b/project3-microservices-udagram/udacity-c3-restapi-user/tslint.json
new file mode 100644
index 0000000..05e6a30
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/tslint.json
@@ -0,0 +1,139 @@
+{
+ "rulesDirectory": [
+ "node_modules/codelyzer"
+ ],
+ "rules": {
+ "arrow-return-shorthand": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "deprecation": {
+ "severity": "warn"
+ },
+ "eofline": true,
+ "forin": true,
+ "import-spacing": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "interface-over-type-literal": true,
+ "label-position": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-empty": false,
+ "no-empty-interface": true,
+ "no-eval": true,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-misused-new": true,
+ "no-non-null-assertion": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-string-throw": true,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-initializer": true,
+ "no-unused-expression": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "prefer-const": true,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "unified-signatures": true,
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "page",
+ "kebab-case"
+ ],
+ "no-output-on-prefix": true,
+ "use-input-property-decorator": true,
+ "use-output-property-decorator": true,
+ "use-host-property-decorator": true,
+ "no-input-rename": true,
+ "no-output-rename": true,
+ "use-life-cycle-interface": true,
+ "use-pipe-transform-interface": true,
+ "directive-class-suffix": true
+ }
+ }
+
\ No newline at end of file
diff --git a/project3-microservices-udagram/udacity-c3-restapi-user/udacity-c3-restapi.postman_collection.json b/project3-microservices-udagram/udacity-c3-restapi-user/udacity-c3-restapi.postman_collection.json
new file mode 100644
index 0000000..ddf94c9
--- /dev/null
+++ b/project3-microservices-udagram/udacity-c3-restapi-user/udacity-c3-restapi.postman_collection.json
@@ -0,0 +1,870 @@
+{
+ "info": {
+ "_postman_id": "ab6a67e0-1406-4a1b-aee8-a40906e123a2",
+ "name": "udacity-c2-restapi",
+ "description": "Requests that should work!",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "Public",
+ "item": [
+ {
+ "name": "/api/v0/feed",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "1ca4d5f0-f73c-4d7e-95d1-4f97bf49369d",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"The count is equal to the number of items rx\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.count).to.eql(jsonData.rows.length);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 600ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(600);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Get all the items in the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed/:id",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "0f86726d-0a45-463c-a775-e34430735155",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ },
+ "description": "Request a specific feed item detail"
+ },
+ "response": [
+ {
+ "name": "/api/v0/feed/:id",
+ "originalRequest": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ }
+ },
+ "status": "OK",
+ "code": 200,
+ "_postman_previewlanguage": "json",
+ "header": [
+ {
+ "key": "X-Powered-By",
+ "value": "Express"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json; charset=utf-8"
+ },
+ {
+ "key": "Content-Length",
+ "value": "133"
+ },
+ {
+ "key": "ETag",
+ "value": "W/\"85-gic7UchUXbyxmSqNsq7nx4+Eaas\""
+ },
+ {
+ "key": "Date",
+ "value": "Tue, 26 Mar 2019 15:07:32 GMT"
+ },
+ {
+ "key": "Connection",
+ "value": "keep-alive"
+ }
+ ],
+ "cookie": [],
+ "body": "{\n \"id\": 3,\n \"caption\": \"hello0.5278862272947393\",\n \"url\": null,\n \"createdAt\": \"2019-03-26T14:16:58.442Z\",\n \"updatedAt\": \"2019-03-26T14:16:58.443Z\"\n}"
+ }
+ ]
+ },
+ {
+ "name": "/api/v0/feed/:id",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "671b15c9-4498-413f-b7e2-3a5bec6ca0f4",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "PATCH",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n\t\"id\": 3,\r\n \"caption\": \"GoodbyeUPDATEDBIS\",\r\n \"url\": \"test.jpg\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed/2",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ "2"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ]
+ },
+ "description": "Request a specific feed item detail"
+ },
+ "response": [
+ {
+ "name": "/api/v0/feed/:id",
+ "originalRequest": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{host}}/api/v0/feed/:id",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ ":id"
+ ],
+ "query": [
+ {
+ "key": "id",
+ "value": "4",
+ "disabled": true
+ }
+ ],
+ "variable": [
+ {
+ "key": "id",
+ "value": "3"
+ }
+ ]
+ }
+ },
+ "status": "OK",
+ "code": 200,
+ "_postman_previewlanguage": "json",
+ "header": [
+ {
+ "key": "X-Powered-By",
+ "value": "Express"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json; charset=utf-8"
+ },
+ {
+ "key": "Content-Length",
+ "value": "133"
+ },
+ {
+ "key": "ETag",
+ "value": "W/\"85-gic7UchUXbyxmSqNsq7nx4+Eaas\""
+ },
+ {
+ "key": "Date",
+ "value": "Tue, 26 Mar 2019 15:07:32 GMT"
+ },
+ {
+ "key": "Connection",
+ "value": "keep-alive"
+ }
+ ],
+ "cookie": [],
+ "body": "{\n \"id\": 3,\n \"caption\": \"hello0.5278862272947393\",\n \"url\": null,\n \"createdAt\": \"2019-03-26T14:16:58.442Z\",\n \"updatedAt\": \"2019-03-26T14:16:58.443Z\"\n}"
+ }
+ ]
+ },
+ {
+ "name": "/api/v0/user/auth valid registration",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "e43fba10-e5c3-48c5-912c-4e954ad6366e",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"A single item is returned\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n\t\"email\":\"hello@gmail.com\",\n\t\"password\":\"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth invalid registration",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "ec80bf59-c7e1-47e8-89ef-da5e8cf8a088",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"auth is false and a message is included in the error body\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ " pm.expect(jsonData.message).to.not.eql(null)",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"password\": \"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth/login valid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "680c7fcc-7e63-424f-af32-9aaa629b44d6",
+ "exec": [
+ "pm.test(\"Status code is 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "pm.test(\"body includes an email and token\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.auth).to.eql(true);",
+ " pm.expect(jsonData.user).to.not.eql(null);",
+ " pm.expect(jsonData.token).to.not.eql(null)",
+ " ",
+ " pm.environment.set(\"token\", jsonData.token);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 500ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(500);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n\t\"email\":\"hello@gmail.com\",\n\t\"password\":\"fancypass\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth/login",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth",
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/user/auth/login invalid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "4460e048-e276-4ce1-90de-590e2bd97d8a",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"auth is false and a message is included in the error body\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ " pm.expect(jsonData.message).to.not.eql(null)",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/users/auth/login",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "users",
+ "auth",
+ "login"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "upload file with the generated aws signed-url",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "PUT",
+ "header": [],
+ "body": {
+ "mode": "file",
+ "file": {
+ "src": "/P:/personnel/pollux.png"
+ }
+ },
+ "url": {
+ "raw": "https://udagram-kjm-dev.s3.eu-west-3.amazonaws.com/pollux.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZISZGJJ7POB32J6L%2F20200603%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20200603T144712Z&X-Amz-Expires=300&X-Amz-Signature=4e5a7b5ca3c4eee63d5abdccad782e91f0df0f52620e5b1be30912c82c50f7de&X-Amz-SignedHeaders=host",
+ "protocol": "https",
+ "host": [
+ "udagram-kjm-dev",
+ "s3",
+ "eu-west-3",
+ "amazonaws",
+ "com"
+ ],
+ "path": [
+ "pollux.png"
+ ],
+ "query": [
+ {
+ "key": "X-Amz-Algorithm",
+ "value": "AWS4-HMAC-SHA256"
+ },
+ {
+ "key": "X-Amz-Credential",
+ "value": "AKIAZISZGJJ7POB32J6L%2F20200603%2Feu-west-3%2Fs3%2Faws4_request"
+ },
+ {
+ "key": "X-Amz-Date",
+ "value": "20200603T144712Z"
+ },
+ {
+ "key": "X-Amz-Expires",
+ "value": "300"
+ },
+ {
+ "key": "X-Amz-Signature",
+ "value": "4e5a7b5ca3c4eee63d5abdccad782e91f0df0f52620e5b1be30912c82c50f7de"
+ },
+ {
+ "key": "X-Amz-SignedHeaders",
+ "value": "host"
+ }
+ ]
+ },
+ "description": "Upload the file using the signed url received as a response to /feed/signed-url request"
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ },
+ {
+ "name": "Unauthorized",
+ "item": [
+ {
+ "name": "/api/v0/feed unauthorized",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "be0a08a6-209a-467f-8cf3-11702bb4a8df",
+ "exec": [
+ "pm.test(\"Status code is 401\", function () {",
+ " pm.response.to.have.status(401);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ }
+ ],
+ "protocolProfileBehavior": {}
+ },
+ {
+ "name": "Authorized",
+ "item": [
+ {
+ "name": "/api/v0/feed invalid",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "34606858-be42-447e-a935-409a8e05d87f",
+ "exec": [
+ "pm.test(\"Status code is 400\", function () {",
+ " pm.response.to.have.status(400);",
+ "});",
+ "",
+ "pm.test(\"body includes a message\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.message).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 500ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(500);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed authorized",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "b4a1781a-cb0d-462f-aab6-0ce88e96c2b2",
+ "exec": [
+ "pm.test(\"Status code is 201\", function () {",
+ " pm.response.to.have.status(201);",
+ "});",
+ "",
+ "pm.test(\"The post returns a new item with an id\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"caption\": \"Hello\",\n \"url\": \"test.jpg\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ },
+ {
+ "name": "/api/v0/feed/signed-url/:fileName",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "0f7ff773-58f0-47de-8657-a1fb7eb8311d",
+ "exec": [
+ "pm.test(\"Status code is 201\", function () {",
+ " pm.response.to.have.status(201);",
+ "});",
+ "",
+ "pm.test(\"The post returns a new item with an id\", function () {",
+ " var jsonData = pm.response.json();",
+ " pm.expect(jsonData.id).to.not.eql(null);",
+ "});",
+ "",
+ "pm.test(\"Response time is less than 200ms\", function () {",
+ " pm.expect(pm.response.responseTime).to.be.below(200);",
+ "});"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"caption\": \"Hello\",\n \"url\": \"test.jpg\"\n}"
+ },
+ "url": {
+ "raw": "{{host}}/api/v0/feed/signed-url/pollux.png",
+ "host": [
+ "{{host}}"
+ ],
+ "path": [
+ "api",
+ "v0",
+ "feed",
+ "signed-url",
+ "pollux.png"
+ ]
+ },
+ "description": "Post a new item to the feed"
+ },
+ "response": []
+ }
+ ],
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{token}}",
+ "type": "string"
+ }
+ ]
+ },
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "52aed6e2-667a-40ec-adc2-0a96307c5d33",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "f402b58e-86e1-4f42-ab30-5cd07b4822d4",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "protocolProfileBehavior": {}
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "id": "5a019e7f-bc38-4ae8-9a8c-d64d79ad1903",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "id": "7f504948-40fe-450d-8479-93ef51d1ee49",
+ "type": "text/javascript",
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "variable": [
+ {
+ "id": "3e3ea131-5328-4f50-8fe1-516e3995917d",
+ "key": "host",
+ "value": "http://localhost:8080",
+ "type": "string"
+ }
+ ],
+ "protocolProfileBehavior": {}
+}
\ No newline at end of file