├── src
├── assets
│ └── .gitkeep
├── app
│ ├── pages
│ │ ├── home
│ │ │ ├── home.component.scss
│ │ │ ├── home.component.html
│ │ │ ├── home-routing.module.ts
│ │ │ ├── home.component.ts
│ │ │ ├── home.module.ts
│ │ │ └── home.component.spec.ts
│ │ ├── admin
│ │ │ ├── admin.component.scss
│ │ │ ├── admin.component.html
│ │ │ ├── components
│ │ │ │ └── modal
│ │ │ │ │ ├── modal.component.scss
│ │ │ │ │ ├── modal.component.spec.ts
│ │ │ │ │ ├── modal.component.ts
│ │ │ │ │ └── modal.component.html
│ │ │ ├── users
│ │ │ │ ├── users.component.scss
│ │ │ │ ├── users-routing.module.ts
│ │ │ │ ├── users.module.ts
│ │ │ │ ├── users.component.spec.ts
│ │ │ │ ├── users.component.html
│ │ │ │ └── users.component.ts
│ │ │ ├── admin.component.ts
│ │ │ ├── services
│ │ │ │ ├── users.service.spec.ts
│ │ │ │ └── users.service.ts
│ │ │ ├── admin-routing.module.ts
│ │ │ ├── admin.module.ts
│ │ │ └── admin.component.spec.ts
│ │ ├── not-found
│ │ │ ├── not-found.component.scss
│ │ │ ├── not-found.component.html
│ │ │ ├── not-found.component.ts
│ │ │ ├── not-found-routing.module.ts
│ │ │ ├── not-found.module.ts
│ │ │ └── not-found.component.spec.ts
│ │ └── auth
│ │ │ ├── login
│ │ │ ├── login.component.scss
│ │ │ ├── login-routing.module.ts
│ │ │ ├── login.module.ts
│ │ │ ├── login.component.spec.ts
│ │ │ ├── login.component.ts
│ │ │ └── login.component.html
│ │ │ ├── auth.service.spec.ts
│ │ │ └── auth.service.ts
│ ├── shared
│ │ ├── components
│ │ │ ├── sidebar
│ │ │ │ ├── sidebar.component.scss
│ │ │ │ ├── sidebar.component.html
│ │ │ │ ├── sidebar.module.ts
│ │ │ │ ├── sidebar.component.ts
│ │ │ │ └── sidebar.component.spec.ts
│ │ │ ├── footer
│ │ │ │ ├── footer.component.html
│ │ │ │ ├── footer.component.scss
│ │ │ │ ├── footer.component.ts
│ │ │ │ └── footer.component.spec.ts
│ │ │ └── header
│ │ │ │ ├── header.component.scss
│ │ │ │ ├── header.component.html
│ │ │ │ ├── header.component.spec.ts
│ │ │ │ └── header.component.ts
│ │ ├── models
│ │ │ └── user.interface.ts
│ │ ├── services
│ │ │ └── utils.service.ts
│ │ ├── guards
│ │ │ └── check-login.guard.ts
│ │ ├── interceptors
│ │ │ └── admin-interceptor.ts
│ │ └── utils
│ │ │ └── base-form-user.ts
│ ├── app.component.scss
│ ├── app.component.html
│ ├── app.component.ts
│ ├── app-routing.module.ts
│ ├── app.component.spec.ts
│ ├── app.module.ts
│ └── material.module.ts
├── favicon.ico
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── styles.scss
├── main.ts
├── index.html
├── test.ts
└── polyfills.ts
├── API
├── src
│ ├── config
│ │ └── config.ts
│ ├── routes
│ │ ├── index.ts
│ │ ├── auth.ts
│ │ └── user.ts
│ ├── index.ts
│ ├── middlewares
│ │ ├── jwt.ts
│ │ └── role.ts
│ ├── entity
│ │ └── Users.ts
│ └── controller
│ │ ├── AuthController.ts
│ │ └── UserController.ts
├── README.md
├── tsconfig.json
├── ormconfig.json
├── package.json
└── package-lock.json
├── .editorconfig
├── e2e
├── src
│ ├── app.po.ts
│ └── app.e2e-spec.ts
├── tsconfig.json
└── protractor.conf.js
├── tsconfig.app.json
├── tsconfig.spec.json
├── tsconfig.json
├── tsconfig.base.json
├── .gitignore
├── .browserslistrc
├── LICENSE
├── karma.conf.js
├── README.md
├── package.json
├── tslint.json
└── angular.json
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/pages/home/home.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/shared/components/sidebar/sidebar.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin.component.html:
--------------------------------------------------------------------------------
1 |
admin works!
2 |
--------------------------------------------------------------------------------
/API/src/config/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | jwtSecret: 'BDPEK@'
3 | };
4 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found.component.html:
--------------------------------------------------------------------------------
1 | not-found works!
2 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/domini-code/mysql_node_angular/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/app/shared/components/footer/footer.component.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/pages/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 | Welcome, {{ user?.username || 'User' }}.
3 |
4 | home works!
--------------------------------------------------------------------------------
/src/app/shared/components/footer/footer.component.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | bottom: 0;
3 | width: 100%;
4 | height: 60px;
5 | background-color: #f5f5f5;
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/shared/components/header/header.component.scss:
--------------------------------------------------------------------------------
1 | .spacer {
2 | flex: 1 1 auto;
3 | }
4 |
5 | a {
6 | text-decoration: none;
7 | color: #fff;
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/pages/admin/components/modal/modal.component.scss:
--------------------------------------------------------------------------------
1 | .modal-form {
2 | padding: 1rem 0;
3 |
4 | .full-width-input {
5 | width: 100%;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/API/README.md:
--------------------------------------------------------------------------------
1 | # Awesome Project Build with TypeORM
2 |
3 | Steps to run this project:
4 |
5 | 1. Run `npm i` command
6 | 2. Setup database settings inside `ormconfig.json` file
7 | 3. Run `npm start` command
8 |
--------------------------------------------------------------------------------
/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | mat-sidenav {
2 | width: 200px;
3 | }
4 |
5 | mat-sidenav-content {
6 | background-color: #f9fbfb;
7 | }
8 |
9 | mat-sidenav-container {
10 | height: 100%;
11 | }
12 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | html, body { height: 100%; }
4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
5 |
--------------------------------------------------------------------------------
/API/src/routes/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from 'express';
2 | import auth from './auth';
3 | import user from './user';
4 |
5 | const routes = Router();
6 |
7 | routes.use('/auth', auth);
8 | routes.use('/users', user);
9 |
10 | export default routes;
11 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users.component.scss:
--------------------------------------------------------------------------------
1 | table {
2 | width: 98%;
3 | margin: 0 auto;
4 | margin-top: 1rem;
5 | }
6 |
7 | th.mat-sort-header-sorted {
8 | color: black;
9 | }
10 |
11 | .table-button-row button {
12 | margin: 12px;
13 | }
14 |
15 | .btn-new {
16 | width: 20%;
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/shared/models/user.interface.ts:
--------------------------------------------------------------------------------
1 | export type Roles = 'SUSCRIPTOR' | 'ADMIN';
2 |
3 | export interface User {
4 | username: string;
5 | password: string;
6 | }
7 |
8 | export interface UserResponse extends User {
9 | message: string;
10 | token: string;
11 | userId: number;
12 | role: Roles;
13 | }
14 |
--------------------------------------------------------------------------------
/API/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["es5", "es6"],
4 | "target": "es5",
5 | "module": "commonjs",
6 | "moduleResolution": "node",
7 | "outDir": "./dist",
8 | "rootDir": "./src",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "sourceMap": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo(): Promise {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText(): Promise {
9 | return element(by.css('app-root .content span')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "../tsconfig.base.json",
4 | "compilerOptions": {
5 | "outDir": "../out-tsc/e2e",
6 | "module": "commonjs",
7 | "target": "es2018",
8 | "types": [
9 | "jasmine",
10 | "jasminewd2",
11 | "node"
12 | ]
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-admin',
5 | templateUrl: './admin.component.html',
6 | styleUrls: ['./admin.component.scss']
7 | })
8 | export class AdminComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit(): void {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.base.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/shared/components/footer/footer.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-footer',
5 | templateUrl: './footer.component.html',
6 | styleUrls: ['./footer.component.scss']
7 | })
8 | export class FooterComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit(): void {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-not-found',
5 | templateUrl: './not-found.component.html',
6 | styleUrls: ['./not-found.component.scss']
7 | })
8 | export class NotFoundComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit(): void {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login.component.scss:
--------------------------------------------------------------------------------
1 | .login-form {
2 | padding: 4rem 1rem;
3 |
4 | mat-card {
5 | max-width: 300px;
6 | margin: 2rem auto;
7 | text-align: center;
8 | height: 350px;
9 | }
10 |
11 | .full-width-input,
12 | button {
13 | width: 100%;
14 | }
15 |
16 | .separator {
17 | margin-bottom: 2rem;
18 | }
19 |
20 |
21 |
22 |
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/shared/services/utils.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { BehaviorSubject } from 'rxjs';
3 | @Injectable()
4 | export class UtilsService {
5 | private sidebarOpened = new BehaviorSubject(false);
6 | sidebarOpened$ = this.sidebarOpened.asObservable();
7 |
8 | openSidebar(value: boolean): void {
9 | this.sidebarOpened.next(value);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/API/src/routes/auth.ts:
--------------------------------------------------------------------------------
1 | import { checkJwt } from './../middlewares/jwt';
2 | import { Router } from 'express';
3 | import AuthController from '../controller/AuthController';
4 |
5 | const router = Router();
6 |
7 | // login
8 | router.post('/login', AuthController.login);
9 |
10 | // Change password
11 | router.post('/change-password', [checkJwt], AuthController.changePassword);
12 |
13 | export default router;
14 |
--------------------------------------------------------------------------------
/src/app/pages/home/home-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { HomeComponent } from './home.component';
5 |
6 | const routes: Routes = [{ path: '', component: HomeComponent }];
7 |
8 | @NgModule({
9 | imports: [RouterModule.forChild(routes)],
10 | exports: [RouterModule]
11 | })
12 | export class HomeRoutingModule { }
13 |
--------------------------------------------------------------------------------
/src/app/pages/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { AuthService } from '@auth/auth.service';
3 |
4 | @Component({
5 | selector: 'app-home',
6 | templateUrl: './home.component.html',
7 | styleUrls: ['./home.component.scss'],
8 | })
9 | export class HomeComponent implements OnInit {
10 | constructor(public authSvc: AuthService) {}
11 |
12 | ngOnInit(): void {}
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/pages/home/home.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { HomeRoutingModule } from './home-routing.module';
5 | import { HomeComponent } from './home.component';
6 |
7 |
8 | @NgModule({
9 | declarations: [HomeComponent],
10 | imports: [
11 | CommonModule,
12 | HomeRoutingModule
13 | ]
14 | })
15 | export class HomeModule { }
16 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.base.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { UsersComponent } from './users.component';
5 |
6 | const routes: Routes = [{ path: '', component: UsersComponent }];
7 |
8 | @NgModule({
9 | imports: [RouterModule.forChild(routes)],
10 | exports: [RouterModule]
11 | })
12 | export class UsersRoutingModule { }
13 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { LoginComponent } from './login.component';
5 |
6 | const routes: Routes = [{ path: '', component: LoginComponent }];
7 |
8 | @NgModule({
9 | imports: [RouterModule.forChild(routes)],
10 | exports: [RouterModule]
11 | })
12 | export class LoginRoutingModule { }
13 |
--------------------------------------------------------------------------------
/src/app/pages/auth/auth.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { AuthService } from './auth.service';
4 |
5 | describe('AuthService', () => {
6 | let service: AuthService;
7 |
8 | beforeEach(() => {
9 | TestBed.configureTestingModule({});
10 | service = TestBed.inject(AuthService);
11 | });
12 |
13 | it('should be created', () => {
14 | expect(service).toBeTruthy();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { NotFoundComponent } from './not-found.component';
5 |
6 | const routes: Routes = [{ path: '', component: NotFoundComponent }];
7 |
8 | @NgModule({
9 | imports: [RouterModule.forChild(routes)],
10 | exports: [RouterModule]
11 | })
12 | export class NotFoundRoutingModule { }
13 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Menu
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/app/pages/admin/services/users.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { UsersService } from './users.service';
4 |
5 | describe('UsersService', () => {
6 | let service: UsersService;
7 |
8 | beforeEach(() => {
9 | TestBed.configureTestingModule({});
10 | service = TestBed.inject(UsersService);
11 | });
12 |
13 | it('should be created', () => {
14 | expect(service).toBeTruthy();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { NotFoundRoutingModule } from './not-found-routing.module';
5 | import { NotFoundComponent } from './not-found.component';
6 |
7 |
8 | @NgModule({
9 | declarations: [NotFoundComponent],
10 | imports: [
11 | CommonModule,
12 | NotFoundRoutingModule
13 | ]
14 | })
15 | export class NotFoundModule { }
16 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { UsersRoutingModule } from './users-routing.module';
5 | import { UsersComponent } from './users.component';
6 | import { MaterialModule } from '@app/material.module';
7 |
8 | @NgModule({
9 | declarations: [UsersComponent],
10 | imports: [CommonModule, UsersRoutingModule, MaterialModule],
11 | })
12 | export class UsersModule {}
13 |
--------------------------------------------------------------------------------
/API/ormconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "mysql",
3 | "host": "XXXXXXXXX",
4 | "port": 3306,
5 | "username": "XXXXXX",
6 | "password": "XXXXXX",
7 | "database": "XXXXXXXX",
8 | "synchronize": true,
9 | "logging": false,
10 | "entities": ["src/entity/**/*.ts"],
11 | "migrations": ["src/migration/**/*.ts"],
12 | "subscribers": ["src/subscriber/**/*.ts"],
13 | "cli": {
14 | "entitiesDir": "src/entity",
15 | "migrationsDir": "src/migration",
16 | "subscribersDir": "src/subscriber"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/shared/components/sidebar/sidebar.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | insert_chart_outlined
4 | Dashboard
5 |
6 |
7 |
8 | people
9 | Users
10 |
11 |
12 |
13 | exit_to_app
14 | Exit
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /*
2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
3 | It is not intended to be used to perform a compilation.
4 |
5 | To learn more about this file see: https://angular.io/config/solution-tsconfig.
6 | */
7 | {
8 | "files": [],
9 | "references": [
10 | {
11 | "path": "./tsconfig.app.json"
12 | },
13 | {
14 | "path": "./tsconfig.spec.json"
15 | },
16 | {
17 | "path": "./e2e/tsconfig.json"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Login
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { AdminComponent } from './admin.component';
5 |
6 | const routes: Routes = [
7 | { path: '', component: AdminComponent },
8 | {
9 | path: 'users',
10 | loadChildren: () =>
11 | import('./users/users.module').then((m) => m.UsersModule),
12 | },
13 | ];
14 |
15 | @NgModule({
16 | imports: [RouterModule.forChild(routes)],
17 | exports: [RouterModule],
18 | })
19 | export class AdminRoutingModule {}
20 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { LoginRoutingModule } from './login-routing.module';
5 | import { LoginComponent } from './login.component';
6 | import { MaterialModule } from '@app/material.module';
7 | import { ReactiveFormsModule } from '@angular/forms';
8 |
9 | @NgModule({
10 | declarations: [LoginComponent],
11 | imports: [
12 | CommonModule,
13 | LoginRoutingModule,
14 | MaterialModule,
15 | ReactiveFormsModule,
16 | ],
17 | })
18 | export class LoginModule {}
19 |
--------------------------------------------------------------------------------
/src/app/shared/components/header/header.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 | My APP
8 |
9 | Login
10 | Admin
11 |
12 |
13 |
14 | Logout
15 |
16 |
--------------------------------------------------------------------------------
/src/app/shared/components/sidebar/sidebar.module.ts:
--------------------------------------------------------------------------------
1 | import { UtilsService } from './../../services/utils.service';
2 | import { RouterModule } from '@angular/router';
3 | import { NgModule } from '@angular/core';
4 | import { CommonModule } from '@angular/common';
5 | import { SidebarComponent } from './sidebar.component';
6 |
7 | import { MaterialModule } from '@app/material.module';
8 |
9 | @NgModule({
10 | declarations: [SidebarComponent],
11 | imports: [CommonModule, MaterialModule, RouterModule],
12 | exports: [SidebarComponent],
13 | providers: [UtilsService],
14 | })
15 | export class SidebarModule {}
16 |
--------------------------------------------------------------------------------
/src/app/shared/components/sidebar/sidebar.component.ts:
--------------------------------------------------------------------------------
1 | import { UtilsService } from './../../services/utils.service';
2 | import { AuthService } from '@auth/auth.service';
3 | import { Component, OnInit } from '@angular/core';
4 |
5 | @Component({
6 | selector: 'app-sidebar',
7 | templateUrl: './sidebar.component.html',
8 | styleUrls: ['./sidebar.component.scss'],
9 | })
10 | export class SidebarComponent implements OnInit {
11 | constructor(private authSvc: AuthService, private utilsSvc: UtilsService) {}
12 |
13 | ngOnInit(): void {}
14 |
15 | onExit(): void {
16 | this.authSvc.logout();
17 | this.utilsSvc.openSidebar(false);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin.module.ts:
--------------------------------------------------------------------------------
1 | import { ReactiveFormsModule } from '@angular/forms';
2 | import { NgModule } from '@angular/core';
3 | import { CommonModule } from '@angular/common';
4 |
5 | import { AdminRoutingModule } from './admin-routing.module';
6 | import { AdminComponent } from './admin.component';
7 | import { ModalComponent } from './components/modal/modal.component';
8 | import { MaterialModule } from '@app/material.module';
9 |
10 | @NgModule({
11 | declarations: [AdminComponent, ModalComponent],
12 | imports: [
13 | CommonModule,
14 | AdminRoutingModule,
15 | MaterialModule,
16 | ReactiveFormsModule,
17 | ],
18 | })
19 | export class AdminModule {}
20 |
--------------------------------------------------------------------------------
/src/app/shared/guards/check-login.guard.ts:
--------------------------------------------------------------------------------
1 | import { UserResponse } from './../models/user.interface';
2 | import { Injectable } from '@angular/core';
3 | import { CanActivate } from '@angular/router';
4 | import { Observable } from 'rxjs';
5 | import { AuthService } from '@auth/auth.service';
6 | import { take, map } from 'rxjs/operators';
7 |
8 | @Injectable({
9 | providedIn: 'root',
10 | })
11 | export class CheckLoginGuard implements CanActivate {
12 | constructor(private authSvc: AuthService) {}
13 |
14 | canActivate(): Observable {
15 | return this.authSvc.user$.pipe(
16 | take(1),
17 | map((user: UserResponse) => (!user ? true : false))
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/API/src/index.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { createConnection } from 'typeorm';
3 | import * as express from 'express';
4 | import * as cors from 'cors';
5 | import * as helmet from 'helmet';
6 | import routes from './routes';
7 |
8 | const PORT = process.env.PORT || 3000;
9 |
10 | createConnection()
11 | .then(async () => {
12 | // create express app
13 | const app = express();
14 | // Middlewares
15 | app.use(cors());
16 | app.use(helmet());
17 |
18 | app.use(express.json());
19 | // Routes
20 | app.use('/', routes);
21 |
22 | // start express server
23 | app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
24 | })
25 | .catch(error => console.log(error));
26 |
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('login app is running!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | } as logging.Entry));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/pages/home/home.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HomeComponent } from './home.component';
4 |
5 | describe('HomeComponent', () => {
6 | let component: HomeComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ HomeComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(HomeComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/pages/admin/admin.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { AdminComponent } from './admin.component';
4 |
5 | describe('AdminComponent', () => {
6 | let component: AdminComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ AdminComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(AdminComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { UsersComponent } from './users.component';
4 |
5 | describe('UsersComponent', () => {
6 | let component: UsersComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ UsersComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(UsersComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LoginComponent } from './login.component';
4 |
5 | describe('LoginComponent', () => {
6 | let component: LoginComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ LoginComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(LoginComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/API/src/middlewares/jwt.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response, NextFunction } from 'express';
2 | import * as jwt from 'jsonwebtoken';
3 | import config from '../config/config';
4 |
5 | export const checkJwt = (req: Request, res: Response, next: NextFunction) => {
6 | const token = req.headers['auth'];
7 | let jwtPayload;
8 |
9 | try {
10 | jwtPayload = jwt.verify(token, config.jwtSecret);
11 | res.locals.jwtPayload = jwtPayload;
12 | } catch (e) {
13 | return res.status(401).json({ message: 'Not Authorized' });
14 | }
15 |
16 | const { userId, username } = jwtPayload;
17 |
18 | const newToken = jwt.sign({ userId, username }, config.jwtSecret, { expiresIn: '1h' });
19 | res.setHeader('token', newToken);
20 | // Call next
21 | next();
22 | };
23 |
--------------------------------------------------------------------------------
/src/app/pages/admin/components/modal/modal.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ModalComponent } from './modal.component';
4 |
5 | describe('ModalComponent', () => {
6 | let component: ModalComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ ModalComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(ModalComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/shared/components/footer/footer.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { FooterComponent } from './footer.component';
4 |
5 | describe('FooterComponent', () => {
6 | let component: FooterComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ FooterComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(FooterComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/shared/components/header/header.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HeaderComponent } from './header.component';
4 |
5 | describe('HeaderComponent', () => {
6 | let component: HeaderComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ HeaderComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(HeaderComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/API/src/routes/user.ts:
--------------------------------------------------------------------------------
1 | import { checkRole } from './../middlewares/role';
2 | import { checkJwt } from './../middlewares/jwt';
3 | import { UserController } from './../controller/UserController';
4 | import { Router } from 'express';
5 |
6 | const router = Router();
7 |
8 | // Get all users
9 | router.get('/', UserController.getAll);
10 |
11 | // Get one user
12 | router.get('/:id', [checkJwt, checkRole(['admin'])], UserController.getById);
13 |
14 | // Create a new user
15 | router.post('/', [checkJwt, checkRole(['admin'])], UserController.new);
16 |
17 | // Edit user
18 | router.patch('/:id', [checkJwt, checkRole(['admin'])], UserController.edit);
19 |
20 | // Delete
21 | router.delete('/:id', [checkJwt, checkRole(['admin'])], UserController.delete);
22 |
23 | export default router;
24 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false,
7 | API_URL: 'http://localhost:3000',
8 | };
9 |
10 | /*
11 | * For easier debugging in development mode, you can import the following file
12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
13 | *
14 | * This import should be commented out in production mode because it will have a negative impact
15 | * on performance if an error is thrown.
16 | */
17 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
18 |
--------------------------------------------------------------------------------
/src/app/pages/not-found/not-found.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { NotFoundComponent } from './not-found.component';
4 |
5 | describe('NotFoundComponent', () => {
6 | let component: NotFoundComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ NotFoundComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(NotFoundComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/shared/components/sidebar/sidebar.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { SidebarComponent } from './sidebar.component';
4 |
5 | describe('SidebarComponent', () => {
6 | let component: SidebarComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ SidebarComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(SidebarComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/app/shared/interceptors/admin-interceptor.ts:
--------------------------------------------------------------------------------
1 | import { AuthService } from '@auth/auth.service';
2 | import { Observable } from 'rxjs';
3 | import { Injectable } from '@angular/core';
4 | import {
5 | HttpInterceptor,
6 | HttpRequest,
7 | HttpHandler,
8 | } from '@angular/common/http';
9 | @Injectable()
10 | export class AdminInterceptor implements HttpInterceptor {
11 | constructor(private authSvc: AuthService) {}
12 | intercept(req: HttpRequest, next: HttpHandler): Observable {
13 | if (req.url.includes('users')) {
14 | const userValue = this.authSvc.userValue;
15 | const authReq = req.clone({
16 | setHeaders: {
17 | auth: userValue.token,
18 | },
19 | });
20 | return next.handle(authReq);
21 | }
22 | return next.handle(req);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/API/src/middlewares/role.ts:
--------------------------------------------------------------------------------
1 | import { getRepository } from 'typeorm';
2 | import { Request, Response, NextFunction } from 'express';
3 | import { Users } from '../entity/Users';
4 |
5 | export const checkRole = (roles: Array) => {
6 | return async (req: Request, res: Response, next: NextFunction) => {
7 | const { userId } = res.locals.jwtPayload;
8 | const userRepository = getRepository(Users);
9 | let user: Users;
10 |
11 | try {
12 | user = await userRepository.findOneOrFail(userId);
13 | } catch (e) {
14 | return res.status(401).json({ message: 'Not Authorized' });
15 | }
16 |
17 | //Check
18 | const { role } = user;
19 | if (roles.includes(role)) {
20 | next();
21 | } else {
22 | res.status(401).json({ message: 'Not Authorized' });
23 | }
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "paths": {
7 | "@app/*": ["src/app/*"],
8 | "@shared/*": ["src/app/shared/*"],
9 | "@admin/*": ["src/app/pages/*"],
10 | "@pages/*": ["src/app/pages/*"],
11 | "@auth/*": ["src/app/pages/auth/*"],
12 | "@env/*": ["src/environments/*"],
13 | },
14 | "outDir": "./dist/out-tsc",
15 | "sourceMap": true,
16 | "declaration": false,
17 | "downlevelIteration": true,
18 | "experimentalDecorators": true,
19 | "moduleResolution": "node",
20 | "importHelpers": true,
21 | "target": "es2015",
22 | "module": "es2020",
23 | "lib": [
24 | "es2018",
25 | "dom"
26 | ]
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/API/src/entity/Users.ts:
--------------------------------------------------------------------------------
1 | import { Entity, PrimaryGeneratedColumn, Unique, Column } from 'typeorm';
2 | import { MinLength, IsNotEmpty, IsEmail } from 'class-validator';
3 | import * as bcrypt from 'bcryptjs';
4 |
5 | @Entity()
6 | @Unique(['username'])
7 | export class Users {
8 | @PrimaryGeneratedColumn()
9 | id: number;
10 |
11 | @Column()
12 | @MinLength(6)
13 | @IsEmail()
14 | @IsNotEmpty()
15 | username: string;
16 |
17 | @Column()
18 | @MinLength(6)
19 | @IsNotEmpty()
20 | password: string;
21 |
22 | @Column()
23 | @IsNotEmpty()
24 | role: string;
25 |
26 | hashPassword(): void {
27 | const salt = bcrypt.genSaltSync(10);
28 | this.password = bcrypt.hashSync(this.password, salt);
29 | }
30 |
31 | checkPassword(password: string): boolean {
32 | return bcrypt.compareSync(password, this.password);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { takeUntil } from 'rxjs/operators';
2 | import { UtilsService } from './shared/services/utils.service';
3 | import { Component, OnInit, OnDestroy } from '@angular/core';
4 | import { Subject } from 'rxjs';
5 |
6 | @Component({
7 | selector: 'app-root',
8 | templateUrl: './app.component.html',
9 | styleUrls: ['./app.component.scss'],
10 | })
11 | export class AppComponent implements OnInit, OnDestroy {
12 | opened = false;
13 | private destroy$ = new Subject();
14 |
15 | constructor(private utilsSvc: UtilsService) {}
16 |
17 | ngOnInit(): void {
18 | this.utilsSvc.sidebarOpened$
19 | .pipe(takeUntil(this.destroy$))
20 | .subscribe((res: boolean) => (this.opened = res));
21 | }
22 |
23 | ngOnDestroy(): void {
24 | this.destroy$.next({});
25 | this.destroy$.complete();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting()
21 | );
22 | // Then we find all the tests.
23 | const context = require.context('./', true, /\.spec\.ts$/);
24 | // And load the modules.
25 | context.keys().map(context);
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | # Only exists if Bazel was run
8 | /bazel-out
9 |
10 | # dependencies
11 | /node_modules
12 |
13 | # profiling files
14 | chrome-profiler-events*.json
15 | speed-measure-plugin*.json
16 |
17 | # IDEs and editors
18 | /.idea
19 | .project
20 | .classpath
21 | .c9/
22 | *.launch
23 | .settings/
24 | *.sublime-workspace
25 |
26 | # IDE - VSCode
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 | .history/*
33 |
34 | # misc
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 | API/node_modules/*
48 |
--------------------------------------------------------------------------------
/API/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "login_roles",
3 | "version": "0.0.1",
4 | "description": "Awesome project developed with TypeORM.",
5 | "devDependencies": {
6 | "@types/bcryptjs": "^2.4.2",
7 | "@types/cors": "^2.8.6",
8 | "@types/express": "^4.17.7",
9 | "@types/jsonwebtoken": "^8.5.0",
10 | "@types/node": "^8.10.61",
11 | "ts-node-dev": "^1.0.0-pre.51",
12 | "typescript": "^3.9.6"
13 | },
14 | "dependencies": {
15 | "bcryptjs": "^2.4.3",
16 | "class-validator": "^0.11.1",
17 | "cors": "^2.8.5",
18 | "express": "^4.15.4",
19 | "helmet": "^3.23.3",
20 | "jsonwebtoken": "^8.5.1",
21 | "mysql": "^2.18.1",
22 | "reflect-metadata": "^0.1.10",
23 | "ts-node": "^8.10.2",
24 | "typeorm": "^0.2.25"
25 | },
26 | "scripts": {
27 | "tsc": "tsc",
28 | "dev": "ts-node-dev --respawn --transpile-only ./src/index.ts"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # For the full list of supported browsers by the Angular framework, please see:
6 | # https://angular.io/guide/browser-support
7 |
8 | # You can see what browsers were selected by your queries by running:
9 | # npx browserslist
10 |
11 | last 1 Chrome version
12 | last 1 Firefox version
13 | last 2 Edge major versions
14 | last 2 Safari major versions
15 | last 2 iOS major versions
16 | Firefox ESR
17 | not IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line.
18 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
19 |
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Protractor configuration file, see link for more information
3 | // https://github.com/angular/protractor/blob/master/lib/config.ts
4 |
5 | const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter');
6 |
7 | /**
8 | * @type { import("protractor").Config }
9 | */
10 | exports.config = {
11 | allScriptsTimeout: 11000,
12 | specs: [
13 | './src/**/*.e2e-spec.ts'
14 | ],
15 | capabilities: {
16 | browserName: 'chrome'
17 | },
18 | directConnect: true,
19 | baseUrl: 'http://localhost:4200/',
20 | framework: 'jasmine',
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000,
24 | print: function() {}
25 | },
26 | onPrepare() {
27 | require('ts-node').register({
28 | project: require('path').join(__dirname, './tsconfig.json')
29 | });
30 | jasmine.getEnv().addReporter(new SpecReporter({
31 | spec: {
32 | displayStacktrace: StacktraceOption.PRETTY
33 | }
34 | }));
35 | }
36 | };
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { CheckLoginGuard } from '@shared/guards/check-login.guard';
5 | const routes: Routes = [
6 | {
7 | path: '',
8 | loadChildren: () =>
9 | import('./pages/home/home.module').then((m) => m.HomeModule),
10 | },
11 | {
12 | path: 'notFound',
13 | loadChildren: () =>
14 | import('./pages/not-found/not-found.module').then(
15 | (m) => m.NotFoundModule
16 | ),
17 | },
18 | {
19 | path: 'admin',
20 | loadChildren: () =>
21 | import('./pages/admin/admin.module').then((m) => m.AdminModule),
22 | },
23 | {
24 | path: 'login',
25 | loadChildren: () =>
26 | import('./pages/auth/login/login.module').then((m) => m.LoginModule),
27 | canActivate: [CheckLoginGuard],
28 | },
29 | ];
30 |
31 | @NgModule({
32 | imports: [RouterModule.forRoot(routes)],
33 | exports: [RouterModule],
34 | })
35 | export class AppRoutingModule {}
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Bezael Pérez
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/login'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(async(() => {
7 | TestBed.configureTestingModule({
8 | imports: [
9 | RouterTestingModule
10 | ],
11 | declarations: [
12 | AppComponent
13 | ],
14 | }).compileComponents();
15 | }));
16 |
17 | it('should create the app', () => {
18 | const fixture = TestBed.createComponent(AppComponent);
19 | const app = fixture.componentInstance;
20 | expect(app).toBeTruthy();
21 | });
22 |
23 | it(`should have as title 'login'`, () => {
24 | const fixture = TestBed.createComponent(AppComponent);
25 | const app = fixture.componentInstance;
26 | expect(app.title).toEqual('login');
27 | });
28 |
29 | it('should render title', () => {
30 | const fixture = TestBed.createComponent(AppComponent);
31 | fixture.detectChanges();
32 | const compiled = fixture.nativeElement;
33 | expect(compiled.querySelector('.content span').textContent).toContain('login app is running!');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Login
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.0.2.
4 |
5 | ## Development server
6 |
7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Code scaffolding
10 |
11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12 |
13 | ## Build
14 |
15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
16 |
17 | ## Running unit tests
18 |
19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20 |
21 | ## Running end-to-end tests
22 |
23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
28 |
29 | ## License
30 |
31 | This project uses the following license: [MIT]()
32 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { ReactiveFormsModule } from '@angular/forms';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { NgModule } from '@angular/core';
4 |
5 | import { AppRoutingModule } from './app-routing.module';
6 | import { AppComponent } from './app.component';
7 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
8 | import { HeaderComponent } from '@shared/components/header/header.component';
9 | import { FooterComponent } from '@shared/components/footer/footer.component';
10 | import { MaterialModule } from '@app/material.module';
11 | import { SidebarModule } from '@shared/components/sidebar/sidebar.module';
12 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
13 |
14 | import { AdminInterceptor } from '@shared/interceptors/admin-interceptor';
15 |
16 | @NgModule({
17 | declarations: [AppComponent, HeaderComponent, FooterComponent],
18 | imports: [
19 | BrowserModule,
20 | AppRoutingModule,
21 | BrowserAnimationsModule,
22 | MaterialModule,
23 | SidebarModule,
24 | HttpClientModule,
25 | ReactiveFormsModule,
26 | ],
27 | providers: [
28 | { provide: HTTP_INTERCEPTORS, useClass: AdminInterceptor, multi: true },
29 | ],
30 | bootstrap: [AppComponent],
31 | })
32 | export class AppModule {}
33 |
--------------------------------------------------------------------------------
/src/app/material.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { MatToolbarModule } from '@angular/material/toolbar';
3 | import { MatSidenavModule } from '@angular/material/sidenav';
4 | import { MatButtonModule } from '@angular/material/button';
5 | import { MatMenuModule } from '@angular/material/menu';
6 | import { MatListModule } from '@angular/material/list';
7 | import { MatIconModule } from '@angular/material/icon';
8 | import { MatInputModule } from '@angular/material/input';
9 | import { MatCardModule } from '@angular/material/card';
10 | import { MatTableModule } from '@angular/material/table';
11 | import { MatSortModule } from '@angular/material/sort';
12 | import { MatDialogModule } from '@angular/material/dialog';
13 | import { MatOptionModule } from '@angular/material/core';
14 | import { MatSelectModule } from '@angular/material/select';
15 |
16 | const myModules = [
17 | MatToolbarModule,
18 | MatSidenavModule,
19 | MatButtonModule,
20 | MatMenuModule,
21 | MatListModule,
22 | MatIconModule,
23 | MatInputModule,
24 | MatCardModule,
25 | MatTableModule,
26 | MatSortModule,
27 | MatDialogModule,
28 | MatOptionModule,
29 | MatSelectModule,
30 | ];
31 |
32 | @NgModule({
33 | imports: [...myModules],
34 | exports: [...myModules],
35 | })
36 | export class MaterialModule {}
37 |
--------------------------------------------------------------------------------
/src/app/shared/components/header/header.component.ts:
--------------------------------------------------------------------------------
1 | import { UserResponse } from './../../models/user.interface';
2 | import {
3 | Component,
4 | OnInit,
5 | Output,
6 | EventEmitter,
7 | OnDestroy,
8 | } from '@angular/core';
9 | import { Subject } from 'rxjs';
10 | import { AuthService } from '@auth/auth.service';
11 | import { takeUntil } from 'rxjs/operators';
12 | import { Roles } from '@app/shared/models/user.interface';
13 |
14 | @Component({
15 | selector: 'app-header',
16 | templateUrl: './header.component.html',
17 | styleUrls: ['./header.component.scss'],
18 | })
19 | export class HeaderComponent implements OnInit, OnDestroy {
20 | isAdmin = null;
21 | isLogged = false;
22 |
23 | private destroy$ = new Subject();
24 |
25 | @Output() toggleSidenav = new EventEmitter();
26 |
27 | constructor(private authSvc: AuthService) {}
28 |
29 | ngOnInit(): void {
30 | this.authSvc.user$
31 | .pipe(takeUntil(this.destroy$))
32 | .subscribe((user: UserResponse) => {
33 | this.isLogged = true;
34 | this.isAdmin = user?.role;
35 | });
36 | }
37 |
38 | ngOnDestroy(): void {
39 | this.destroy$.next({});
40 | this.destroy$.complete();
41 | }
42 |
43 | onToggleSidenav(): void {
44 | this.toggleSidenav.emit();
45 | }
46 |
47 | onLogout(): void {
48 | this.authSvc.logout();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/shared/utils/base-form-user.ts:
--------------------------------------------------------------------------------
1 | import { FormBuilder, Validators } from '@angular/forms';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable({ providedIn: 'root' })
5 | export class BaseFormUser {
6 | private isValidEmail = /\S+@\S+\.\S+/;
7 | errorMessage = null;
8 |
9 | constructor(private fb: FormBuilder) {}
10 |
11 | baseForm = this.fb.group({
12 | username: [
13 | '',
14 | [Validators.required, Validators.pattern(this.isValidEmail)],
15 | ],
16 | password: ['', [Validators.required, Validators.minLength(5)]],
17 | role: ['', [Validators.required]],
18 | });
19 |
20 | isValidField(field: string): boolean {
21 | this.getErrorMessage(field);
22 | return (
23 | (this.baseForm.get(field).touched || this.baseForm.get(field).dirty) &&
24 | !this.baseForm.get(field).valid
25 | );
26 | }
27 |
28 | private getErrorMessage(field: string): void {
29 | const { errors } = this.baseForm.get(field);
30 |
31 | if (errors) {
32 | const minlenght = errors?.minlength?.requiredLength;
33 | const messages = {
34 | required: 'You must enter a value.',
35 | pattern: 'Not a valid email.',
36 | minlength: `This field must be longer than ${minlenght} characters`,
37 | };
38 |
39 | const errorKey = Object.keys(errors).find(Boolean);
40 | this.errorMessage = messages[errorKey];
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, OnDestroy } from '@angular/core';
2 | import { Router } from '@angular/router';
3 |
4 | import { BaseFormUser } from '@shared/utils/base-form-user';
5 | import { AuthService } from '@auth/auth.service';
6 | import { Subscription } from 'rxjs';
7 | @Component({
8 | selector: 'app-login',
9 | templateUrl: './login.component.html',
10 | styleUrls: ['./login.component.scss'],
11 | })
12 | export class LoginComponent implements OnInit, OnDestroy {
13 | hide = true;
14 | private subscription: Subscription = new Subscription();
15 |
16 | constructor(
17 | private authSvc: AuthService,
18 | private router: Router,
19 | public loginForm: BaseFormUser
20 | ) {}
21 |
22 | ngOnInit(): void {
23 | this.loginForm.baseForm.get('role').setValidators(null);
24 | this.loginForm.baseForm.get('role').updateValueAndValidity();
25 | }
26 |
27 | ngOnDestroy(): void {
28 | this.subscription.unsubscribe();
29 | }
30 |
31 | onLogin(): void {
32 | if (this.loginForm.baseForm.invalid) {
33 | return;
34 | }
35 |
36 | const formValue = this.loginForm.baseForm.value;
37 | this.subscription.add(
38 | this.authSvc.login(formValue).subscribe((res) => {
39 | if (res) {
40 | this.router.navigate(['']);
41 | }
42 | })
43 | );
44 | }
45 |
46 | checkField(field: string): boolean {
47 | return this.loginForm.isValidField(field);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/app/pages/auth/login/login.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | LOGIN
5 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "login",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e",
11 | "server": "cd API && npm run dev",
12 | "dev": "concurrently \"npm run server\" \"npm run start\""
13 | },
14 | "private": true,
15 | "dependencies": {
16 | "@angular/animations": "~10.0.3",
17 | "@angular/cdk": "^10.1.1",
18 | "@angular/common": "~10.0.3",
19 | "@angular/compiler": "~10.0.3",
20 | "@angular/core": "~10.0.3",
21 | "@angular/forms": "~10.0.3",
22 | "@angular/material": "^10.1.1",
23 | "@angular/platform-browser": "~10.0.3",
24 | "@angular/platform-browser-dynamic": "~10.0.3",
25 | "@angular/router": "~10.0.3",
26 | "@auth0/angular-jwt": "^5.0.1",
27 | "concurrently": "^5.2.0",
28 | "rxjs": "~6.5.5",
29 | "tslib": "^2.0.0",
30 | "zone.js": "~0.10.3"
31 | },
32 | "devDependencies": {
33 | "@angular-devkit/build-angular": "~0.1000.2",
34 | "@angular/cli": "~10.0.2",
35 | "@angular/compiler-cli": "~10.0.3",
36 | "@types/node": "^12.11.1",
37 | "@types/jasmine": "~3.5.0",
38 | "@types/jasminewd2": "~2.0.3",
39 | "codelyzer": "^6.0.0",
40 | "jasmine-core": "~3.5.0",
41 | "jasmine-spec-reporter": "~5.0.0",
42 | "karma": "~5.0.0",
43 | "karma-chrome-launcher": "~3.1.0",
44 | "karma-coverage-istanbul-reporter": "~3.0.2",
45 | "karma-jasmine": "~3.3.0",
46 | "karma-jasmine-html-reporter": "^1.5.0",
47 | "protractor": "~7.0.0",
48 | "ts-node": "~8.3.0",
49 | "tslint": "~6.1.0",
50 | "typescript": "~3.9.5"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users.component.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 | | No. |
16 | {{ element.id }} |
17 |
18 |
19 |
20 |
21 | Role |
22 | {{ element.role }} |
23 |
24 |
25 |
26 |
27 | Username |
28 | {{ element.username }} |
29 |
30 |
31 |
32 | Actions |
33 |
34 |
35 |
38 |
41 |
42 | |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/app/pages/admin/services/users.service.ts:
--------------------------------------------------------------------------------
1 | import { catchError } from 'rxjs/operators';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable, throwError } from 'rxjs';
4 | import { Injectable } from '@angular/core';
5 | import { environment } from '@env/environment';
6 | import { User } from '@app/shared/models/user.interface';
7 |
8 | @Injectable({
9 | providedIn: 'root',
10 | })
11 | export class UsersService {
12 | constructor(private http: HttpClient) {}
13 |
14 | getAll(): Observable {
15 | return this.http
16 | .get(`${environment.API_URL}/users`)
17 | .pipe(catchError(this.handlerError));
18 | }
19 |
20 | getById(userId: number): Observable {
21 | return this.http
22 | .get(`${environment.API_URL}/users/${userId}`)
23 | .pipe(catchError(this.handlerError));
24 | }
25 |
26 | new(user: User): Observable {
27 | return this.http
28 | .post(`${environment.API_URL}/users`, user)
29 | .pipe(catchError(this.handlerError));
30 | }
31 |
32 | update(userId: number, user: User): Observable {
33 | return this.http
34 | .patch(`${environment.API_URL}/users/${userId}`, user)
35 | .pipe(catchError(this.handlerError));
36 | }
37 |
38 | delete(userId: number): Observable<{}> {
39 | return this.http
40 | .delete(`${environment.API_URL}/users/${userId}`)
41 | .pipe(catchError(this.handlerError));
42 | }
43 |
44 | handlerError(error): Observable {
45 | let errorMessage = 'Error unknown';
46 | if (error) {
47 | errorMessage = `Error ${error.message}`;
48 | }
49 | window.alert(errorMessage);
50 | return throwError(errorMessage);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/pages/admin/components/modal/modal.component.ts:
--------------------------------------------------------------------------------
1 | import { UsersService } from './../../services/users.service';
2 | import { Component, Inject, OnInit } from '@angular/core';
3 | import { MAT_DIALOG_DATA } from '@angular/material/dialog';
4 |
5 | import { BaseFormUser } from '@shared/utils/base-form-user';
6 | enum Action {
7 | EDIT = 'edit',
8 | NEW = 'new',
9 | }
10 |
11 | @Component({
12 | selector: 'app-modal',
13 | templateUrl: './modal.component.html',
14 | styleUrls: ['./modal.component.scss'],
15 | })
16 | export class ModalComponent implements OnInit {
17 | actionTODO = Action.NEW;
18 | showPasswordField = true;
19 | hide = true;
20 | constructor(
21 | @Inject(MAT_DIALOG_DATA) public data: any,
22 | public userForm: BaseFormUser,
23 | private userSvc: UsersService
24 | ) {}
25 |
26 | ngOnInit(): void {
27 | if (this.data?.user.hasOwnProperty('id')) {
28 | this.actionTODO = Action.EDIT;
29 | this.showPasswordField = false;
30 | this.userForm.baseForm.get('password').setValidators(null);
31 | this.userForm.baseForm.updateValueAndValidity();
32 | this.data.title = 'Edit user';
33 | this.pathFormData();
34 | }
35 | }
36 |
37 | onSave(): void {
38 | const formValue = this.userForm.baseForm.value;
39 | if (this.actionTODO === Action.NEW) {
40 | this.userSvc.new(formValue).subscribe((res) => {
41 | console.log('New ', res);
42 | });
43 | } else {
44 | const userId = this.data?.user?.id;
45 | this.userSvc.update(userId, formValue).subscribe((res) => {
46 | console.log('Update', res);
47 | });
48 | }
49 | }
50 |
51 | checkField(field: string): boolean {
52 | return this.userForm.isValidField(field);
53 | }
54 |
55 | private pathFormData(): void {
56 | this.userForm.baseForm.patchValue({
57 | username: this.data?.user?.username,
58 | role: this.data?.user?.role,
59 | });
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/pages/admin/components/modal/modal.component.html:
--------------------------------------------------------------------------------
1 | {{ data?.title }}
2 |
3 |
4 |
42 |
43 |
44 |
45 |
46 |
56 |
57 |
--------------------------------------------------------------------------------
/src/app/pages/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Router } from '@angular/router';
3 | import { Injectable } from '@angular/core';
4 | import { environment } from '@env/environment';
5 | import { Observable, throwError, BehaviorSubject } from 'rxjs';
6 |
7 | import { UserResponse, User, Roles } from '@shared/models/user.interface';
8 | import { catchError, map } from 'rxjs/operators';
9 | import { JwtHelperService } from '@auth0/angular-jwt';
10 |
11 | const helper = new JwtHelperService();
12 |
13 | @Injectable({
14 | providedIn: 'root',
15 | })
16 | export class AuthService {
17 | private user = new BehaviorSubject(null);
18 |
19 | constructor(private http: HttpClient, private router: Router) {
20 | this.checkToken();
21 | }
22 | get user$(): Observable {
23 | return this.user.asObservable();
24 | }
25 |
26 | get userValue(): UserResponse {
27 | return this.user.getValue();
28 | }
29 | login(authData: User): Observable {
30 | return this.http
31 | .post(`${environment.API_URL}/auth/login`, authData)
32 | .pipe(
33 | map((user: UserResponse) => {
34 | this.saveLocalStorage(user);
35 | this.user.next(user);
36 | return user;
37 | }),
38 | catchError((err) => this.handlerError(err))
39 | );
40 | }
41 |
42 | logout(): void {
43 | localStorage.removeItem('user');
44 | this.user.next(null);
45 | this.router.navigate(['/login']);
46 | }
47 |
48 | private checkToken(): void {
49 | const user = JSON.parse(localStorage.getItem('user')) || null;
50 |
51 | if (user) {
52 | const isExpired = helper.isTokenExpired(user.token);
53 |
54 | if (isExpired) {
55 | this.logout();
56 | } else {
57 | this.user.next(user);
58 | }
59 | }
60 | }
61 |
62 | private saveLocalStorage(user: UserResponse): void {
63 | const { userId, message, ...rest } = user;
64 | localStorage.setItem('user', JSON.stringify(rest));
65 | }
66 |
67 | private handlerError(err): Observable {
68 | let errorMessage = 'An errror occured retrienving data';
69 | if (err) {
70 | errorMessage = `Error: code ${err.message}`;
71 | }
72 | window.alert(errorMessage);
73 | return throwError(errorMessage);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/pages/admin/users/users.component.ts:
--------------------------------------------------------------------------------
1 | import { takeUntil } from 'rxjs/operators';
2 | import { UsersService } from './../services/users.service';
3 | import {
4 | AfterViewInit,
5 | Component,
6 | OnInit,
7 | ViewChild,
8 | OnDestroy,
9 | } from '@angular/core';
10 | import { MatTableDataSource } from '@angular/material/table';
11 | import { MatSort } from '@angular/material/sort';
12 | import { MatDialog } from '@angular/material/dialog';
13 | import { ModalComponent } from './../components/modal/modal.component';
14 | import { Subject } from 'rxjs';
15 | @Component({
16 | selector: 'app-users',
17 | templateUrl: './users.component.html',
18 | styleUrls: ['./users.component.scss'],
19 | })
20 | export class UsersComponent implements AfterViewInit, OnInit, OnDestroy {
21 | displayedColumns: string[] = ['id', 'role', 'username', 'actions'];
22 | dataSource = new MatTableDataSource();
23 |
24 | private destroy$ = new Subject();
25 |
26 | @ViewChild(MatSort) sort: MatSort;
27 | constructor(private userSvc: UsersService, private dialog: MatDialog) {}
28 |
29 | ngOnInit(): void {
30 | this.userSvc.getAll().subscribe((users) => {
31 | this.dataSource.data = users;
32 | });
33 | }
34 |
35 | ngAfterViewInit(): void {
36 | this.dataSource.sort = this.sort;
37 | }
38 | onDelete(userId: number): void {
39 | if (window.confirm('Do you really want remove this user')) {
40 | this.userSvc
41 | .delete(userId)
42 | .pipe(takeUntil(this.destroy$))
43 | .subscribe((res) => {
44 | window.alert(res);
45 | // Update result after deleting the user.
46 | this.userSvc.getAll().subscribe((users) => {
47 | this.dataSource.data = users;
48 | });
49 | });
50 | }
51 | }
52 |
53 | onOpenModal(user = {}): void {
54 | console.log('User->', user);
55 | let dialogRef = this.dialog.open(ModalComponent, {
56 | height: '400px',
57 | width: '600px',
58 | hasBackdrop: false,
59 | data: { title: 'New user', user },
60 | });
61 | dialogRef.afterClosed().subscribe(result => {
62 | console.log(`Dialog result: ${result}`, typeof result);
63 | // Update result after adding new user.
64 | this.userSvc.getAll().subscribe((users) => {
65 | this.dataSource.data = users;
66 | });
67 | });
68 | }
69 |
70 | ngOnDestroy(): void {
71 | this.destroy$.next({});
72 | this.destroy$.complete();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/API/src/controller/AuthController.ts:
--------------------------------------------------------------------------------
1 | import { getRepository } from 'typeorm';
2 | import { Request, Response } from 'express';
3 | import { Users } from '../entity/Users';
4 | import * as jwt from 'jsonwebtoken';
5 | import config from '../config/config';
6 | import { validate } from 'class-validator';
7 |
8 | class AuthController {
9 | static login = async (req: Request, res: Response) => {
10 | const { username, password } = req.body;
11 |
12 | if (!(username && password)) {
13 | return res.status(400).json({ message: ' Username & Password are required!' });
14 | }
15 |
16 | const userRepository = getRepository(Users);
17 | let user: Users;
18 |
19 | try {
20 | user = await userRepository.findOneOrFail({ where: { username } });
21 | } catch (e) {
22 | return res.status(400).json({ message: ' Username or password incorecct!' });
23 | }
24 |
25 | // Check password
26 | if (!user.checkPassword(password)) {
27 | return res.status(400).json({ message: 'Username or Password are incorrect!' });
28 | }
29 |
30 | const token = jwt.sign({ userId: user.id, username: user.username }, config.jwtSecret, { expiresIn: '1h' });
31 |
32 | res.json({ message: 'OK', token, userId: user.id, role: user.role });
33 | };
34 |
35 | static changePassword = async (req: Request, res: Response) => {
36 | const { userId } = res.locals.jwtPayload;
37 | const { oldPassword, newPassword } = req.body;
38 |
39 | if (!(oldPassword && newPassword)) {
40 | res.status(400).json({ message: 'Old password & new password are required' });
41 | }
42 |
43 | const userRepository = getRepository(Users);
44 | let user: Users;
45 |
46 | try {
47 | user = await userRepository.findOneOrFail(userId);
48 | } catch (e) {
49 | res.status(400).json({ message: 'Somenthing goes wrong!' });
50 | }
51 |
52 | if (!user.checkPassword(oldPassword)) {
53 | return res.status(401).json({ message: 'Check your old Password' });
54 | }
55 |
56 | user.password = newPassword;
57 | const validationOps = { validationError: { target: false, value: false } };
58 | const errors = await validate(user, validationOps);
59 |
60 | if (errors.length > 0) {
61 | return res.status(400).json(errors);
62 | }
63 |
64 | // Hash password
65 | user.hashPassword();
66 | userRepository.save(user);
67 |
68 | res.json({ message: 'Password change!' });
69 | };
70 | }
71 | export default AuthController;
72 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/API/src/controller/UserController.ts:
--------------------------------------------------------------------------------
1 | import { getRepository } from 'typeorm';
2 | import { Request, Response } from 'express';
3 | import { Users } from '../entity/Users';
4 | import { validate } from 'class-validator';
5 |
6 | export class UserController {
7 | static getAll = async (req: Request, res: Response) => {
8 | const userRepository = getRepository(Users);
9 | let users;
10 |
11 | try {
12 | users = await userRepository.find({ select: ['id', 'username', 'role'] });
13 | } catch (e) {
14 | res.status(404).json({ message: 'Somenthing goes wrong!' });
15 | }
16 |
17 | if (users.length > 0) {
18 | res.send(users);
19 | } else {
20 | res.status(404).json({ message: 'Not result' });
21 | }
22 | };
23 |
24 | static getById = async (req: Request, res: Response) => {
25 | const { id } = req.params;
26 | const userRepository = getRepository(Users);
27 | try {
28 | const user = await userRepository.findOneOrFail(id);
29 | res.send(user);
30 | } catch (e) {
31 | res.status(404).json({ message: 'Not result' });
32 | }
33 | };
34 |
35 | static new = async (req: Request, res: Response) => {
36 | const { username, password, role } = req.body;
37 | const user = new Users();
38 |
39 | user.username = username;
40 | user.password = password;
41 | user.role = role;
42 |
43 | // Validate
44 | const validationOpt = { validationError: { target: false, value: false } };
45 | const errors = await validate(user, validationOpt);
46 | if (errors.length > 0) {
47 | return res.status(400).json(errors);
48 | }
49 |
50 | // TODO: HASH PASSWORD
51 |
52 | const userRepository = getRepository(Users);
53 | try {
54 | user.hashPassword();
55 | await userRepository.save(user);
56 | } catch (e) {
57 | return res.status(409).json({ message: 'Username already exist' });
58 | }
59 | // All ok
60 | res.send('User created');
61 | };
62 |
63 | static edit = async (req: Request, res: Response) => {
64 | let user;
65 | const { id } = req.params;
66 | const { username, role } = req.body;
67 |
68 | const userRepository = getRepository(Users);
69 | // Try get user
70 | try {
71 | user = await userRepository.findOneOrFail(id);
72 | user.username = username;
73 | user.role = role;
74 | } catch (e) {
75 | return res.status(404).json({ message: 'User not found' });
76 | }
77 | const validationOpt = { validationError: { target: false, value: false } };
78 | const errors = await validate(user, validationOpt);
79 |
80 | if (errors.length > 0) {
81 | return res.status(400).json(errors);
82 | }
83 |
84 | // Try to save user
85 | try {
86 | await userRepository.save(user);
87 | } catch (e) {
88 | return res.status(409).json({ message: 'Username already in use' });
89 | }
90 |
91 | res.status(201).json({ message: 'User update' });
92 | };
93 |
94 | static delete = async (req: Request, res: Response) => {
95 | const { id } = req.params;
96 | const userRepository = getRepository(Users);
97 | let user: Users;
98 |
99 | try {
100 | user = await userRepository.findOneOrFail(id);
101 | } catch (e) {
102 | return res.status(404).json({ message: 'User not found' });
103 | }
104 |
105 | // Remove user
106 | userRepository.delete(id);
107 | res.status(201).json({ message: ' User deleted' });
108 | };
109 | }
110 |
111 | export default UserController;
112 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "align": {
5 | "options": [
6 | "parameters",
7 | "statements"
8 | ]
9 | },
10 | "array-type": false,
11 | "arrow-return-shorthand": true,
12 | "curly": true,
13 | "deprecation": {
14 | "severity": "warning"
15 | },
16 | "component-class-suffix": true,
17 | "contextual-lifecycle": true,
18 | "directive-class-suffix": true,
19 | "directive-selector": [
20 | true,
21 | "attribute",
22 | "app",
23 | "camelCase"
24 | ],
25 | "component-selector": [
26 | true,
27 | "element",
28 | "app",
29 | "kebab-case"
30 | ],
31 | "eofline": true,
32 | "import-blacklist": [
33 | true,
34 | "rxjs/Rx"
35 | ],
36 | "import-spacing": true,
37 | "indent": {
38 | "options": [
39 | "spaces"
40 | ]
41 | },
42 | "max-classes-per-file": false,
43 | "max-line-length": [
44 | true,
45 | 140
46 | ],
47 | "member-ordering": [
48 | true,
49 | {
50 | "order": [
51 | "static-field",
52 | "instance-field",
53 | "static-method",
54 | "instance-method"
55 | ]
56 | }
57 | ],
58 | "no-console": [
59 | true,
60 | "debug",
61 | "info",
62 | "time",
63 | "timeEnd",
64 | "trace"
65 | ],
66 | "no-empty": false,
67 | "no-inferrable-types": [
68 | true,
69 | "ignore-params"
70 | ],
71 | "no-non-null-assertion": true,
72 | "no-redundant-jsdoc": true,
73 | "no-switch-case-fall-through": true,
74 | "no-var-requires": false,
75 | "object-literal-key-quotes": [
76 | true,
77 | "as-needed"
78 | ],
79 | "quotemark": [
80 | true,
81 | "single"
82 | ],
83 | "semicolon": {
84 | "options": [
85 | "always"
86 | ]
87 | },
88 | "space-before-function-paren": {
89 | "options": {
90 | "anonymous": "never",
91 | "asyncArrow": "always",
92 | "constructor": "never",
93 | "method": "never",
94 | "named": "never"
95 | }
96 | },
97 | "typedef": [
98 | true,
99 | "call-signature"
100 | ],
101 | "typedef-whitespace": {
102 | "options": [
103 | {
104 | "call-signature": "nospace",
105 | "index-signature": "nospace",
106 | "parameter": "nospace",
107 | "property-declaration": "nospace",
108 | "variable-declaration": "nospace"
109 | },
110 | {
111 | "call-signature": "onespace",
112 | "index-signature": "onespace",
113 | "parameter": "onespace",
114 | "property-declaration": "onespace",
115 | "variable-declaration": "onespace"
116 | }
117 | ]
118 | },
119 | "variable-name": {
120 | "options": [
121 | "ban-keywords",
122 | "check-format",
123 | "allow-pascal-case"
124 | ]
125 | },
126 | "whitespace": {
127 | "options": [
128 | "check-branch",
129 | "check-decl",
130 | "check-operator",
131 | "check-separator",
132 | "check-type",
133 | "check-typecast"
134 | ]
135 | },
136 | "no-conflicting-lifecycle": true,
137 | "no-host-metadata-property": true,
138 | "no-input-rename": true,
139 | "no-inputs-metadata-property": true,
140 | "no-output-native": true,
141 | "no-output-on-prefix": true,
142 | "no-output-rename": true,
143 | "no-outputs-metadata-property": true,
144 | "template-banana-in-box": true,
145 | "template-no-negated-async": true,
146 | "use-lifecycle-interface": true,
147 | "use-pipe-transform-interface": true
148 | },
149 | "rulesDirectory": [
150 | "codelyzer"
151 | ]
152 | }
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "login": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:component": {
10 | "style": "scss"
11 | }
12 | },
13 | "root": "",
14 | "sourceRoot": "src",
15 | "prefix": "app",
16 | "architect": {
17 | "build": {
18 | "builder": "@angular-devkit/build-angular:browser",
19 | "options": {
20 | "outputPath": "dist/login",
21 | "index": "src/index.html",
22 | "main": "src/main.ts",
23 | "polyfills": "src/polyfills.ts",
24 | "tsConfig": "tsconfig.app.json",
25 | "aot": true,
26 | "assets": [
27 | "src/favicon.ico",
28 | "src/assets"
29 | ],
30 | "styles": [
31 | "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
32 | "src/styles.scss"
33 | ],
34 | "scripts": []
35 | },
36 | "configurations": {
37 | "production": {
38 | "fileReplacements": [
39 | {
40 | "replace": "src/environments/environment.ts",
41 | "with": "src/environments/environment.prod.ts"
42 | }
43 | ],
44 | "optimization": true,
45 | "outputHashing": "all",
46 | "sourceMap": false,
47 | "extractCss": true,
48 | "namedChunks": false,
49 | "extractLicenses": true,
50 | "vendorChunk": false,
51 | "buildOptimizer": true,
52 | "budgets": [
53 | {
54 | "type": "initial",
55 | "maximumWarning": "2mb",
56 | "maximumError": "5mb"
57 | },
58 | {
59 | "type": "anyComponentStyle",
60 | "maximumWarning": "6kb",
61 | "maximumError": "10kb"
62 | }
63 | ]
64 | }
65 | }
66 | },
67 | "serve": {
68 | "builder": "@angular-devkit/build-angular:dev-server",
69 | "options": {
70 | "browserTarget": "login:build"
71 | },
72 | "configurations": {
73 | "production": {
74 | "browserTarget": "login:build:production"
75 | }
76 | }
77 | },
78 | "extract-i18n": {
79 | "builder": "@angular-devkit/build-angular:extract-i18n",
80 | "options": {
81 | "browserTarget": "login:build"
82 | }
83 | },
84 | "test": {
85 | "builder": "@angular-devkit/build-angular:karma",
86 | "options": {
87 | "main": "src/test.ts",
88 | "polyfills": "src/polyfills.ts",
89 | "tsConfig": "tsconfig.spec.json",
90 | "karmaConfig": "karma.conf.js",
91 | "assets": [
92 | "src/favicon.ico",
93 | "src/assets"
94 | ],
95 | "styles": [
96 | "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
97 | "src/styles.scss"
98 | ],
99 | "scripts": []
100 | }
101 | },
102 | "lint": {
103 | "builder": "@angular-devkit/build-angular:tslint",
104 | "options": {
105 | "tsConfig": [
106 | "tsconfig.app.json",
107 | "tsconfig.spec.json",
108 | "e2e/tsconfig.json"
109 | ],
110 | "exclude": [
111 | "**/node_modules/**"
112 | ]
113 | }
114 | },
115 | "e2e": {
116 | "builder": "@angular-devkit/build-angular:protractor",
117 | "options": {
118 | "protractorConfig": "e2e/protractor.conf.js",
119 | "devServerTarget": "login:serve"
120 | },
121 | "configurations": {
122 | "production": {
123 | "devServerTarget": "login:serve:production"
124 | }
125 | }
126 | }
127 | }
128 | }
129 | },
130 | "defaultProject": "login",
131 | "cli": {
132 | "analytics": false
133 | }
134 | }
--------------------------------------------------------------------------------
/API/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "login_roles",
3 | "version": "0.0.1",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/bcryptjs": {
8 | "version": "2.4.2",
9 | "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz",
10 | "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==",
11 | "dev": true
12 | },
13 | "@types/body-parser": {
14 | "version": "1.19.0",
15 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
16 | "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
17 | "dev": true,
18 | "requires": {
19 | "@types/connect": "*",
20 | "@types/node": "*"
21 | }
22 | },
23 | "@types/color-name": {
24 | "version": "1.1.1",
25 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
26 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
27 | },
28 | "@types/connect": {
29 | "version": "3.4.33",
30 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
31 | "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
32 | "dev": true,
33 | "requires": {
34 | "@types/node": "*"
35 | }
36 | },
37 | "@types/cors": {
38 | "version": "2.8.6",
39 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
40 | "integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
41 | "dev": true,
42 | "requires": {
43 | "@types/express": "*"
44 | }
45 | },
46 | "@types/express": {
47 | "version": "4.17.7",
48 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
49 | "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
50 | "dev": true,
51 | "requires": {
52 | "@types/body-parser": "*",
53 | "@types/express-serve-static-core": "*",
54 | "@types/qs": "*",
55 | "@types/serve-static": "*"
56 | }
57 | },
58 | "@types/express-serve-static-core": {
59 | "version": "4.17.8",
60 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz",
61 | "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==",
62 | "dev": true,
63 | "requires": {
64 | "@types/node": "*",
65 | "@types/qs": "*",
66 | "@types/range-parser": "*"
67 | }
68 | },
69 | "@types/jsonwebtoken": {
70 | "version": "8.5.0",
71 | "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz",
72 | "integrity": "sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg==",
73 | "dev": true,
74 | "requires": {
75 | "@types/node": "*"
76 | }
77 | },
78 | "@types/mime": {
79 | "version": "2.0.2",
80 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz",
81 | "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==",
82 | "dev": true
83 | },
84 | "@types/node": {
85 | "version": "8.10.61",
86 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz",
87 | "integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==",
88 | "dev": true
89 | },
90 | "@types/qs": {
91 | "version": "6.9.3",
92 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz",
93 | "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==",
94 | "dev": true
95 | },
96 | "@types/range-parser": {
97 | "version": "1.2.3",
98 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
99 | "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
100 | "dev": true
101 | },
102 | "@types/serve-static": {
103 | "version": "1.13.4",
104 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz",
105 | "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==",
106 | "dev": true,
107 | "requires": {
108 | "@types/express-serve-static-core": "*",
109 | "@types/mime": "*"
110 | }
111 | },
112 | "@types/strip-bom": {
113 | "version": "3.0.0",
114 | "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
115 | "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
116 | "dev": true
117 | },
118 | "@types/strip-json-comments": {
119 | "version": "0.0.30",
120 | "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
121 | "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
122 | "dev": true
123 | },
124 | "@types/validator": {
125 | "version": "10.11.3",
126 | "resolved": "https://registry.npmjs.org/@types/validator/-/validator-10.11.3.tgz",
127 | "integrity": "sha512-GKF2VnEkMmEeEGvoo03ocrP9ySMuX1ypKazIYMlsjfslfBMhOAtC5dmEWKdJioW4lJN7MZRS88kalTsVClyQ9w=="
128 | },
129 | "accepts": {
130 | "version": "1.3.7",
131 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
132 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
133 | "requires": {
134 | "mime-types": "~2.1.24",
135 | "negotiator": "0.6.2"
136 | }
137 | },
138 | "ansi-regex": {
139 | "version": "5.0.0",
140 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
141 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
142 | },
143 | "ansi-styles": {
144 | "version": "3.2.1",
145 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
146 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
147 | "requires": {
148 | "color-convert": "^1.9.0"
149 | }
150 | },
151 | "any-promise": {
152 | "version": "1.3.0",
153 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
154 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
155 | },
156 | "anymatch": {
157 | "version": "3.1.1",
158 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
159 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
160 | "dev": true,
161 | "requires": {
162 | "normalize-path": "^3.0.0",
163 | "picomatch": "^2.0.4"
164 | }
165 | },
166 | "app-root-path": {
167 | "version": "3.0.0",
168 | "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz",
169 | "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw=="
170 | },
171 | "arg": {
172 | "version": "4.1.3",
173 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
174 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
175 | },
176 | "argparse": {
177 | "version": "1.0.10",
178 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
179 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
180 | "requires": {
181 | "sprintf-js": "~1.0.2"
182 | }
183 | },
184 | "array-find-index": {
185 | "version": "1.0.2",
186 | "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
187 | "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
188 | "dev": true
189 | },
190 | "array-flatten": {
191 | "version": "1.1.1",
192 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
193 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
194 | },
195 | "balanced-match": {
196 | "version": "1.0.0",
197 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
198 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
199 | },
200 | "base64-js": {
201 | "version": "1.3.1",
202 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
203 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
204 | },
205 | "bcryptjs": {
206 | "version": "2.4.3",
207 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
208 | "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
209 | },
210 | "bignumber.js": {
211 | "version": "9.0.0",
212 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
213 | "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
214 | },
215 | "binary-extensions": {
216 | "version": "2.1.0",
217 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
218 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
219 | "dev": true
220 | },
221 | "body-parser": {
222 | "version": "1.19.0",
223 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
224 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
225 | "requires": {
226 | "bytes": "3.1.0",
227 | "content-type": "~1.0.4",
228 | "debug": "2.6.9",
229 | "depd": "~1.1.2",
230 | "http-errors": "1.7.2",
231 | "iconv-lite": "0.4.24",
232 | "on-finished": "~2.3.0",
233 | "qs": "6.7.0",
234 | "raw-body": "2.4.0",
235 | "type-is": "~1.6.17"
236 | }
237 | },
238 | "bowser": {
239 | "version": "2.9.0",
240 | "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.9.0.tgz",
241 | "integrity": "sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA=="
242 | },
243 | "brace-expansion": {
244 | "version": "1.1.11",
245 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
246 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
247 | "requires": {
248 | "balanced-match": "^1.0.0",
249 | "concat-map": "0.0.1"
250 | }
251 | },
252 | "braces": {
253 | "version": "3.0.2",
254 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
255 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
256 | "dev": true,
257 | "requires": {
258 | "fill-range": "^7.0.1"
259 | }
260 | },
261 | "buffer": {
262 | "version": "5.6.0",
263 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
264 | "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
265 | "requires": {
266 | "base64-js": "^1.0.2",
267 | "ieee754": "^1.1.4"
268 | }
269 | },
270 | "buffer-equal-constant-time": {
271 | "version": "1.0.1",
272 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
273 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
274 | },
275 | "buffer-from": {
276 | "version": "1.1.1",
277 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
278 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
279 | },
280 | "bytes": {
281 | "version": "3.1.0",
282 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
283 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
284 | },
285 | "camelcase": {
286 | "version": "2.1.1",
287 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
288 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
289 | "dev": true
290 | },
291 | "camelcase-keys": {
292 | "version": "2.1.0",
293 | "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
294 | "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
295 | "dev": true,
296 | "requires": {
297 | "camelcase": "^2.0.0",
298 | "map-obj": "^1.0.0"
299 | }
300 | },
301 | "camelize": {
302 | "version": "1.0.0",
303 | "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
304 | "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
305 | },
306 | "chalk": {
307 | "version": "2.4.2",
308 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
309 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
310 | "requires": {
311 | "ansi-styles": "^3.2.1",
312 | "escape-string-regexp": "^1.0.5",
313 | "supports-color": "^5.3.0"
314 | }
315 | },
316 | "chokidar": {
317 | "version": "3.4.0",
318 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
319 | "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
320 | "dev": true,
321 | "requires": {
322 | "anymatch": "~3.1.1",
323 | "braces": "~3.0.2",
324 | "fsevents": "~2.1.2",
325 | "glob-parent": "~5.1.0",
326 | "is-binary-path": "~2.1.0",
327 | "is-glob": "~4.0.1",
328 | "normalize-path": "~3.0.0",
329 | "readdirp": "~3.4.0"
330 | }
331 | },
332 | "class-validator": {
333 | "version": "0.11.1",
334 | "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.11.1.tgz",
335 | "integrity": "sha512-6CGdjwJLmKw+sQbK5ZDo1v1yTajkqfPOUDWSYVIlhUiCh6Phy8sAnMFE2XKHAcKAdoOz4jJUQhjPQWPYUuHxrA==",
336 | "requires": {
337 | "@types/validator": "10.11.3",
338 | "google-libphonenumber": "^3.1.6",
339 | "validator": "12.0.0"
340 | }
341 | },
342 | "cli-highlight": {
343 | "version": "2.1.4",
344 | "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.4.tgz",
345 | "integrity": "sha512-s7Zofobm20qriqDoU9sXptQx0t2R9PEgac92mENNm7xaEe1hn71IIMsXMK+6encA6WRCWWxIGQbipr3q998tlQ==",
346 | "requires": {
347 | "chalk": "^3.0.0",
348 | "highlight.js": "^9.6.0",
349 | "mz": "^2.4.0",
350 | "parse5": "^5.1.1",
351 | "parse5-htmlparser2-tree-adapter": "^5.1.1",
352 | "yargs": "^15.0.0"
353 | },
354 | "dependencies": {
355 | "ansi-styles": {
356 | "version": "4.2.1",
357 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
358 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
359 | "requires": {
360 | "@types/color-name": "^1.1.1",
361 | "color-convert": "^2.0.1"
362 | }
363 | },
364 | "chalk": {
365 | "version": "3.0.0",
366 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
367 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
368 | "requires": {
369 | "ansi-styles": "^4.1.0",
370 | "supports-color": "^7.1.0"
371 | }
372 | },
373 | "color-convert": {
374 | "version": "2.0.1",
375 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
376 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
377 | "requires": {
378 | "color-name": "~1.1.4"
379 | }
380 | },
381 | "color-name": {
382 | "version": "1.1.4",
383 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
384 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
385 | },
386 | "find-up": {
387 | "version": "4.1.0",
388 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
389 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
390 | "requires": {
391 | "locate-path": "^5.0.0",
392 | "path-exists": "^4.0.0"
393 | }
394 | },
395 | "has-flag": {
396 | "version": "4.0.0",
397 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
398 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
399 | },
400 | "path-exists": {
401 | "version": "4.0.0",
402 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
403 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
404 | },
405 | "supports-color": {
406 | "version": "7.1.0",
407 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
408 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
409 | "requires": {
410 | "has-flag": "^4.0.0"
411 | }
412 | },
413 | "yargs": {
414 | "version": "15.4.1",
415 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
416 | "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
417 | "requires": {
418 | "cliui": "^6.0.0",
419 | "decamelize": "^1.2.0",
420 | "find-up": "^4.1.0",
421 | "get-caller-file": "^2.0.1",
422 | "require-directory": "^2.1.1",
423 | "require-main-filename": "^2.0.0",
424 | "set-blocking": "^2.0.0",
425 | "string-width": "^4.2.0",
426 | "which-module": "^2.0.0",
427 | "y18n": "^4.0.0",
428 | "yargs-parser": "^18.1.2"
429 | }
430 | }
431 | }
432 | },
433 | "cliui": {
434 | "version": "6.0.0",
435 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
436 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
437 | "requires": {
438 | "string-width": "^4.2.0",
439 | "strip-ansi": "^6.0.0",
440 | "wrap-ansi": "^6.2.0"
441 | }
442 | },
443 | "color-convert": {
444 | "version": "1.9.3",
445 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
446 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
447 | "requires": {
448 | "color-name": "1.1.3"
449 | }
450 | },
451 | "color-name": {
452 | "version": "1.1.3",
453 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
454 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
455 | },
456 | "concat-map": {
457 | "version": "0.0.1",
458 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
459 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
460 | },
461 | "content-disposition": {
462 | "version": "0.5.3",
463 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
464 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
465 | "requires": {
466 | "safe-buffer": "5.1.2"
467 | }
468 | },
469 | "content-security-policy-builder": {
470 | "version": "2.1.0",
471 | "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz",
472 | "integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ=="
473 | },
474 | "content-type": {
475 | "version": "1.0.4",
476 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
477 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
478 | },
479 | "cookie": {
480 | "version": "0.4.0",
481 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
482 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
483 | },
484 | "cookie-signature": {
485 | "version": "1.0.6",
486 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
487 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
488 | },
489 | "core-util-is": {
490 | "version": "1.0.2",
491 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
492 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
493 | },
494 | "cors": {
495 | "version": "2.8.5",
496 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
497 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
498 | "requires": {
499 | "object-assign": "^4",
500 | "vary": "^1"
501 | }
502 | },
503 | "currently-unhandled": {
504 | "version": "0.4.1",
505 | "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
506 | "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
507 | "dev": true,
508 | "requires": {
509 | "array-find-index": "^1.0.1"
510 | }
511 | },
512 | "dasherize": {
513 | "version": "2.0.0",
514 | "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz",
515 | "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
516 | },
517 | "dateformat": {
518 | "version": "1.0.12",
519 | "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
520 | "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
521 | "dev": true,
522 | "requires": {
523 | "get-stdin": "^4.0.1",
524 | "meow": "^3.3.0"
525 | }
526 | },
527 | "debug": {
528 | "version": "2.6.9",
529 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
530 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
531 | "requires": {
532 | "ms": "2.0.0"
533 | }
534 | },
535 | "decamelize": {
536 | "version": "1.2.0",
537 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
538 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
539 | },
540 | "depd": {
541 | "version": "1.1.2",
542 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
543 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
544 | },
545 | "destroy": {
546 | "version": "1.0.4",
547 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
548 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
549 | },
550 | "diff": {
551 | "version": "4.0.2",
552 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
553 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
554 | },
555 | "dont-sniff-mimetype": {
556 | "version": "1.1.0",
557 | "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz",
558 | "integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug=="
559 | },
560 | "dotenv": {
561 | "version": "6.2.0",
562 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
563 | "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w=="
564 | },
565 | "dynamic-dedupe": {
566 | "version": "0.3.0",
567 | "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
568 | "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
569 | "dev": true,
570 | "requires": {
571 | "xtend": "^4.0.0"
572 | }
573 | },
574 | "ecdsa-sig-formatter": {
575 | "version": "1.0.11",
576 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
577 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
578 | "requires": {
579 | "safe-buffer": "^5.0.1"
580 | }
581 | },
582 | "ee-first": {
583 | "version": "1.1.1",
584 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
585 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
586 | },
587 | "emoji-regex": {
588 | "version": "8.0.0",
589 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
590 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
591 | },
592 | "encodeurl": {
593 | "version": "1.0.2",
594 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
595 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
596 | },
597 | "error-ex": {
598 | "version": "1.3.2",
599 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
600 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
601 | "dev": true,
602 | "requires": {
603 | "is-arrayish": "^0.2.1"
604 | }
605 | },
606 | "escape-html": {
607 | "version": "1.0.3",
608 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
609 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
610 | },
611 | "escape-string-regexp": {
612 | "version": "1.0.5",
613 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
614 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
615 | },
616 | "esprima": {
617 | "version": "4.0.1",
618 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
619 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
620 | },
621 | "etag": {
622 | "version": "1.8.1",
623 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
624 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
625 | },
626 | "express": {
627 | "version": "4.17.1",
628 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
629 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
630 | "requires": {
631 | "accepts": "~1.3.7",
632 | "array-flatten": "1.1.1",
633 | "body-parser": "1.19.0",
634 | "content-disposition": "0.5.3",
635 | "content-type": "~1.0.4",
636 | "cookie": "0.4.0",
637 | "cookie-signature": "1.0.6",
638 | "debug": "2.6.9",
639 | "depd": "~1.1.2",
640 | "encodeurl": "~1.0.2",
641 | "escape-html": "~1.0.3",
642 | "etag": "~1.8.1",
643 | "finalhandler": "~1.1.2",
644 | "fresh": "0.5.2",
645 | "merge-descriptors": "1.0.1",
646 | "methods": "~1.1.2",
647 | "on-finished": "~2.3.0",
648 | "parseurl": "~1.3.3",
649 | "path-to-regexp": "0.1.7",
650 | "proxy-addr": "~2.0.5",
651 | "qs": "6.7.0",
652 | "range-parser": "~1.2.1",
653 | "safe-buffer": "5.1.2",
654 | "send": "0.17.1",
655 | "serve-static": "1.14.1",
656 | "setprototypeof": "1.1.1",
657 | "statuses": "~1.5.0",
658 | "type-is": "~1.6.18",
659 | "utils-merge": "1.0.1",
660 | "vary": "~1.1.2"
661 | }
662 | },
663 | "feature-policy": {
664 | "version": "0.3.0",
665 | "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
666 | "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ=="
667 | },
668 | "figlet": {
669 | "version": "1.4.0",
670 | "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.4.0.tgz",
671 | "integrity": "sha512-CxxIjEKHlqGosgXaIA+sikGDdV6KZOOlzPJnYuPgQlOSHZP5h9WIghYI30fyXnwEVeSH7Hedy72gC6zJrFC+SQ=="
672 | },
673 | "fill-range": {
674 | "version": "7.0.1",
675 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
676 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
677 | "dev": true,
678 | "requires": {
679 | "to-regex-range": "^5.0.1"
680 | }
681 | },
682 | "finalhandler": {
683 | "version": "1.1.2",
684 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
685 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
686 | "requires": {
687 | "debug": "2.6.9",
688 | "encodeurl": "~1.0.2",
689 | "escape-html": "~1.0.3",
690 | "on-finished": "~2.3.0",
691 | "parseurl": "~1.3.3",
692 | "statuses": "~1.5.0",
693 | "unpipe": "~1.0.0"
694 | }
695 | },
696 | "find-up": {
697 | "version": "1.1.2",
698 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
699 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
700 | "dev": true,
701 | "requires": {
702 | "path-exists": "^2.0.0",
703 | "pinkie-promise": "^2.0.0"
704 | }
705 | },
706 | "forwarded": {
707 | "version": "0.1.2",
708 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
709 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
710 | },
711 | "fresh": {
712 | "version": "0.5.2",
713 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
714 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
715 | },
716 | "fs.realpath": {
717 | "version": "1.0.0",
718 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
719 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
720 | },
721 | "fsevents": {
722 | "version": "2.1.3",
723 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
724 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
725 | "dev": true,
726 | "optional": true
727 | },
728 | "get-caller-file": {
729 | "version": "2.0.5",
730 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
731 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
732 | },
733 | "get-stdin": {
734 | "version": "4.0.1",
735 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
736 | "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
737 | "dev": true
738 | },
739 | "glob": {
740 | "version": "7.1.6",
741 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
742 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
743 | "requires": {
744 | "fs.realpath": "^1.0.0",
745 | "inflight": "^1.0.4",
746 | "inherits": "2",
747 | "minimatch": "^3.0.4",
748 | "once": "^1.3.0",
749 | "path-is-absolute": "^1.0.0"
750 | }
751 | },
752 | "glob-parent": {
753 | "version": "5.1.1",
754 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
755 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
756 | "dev": true,
757 | "requires": {
758 | "is-glob": "^4.0.1"
759 | }
760 | },
761 | "google-libphonenumber": {
762 | "version": "3.2.10",
763 | "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.10.tgz",
764 | "integrity": "sha512-TsckE9O8QgqaIeaOXPjcJa4/kX3BzFdO1oCbMfmUpRZckml4xJhjJVxaT9Mdt/VrZZkT9lX44eHAEWfJK1tHtw=="
765 | },
766 | "graceful-fs": {
767 | "version": "4.2.4",
768 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
769 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
770 | "dev": true
771 | },
772 | "growly": {
773 | "version": "1.3.0",
774 | "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
775 | "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
776 | "dev": true
777 | },
778 | "has-ansi": {
779 | "version": "2.0.0",
780 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
781 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
782 | "requires": {
783 | "ansi-regex": "^2.0.0"
784 | },
785 | "dependencies": {
786 | "ansi-regex": {
787 | "version": "2.1.1",
788 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
789 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
790 | }
791 | }
792 | },
793 | "has-flag": {
794 | "version": "3.0.0",
795 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
796 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
797 | },
798 | "helmet": {
799 | "version": "3.23.3",
800 | "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.23.3.tgz",
801 | "integrity": "sha512-U3MeYdzPJQhtvqAVBPntVgAvNSOJyagwZwyKsFdyRa8TV3pOKVFljalPOCxbw5Wwf2kncGhmP0qHjyazIdNdSA==",
802 | "requires": {
803 | "depd": "2.0.0",
804 | "dont-sniff-mimetype": "1.1.0",
805 | "feature-policy": "0.3.0",
806 | "helmet-crossdomain": "0.4.0",
807 | "helmet-csp": "2.10.0",
808 | "hide-powered-by": "1.1.0",
809 | "hpkp": "2.0.0",
810 | "hsts": "2.2.0",
811 | "nocache": "2.1.0",
812 | "referrer-policy": "1.2.0",
813 | "x-xss-protection": "1.3.0"
814 | },
815 | "dependencies": {
816 | "depd": {
817 | "version": "2.0.0",
818 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
819 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
820 | }
821 | }
822 | },
823 | "helmet-crossdomain": {
824 | "version": "0.4.0",
825 | "resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz",
826 | "integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
827 | },
828 | "helmet-csp": {
829 | "version": "2.10.0",
830 | "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.10.0.tgz",
831 | "integrity": "sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w==",
832 | "requires": {
833 | "bowser": "2.9.0",
834 | "camelize": "1.0.0",
835 | "content-security-policy-builder": "2.1.0",
836 | "dasherize": "2.0.0"
837 | }
838 | },
839 | "hide-powered-by": {
840 | "version": "1.1.0",
841 | "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz",
842 | "integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg=="
843 | },
844 | "highlight.js": {
845 | "version": "9.18.1",
846 | "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
847 | "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg=="
848 | },
849 | "hosted-git-info": {
850 | "version": "2.8.8",
851 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
852 | "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
853 | "dev": true
854 | },
855 | "hpkp": {
856 | "version": "2.0.0",
857 | "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz",
858 | "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI="
859 | },
860 | "hsts": {
861 | "version": "2.2.0",
862 | "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz",
863 | "integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==",
864 | "requires": {
865 | "depd": "2.0.0"
866 | },
867 | "dependencies": {
868 | "depd": {
869 | "version": "2.0.0",
870 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
871 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
872 | }
873 | }
874 | },
875 | "http-errors": {
876 | "version": "1.7.2",
877 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
878 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
879 | "requires": {
880 | "depd": "~1.1.2",
881 | "inherits": "2.0.3",
882 | "setprototypeof": "1.1.1",
883 | "statuses": ">= 1.5.0 < 2",
884 | "toidentifier": "1.0.0"
885 | },
886 | "dependencies": {
887 | "inherits": {
888 | "version": "2.0.3",
889 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
890 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
891 | }
892 | }
893 | },
894 | "iconv-lite": {
895 | "version": "0.4.24",
896 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
897 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
898 | "requires": {
899 | "safer-buffer": ">= 2.1.2 < 3"
900 | }
901 | },
902 | "ieee754": {
903 | "version": "1.1.13",
904 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
905 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
906 | },
907 | "indent-string": {
908 | "version": "2.1.0",
909 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
910 | "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
911 | "dev": true,
912 | "requires": {
913 | "repeating": "^2.0.0"
914 | }
915 | },
916 | "inflight": {
917 | "version": "1.0.6",
918 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
919 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
920 | "requires": {
921 | "once": "^1.3.0",
922 | "wrappy": "1"
923 | }
924 | },
925 | "inherits": {
926 | "version": "2.0.4",
927 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
928 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
929 | },
930 | "ipaddr.js": {
931 | "version": "1.9.1",
932 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
933 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
934 | },
935 | "is-arrayish": {
936 | "version": "0.2.1",
937 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
938 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
939 | "dev": true
940 | },
941 | "is-binary-path": {
942 | "version": "2.1.0",
943 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
944 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
945 | "dev": true,
946 | "requires": {
947 | "binary-extensions": "^2.0.0"
948 | }
949 | },
950 | "is-extglob": {
951 | "version": "2.1.1",
952 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
953 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
954 | "dev": true
955 | },
956 | "is-finite": {
957 | "version": "1.1.0",
958 | "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
959 | "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
960 | "dev": true
961 | },
962 | "is-fullwidth-code-point": {
963 | "version": "3.0.0",
964 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
965 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
966 | },
967 | "is-glob": {
968 | "version": "4.0.1",
969 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
970 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
971 | "dev": true,
972 | "requires": {
973 | "is-extglob": "^2.1.1"
974 | }
975 | },
976 | "is-number": {
977 | "version": "7.0.0",
978 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
979 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
980 | "dev": true
981 | },
982 | "is-utf8": {
983 | "version": "0.2.1",
984 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
985 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
986 | "dev": true
987 | },
988 | "is-wsl": {
989 | "version": "1.1.0",
990 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
991 | "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
992 | "dev": true
993 | },
994 | "isarray": {
995 | "version": "1.0.0",
996 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
997 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
998 | },
999 | "isexe": {
1000 | "version": "2.0.0",
1001 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1002 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
1003 | "dev": true
1004 | },
1005 | "js-yaml": {
1006 | "version": "3.14.0",
1007 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
1008 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
1009 | "requires": {
1010 | "argparse": "^1.0.7",
1011 | "esprima": "^4.0.0"
1012 | }
1013 | },
1014 | "jsonwebtoken": {
1015 | "version": "8.5.1",
1016 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
1017 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
1018 | "requires": {
1019 | "jws": "^3.2.2",
1020 | "lodash.includes": "^4.3.0",
1021 | "lodash.isboolean": "^3.0.3",
1022 | "lodash.isinteger": "^4.0.4",
1023 | "lodash.isnumber": "^3.0.3",
1024 | "lodash.isplainobject": "^4.0.6",
1025 | "lodash.isstring": "^4.0.1",
1026 | "lodash.once": "^4.0.0",
1027 | "ms": "^2.1.1",
1028 | "semver": "^5.6.0"
1029 | },
1030 | "dependencies": {
1031 | "ms": {
1032 | "version": "2.1.2",
1033 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1034 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1035 | }
1036 | }
1037 | },
1038 | "jwa": {
1039 | "version": "1.4.1",
1040 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
1041 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
1042 | "requires": {
1043 | "buffer-equal-constant-time": "1.0.1",
1044 | "ecdsa-sig-formatter": "1.0.11",
1045 | "safe-buffer": "^5.0.1"
1046 | }
1047 | },
1048 | "jws": {
1049 | "version": "3.2.2",
1050 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
1051 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
1052 | "requires": {
1053 | "jwa": "^1.4.1",
1054 | "safe-buffer": "^5.0.1"
1055 | }
1056 | },
1057 | "load-json-file": {
1058 | "version": "1.1.0",
1059 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
1060 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
1061 | "dev": true,
1062 | "requires": {
1063 | "graceful-fs": "^4.1.2",
1064 | "parse-json": "^2.2.0",
1065 | "pify": "^2.0.0",
1066 | "pinkie-promise": "^2.0.0",
1067 | "strip-bom": "^2.0.0"
1068 | }
1069 | },
1070 | "locate-path": {
1071 | "version": "5.0.0",
1072 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
1073 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
1074 | "requires": {
1075 | "p-locate": "^4.1.0"
1076 | }
1077 | },
1078 | "lodash.includes": {
1079 | "version": "4.3.0",
1080 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
1081 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
1082 | },
1083 | "lodash.isboolean": {
1084 | "version": "3.0.3",
1085 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
1086 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
1087 | },
1088 | "lodash.isinteger": {
1089 | "version": "4.0.4",
1090 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
1091 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
1092 | },
1093 | "lodash.isnumber": {
1094 | "version": "3.0.3",
1095 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
1096 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
1097 | },
1098 | "lodash.isplainobject": {
1099 | "version": "4.0.6",
1100 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
1101 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
1102 | },
1103 | "lodash.isstring": {
1104 | "version": "4.0.1",
1105 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
1106 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
1107 | },
1108 | "lodash.once": {
1109 | "version": "4.1.1",
1110 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
1111 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
1112 | },
1113 | "loud-rejection": {
1114 | "version": "1.6.0",
1115 | "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
1116 | "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
1117 | "dev": true,
1118 | "requires": {
1119 | "currently-unhandled": "^0.4.1",
1120 | "signal-exit": "^3.0.0"
1121 | }
1122 | },
1123 | "make-error": {
1124 | "version": "1.3.6",
1125 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
1126 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
1127 | },
1128 | "map-obj": {
1129 | "version": "1.0.1",
1130 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
1131 | "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
1132 | "dev": true
1133 | },
1134 | "media-typer": {
1135 | "version": "0.3.0",
1136 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
1137 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
1138 | },
1139 | "meow": {
1140 | "version": "3.7.0",
1141 | "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
1142 | "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
1143 | "dev": true,
1144 | "requires": {
1145 | "camelcase-keys": "^2.0.0",
1146 | "decamelize": "^1.1.2",
1147 | "loud-rejection": "^1.0.0",
1148 | "map-obj": "^1.0.1",
1149 | "minimist": "^1.1.3",
1150 | "normalize-package-data": "^2.3.4",
1151 | "object-assign": "^4.0.1",
1152 | "read-pkg-up": "^1.0.1",
1153 | "redent": "^1.0.0",
1154 | "trim-newlines": "^1.0.0"
1155 | }
1156 | },
1157 | "merge-descriptors": {
1158 | "version": "1.0.1",
1159 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
1160 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
1161 | },
1162 | "methods": {
1163 | "version": "1.1.2",
1164 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1165 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
1166 | },
1167 | "mime": {
1168 | "version": "1.6.0",
1169 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1170 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
1171 | },
1172 | "mime-db": {
1173 | "version": "1.44.0",
1174 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
1175 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
1176 | },
1177 | "mime-types": {
1178 | "version": "2.1.27",
1179 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
1180 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
1181 | "requires": {
1182 | "mime-db": "1.44.0"
1183 | }
1184 | },
1185 | "minimatch": {
1186 | "version": "3.0.4",
1187 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
1188 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
1189 | "requires": {
1190 | "brace-expansion": "^1.1.7"
1191 | }
1192 | },
1193 | "minimist": {
1194 | "version": "1.2.5",
1195 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
1196 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
1197 | "dev": true
1198 | },
1199 | "ms": {
1200 | "version": "2.0.0",
1201 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1202 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1203 | },
1204 | "mysql": {
1205 | "version": "2.18.1",
1206 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
1207 | "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
1208 | "requires": {
1209 | "bignumber.js": "9.0.0",
1210 | "readable-stream": "2.3.7",
1211 | "safe-buffer": "5.1.2",
1212 | "sqlstring": "2.3.1"
1213 | }
1214 | },
1215 | "mz": {
1216 | "version": "2.7.0",
1217 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
1218 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
1219 | "requires": {
1220 | "any-promise": "^1.0.0",
1221 | "object-assign": "^4.0.1",
1222 | "thenify-all": "^1.0.0"
1223 | }
1224 | },
1225 | "negotiator": {
1226 | "version": "0.6.2",
1227 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
1228 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
1229 | },
1230 | "nocache": {
1231 | "version": "2.1.0",
1232 | "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
1233 | "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
1234 | },
1235 | "node-notifier": {
1236 | "version": "5.4.3",
1237 | "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz",
1238 | "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==",
1239 | "dev": true,
1240 | "requires": {
1241 | "growly": "^1.3.0",
1242 | "is-wsl": "^1.1.0",
1243 | "semver": "^5.5.0",
1244 | "shellwords": "^0.1.1",
1245 | "which": "^1.3.0"
1246 | }
1247 | },
1248 | "normalize-package-data": {
1249 | "version": "2.5.0",
1250 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
1251 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
1252 | "dev": true,
1253 | "requires": {
1254 | "hosted-git-info": "^2.1.4",
1255 | "resolve": "^1.10.0",
1256 | "semver": "2 || 3 || 4 || 5",
1257 | "validate-npm-package-license": "^3.0.1"
1258 | }
1259 | },
1260 | "normalize-path": {
1261 | "version": "3.0.0",
1262 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
1263 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
1264 | "dev": true
1265 | },
1266 | "object-assign": {
1267 | "version": "4.1.1",
1268 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1269 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
1270 | },
1271 | "on-finished": {
1272 | "version": "2.3.0",
1273 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1274 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
1275 | "requires": {
1276 | "ee-first": "1.1.1"
1277 | }
1278 | },
1279 | "once": {
1280 | "version": "1.4.0",
1281 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1282 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1283 | "requires": {
1284 | "wrappy": "1"
1285 | }
1286 | },
1287 | "p-limit": {
1288 | "version": "2.3.0",
1289 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
1290 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
1291 | "requires": {
1292 | "p-try": "^2.0.0"
1293 | }
1294 | },
1295 | "p-locate": {
1296 | "version": "4.1.0",
1297 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
1298 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
1299 | "requires": {
1300 | "p-limit": "^2.2.0"
1301 | }
1302 | },
1303 | "p-try": {
1304 | "version": "2.2.0",
1305 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
1306 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
1307 | },
1308 | "parent-require": {
1309 | "version": "1.0.0",
1310 | "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
1311 | "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc="
1312 | },
1313 | "parse-json": {
1314 | "version": "2.2.0",
1315 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
1316 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
1317 | "dev": true,
1318 | "requires": {
1319 | "error-ex": "^1.2.0"
1320 | }
1321 | },
1322 | "parse5": {
1323 | "version": "5.1.1",
1324 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
1325 | "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="
1326 | },
1327 | "parse5-htmlparser2-tree-adapter": {
1328 | "version": "5.1.1",
1329 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-5.1.1.tgz",
1330 | "integrity": "sha512-CF+TKjXqoqyDwHqBhFQ+3l5t83xYi6fVT1tQNg+Ye0JRLnTxWvIroCjEp1A0k4lneHNBGnICUf0cfYVYGEazqw==",
1331 | "requires": {
1332 | "parse5": "^5.1.1"
1333 | }
1334 | },
1335 | "parseurl": {
1336 | "version": "1.3.3",
1337 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1338 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1339 | },
1340 | "path-exists": {
1341 | "version": "2.1.0",
1342 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
1343 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
1344 | "dev": true,
1345 | "requires": {
1346 | "pinkie-promise": "^2.0.0"
1347 | }
1348 | },
1349 | "path-is-absolute": {
1350 | "version": "1.0.1",
1351 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1352 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
1353 | },
1354 | "path-parse": {
1355 | "version": "1.0.6",
1356 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
1357 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
1358 | "dev": true
1359 | },
1360 | "path-to-regexp": {
1361 | "version": "0.1.7",
1362 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1363 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
1364 | },
1365 | "path-type": {
1366 | "version": "1.1.0",
1367 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
1368 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
1369 | "dev": true,
1370 | "requires": {
1371 | "graceful-fs": "^4.1.2",
1372 | "pify": "^2.0.0",
1373 | "pinkie-promise": "^2.0.0"
1374 | }
1375 | },
1376 | "picomatch": {
1377 | "version": "2.2.2",
1378 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
1379 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
1380 | "dev": true
1381 | },
1382 | "pify": {
1383 | "version": "2.3.0",
1384 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
1385 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
1386 | "dev": true
1387 | },
1388 | "pinkie": {
1389 | "version": "2.0.4",
1390 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
1391 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
1392 | "dev": true
1393 | },
1394 | "pinkie-promise": {
1395 | "version": "2.0.1",
1396 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
1397 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
1398 | "dev": true,
1399 | "requires": {
1400 | "pinkie": "^2.0.0"
1401 | }
1402 | },
1403 | "process-nextick-args": {
1404 | "version": "2.0.1",
1405 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1406 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
1407 | },
1408 | "proxy-addr": {
1409 | "version": "2.0.6",
1410 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
1411 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
1412 | "requires": {
1413 | "forwarded": "~0.1.2",
1414 | "ipaddr.js": "1.9.1"
1415 | }
1416 | },
1417 | "qs": {
1418 | "version": "6.7.0",
1419 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
1420 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
1421 | },
1422 | "range-parser": {
1423 | "version": "1.2.1",
1424 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1425 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1426 | },
1427 | "raw-body": {
1428 | "version": "2.4.0",
1429 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
1430 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
1431 | "requires": {
1432 | "bytes": "3.1.0",
1433 | "http-errors": "1.7.2",
1434 | "iconv-lite": "0.4.24",
1435 | "unpipe": "1.0.0"
1436 | }
1437 | },
1438 | "read-pkg": {
1439 | "version": "1.1.0",
1440 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
1441 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
1442 | "dev": true,
1443 | "requires": {
1444 | "load-json-file": "^1.0.0",
1445 | "normalize-package-data": "^2.3.2",
1446 | "path-type": "^1.0.0"
1447 | }
1448 | },
1449 | "read-pkg-up": {
1450 | "version": "1.0.1",
1451 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
1452 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
1453 | "dev": true,
1454 | "requires": {
1455 | "find-up": "^1.0.0",
1456 | "read-pkg": "^1.0.0"
1457 | }
1458 | },
1459 | "readable-stream": {
1460 | "version": "2.3.7",
1461 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
1462 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
1463 | "requires": {
1464 | "core-util-is": "~1.0.0",
1465 | "inherits": "~2.0.3",
1466 | "isarray": "~1.0.0",
1467 | "process-nextick-args": "~2.0.0",
1468 | "safe-buffer": "~5.1.1",
1469 | "string_decoder": "~1.1.1",
1470 | "util-deprecate": "~1.0.1"
1471 | }
1472 | },
1473 | "readdirp": {
1474 | "version": "3.4.0",
1475 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
1476 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
1477 | "dev": true,
1478 | "requires": {
1479 | "picomatch": "^2.2.1"
1480 | }
1481 | },
1482 | "redent": {
1483 | "version": "1.0.0",
1484 | "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
1485 | "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
1486 | "dev": true,
1487 | "requires": {
1488 | "indent-string": "^2.1.0",
1489 | "strip-indent": "^1.0.1"
1490 | }
1491 | },
1492 | "referrer-policy": {
1493 | "version": "1.2.0",
1494 | "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz",
1495 | "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA=="
1496 | },
1497 | "reflect-metadata": {
1498 | "version": "0.1.13",
1499 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
1500 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
1501 | },
1502 | "repeating": {
1503 | "version": "2.0.1",
1504 | "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
1505 | "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
1506 | "dev": true,
1507 | "requires": {
1508 | "is-finite": "^1.0.0"
1509 | }
1510 | },
1511 | "require-directory": {
1512 | "version": "2.1.1",
1513 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
1514 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
1515 | },
1516 | "require-main-filename": {
1517 | "version": "2.0.0",
1518 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
1519 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
1520 | },
1521 | "resolve": {
1522 | "version": "1.17.0",
1523 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
1524 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
1525 | "dev": true,
1526 | "requires": {
1527 | "path-parse": "^1.0.6"
1528 | }
1529 | },
1530 | "rimraf": {
1531 | "version": "2.7.1",
1532 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
1533 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
1534 | "dev": true,
1535 | "requires": {
1536 | "glob": "^7.1.3"
1537 | }
1538 | },
1539 | "safe-buffer": {
1540 | "version": "5.1.2",
1541 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1542 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1543 | },
1544 | "safer-buffer": {
1545 | "version": "2.1.2",
1546 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1547 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1548 | },
1549 | "sax": {
1550 | "version": "1.2.4",
1551 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
1552 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
1553 | },
1554 | "semver": {
1555 | "version": "5.7.1",
1556 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1557 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
1558 | },
1559 | "send": {
1560 | "version": "0.17.1",
1561 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
1562 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
1563 | "requires": {
1564 | "debug": "2.6.9",
1565 | "depd": "~1.1.2",
1566 | "destroy": "~1.0.4",
1567 | "encodeurl": "~1.0.2",
1568 | "escape-html": "~1.0.3",
1569 | "etag": "~1.8.1",
1570 | "fresh": "0.5.2",
1571 | "http-errors": "~1.7.2",
1572 | "mime": "1.6.0",
1573 | "ms": "2.1.1",
1574 | "on-finished": "~2.3.0",
1575 | "range-parser": "~1.2.1",
1576 | "statuses": "~1.5.0"
1577 | },
1578 | "dependencies": {
1579 | "ms": {
1580 | "version": "2.1.1",
1581 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
1582 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
1583 | }
1584 | }
1585 | },
1586 | "serve-static": {
1587 | "version": "1.14.1",
1588 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
1589 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
1590 | "requires": {
1591 | "encodeurl": "~1.0.2",
1592 | "escape-html": "~1.0.3",
1593 | "parseurl": "~1.3.3",
1594 | "send": "0.17.1"
1595 | }
1596 | },
1597 | "set-blocking": {
1598 | "version": "2.0.0",
1599 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
1600 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
1601 | },
1602 | "setprototypeof": {
1603 | "version": "1.1.1",
1604 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1605 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1606 | },
1607 | "sha.js": {
1608 | "version": "2.4.11",
1609 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
1610 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
1611 | "requires": {
1612 | "inherits": "^2.0.1",
1613 | "safe-buffer": "^5.0.1"
1614 | }
1615 | },
1616 | "shellwords": {
1617 | "version": "0.1.1",
1618 | "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
1619 | "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
1620 | "dev": true
1621 | },
1622 | "signal-exit": {
1623 | "version": "3.0.3",
1624 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
1625 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
1626 | "dev": true
1627 | },
1628 | "source-map": {
1629 | "version": "0.6.1",
1630 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1631 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
1632 | },
1633 | "source-map-support": {
1634 | "version": "0.5.19",
1635 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
1636 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
1637 | "requires": {
1638 | "buffer-from": "^1.0.0",
1639 | "source-map": "^0.6.0"
1640 | }
1641 | },
1642 | "spdx-correct": {
1643 | "version": "3.1.1",
1644 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
1645 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
1646 | "dev": true,
1647 | "requires": {
1648 | "spdx-expression-parse": "^3.0.0",
1649 | "spdx-license-ids": "^3.0.0"
1650 | }
1651 | },
1652 | "spdx-exceptions": {
1653 | "version": "2.3.0",
1654 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
1655 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
1656 | "dev": true
1657 | },
1658 | "spdx-expression-parse": {
1659 | "version": "3.0.1",
1660 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
1661 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
1662 | "dev": true,
1663 | "requires": {
1664 | "spdx-exceptions": "^2.1.0",
1665 | "spdx-license-ids": "^3.0.0"
1666 | }
1667 | },
1668 | "spdx-license-ids": {
1669 | "version": "3.0.5",
1670 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
1671 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
1672 | "dev": true
1673 | },
1674 | "sprintf-js": {
1675 | "version": "1.0.3",
1676 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
1677 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
1678 | },
1679 | "sqlstring": {
1680 | "version": "2.3.1",
1681 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
1682 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
1683 | },
1684 | "statuses": {
1685 | "version": "1.5.0",
1686 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1687 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1688 | },
1689 | "string-width": {
1690 | "version": "4.2.0",
1691 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
1692 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
1693 | "requires": {
1694 | "emoji-regex": "^8.0.0",
1695 | "is-fullwidth-code-point": "^3.0.0",
1696 | "strip-ansi": "^6.0.0"
1697 | }
1698 | },
1699 | "string_decoder": {
1700 | "version": "1.1.1",
1701 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
1702 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
1703 | "requires": {
1704 | "safe-buffer": "~5.1.0"
1705 | }
1706 | },
1707 | "strip-ansi": {
1708 | "version": "6.0.0",
1709 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
1710 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
1711 | "requires": {
1712 | "ansi-regex": "^5.0.0"
1713 | }
1714 | },
1715 | "strip-bom": {
1716 | "version": "2.0.0",
1717 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
1718 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
1719 | "dev": true,
1720 | "requires": {
1721 | "is-utf8": "^0.2.0"
1722 | }
1723 | },
1724 | "strip-indent": {
1725 | "version": "1.0.1",
1726 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
1727 | "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
1728 | "dev": true,
1729 | "requires": {
1730 | "get-stdin": "^4.0.1"
1731 | }
1732 | },
1733 | "strip-json-comments": {
1734 | "version": "2.0.1",
1735 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1736 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
1737 | "dev": true
1738 | },
1739 | "supports-color": {
1740 | "version": "5.5.0",
1741 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1742 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1743 | "requires": {
1744 | "has-flag": "^3.0.0"
1745 | }
1746 | },
1747 | "thenify": {
1748 | "version": "3.3.1",
1749 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1750 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1751 | "requires": {
1752 | "any-promise": "^1.0.0"
1753 | }
1754 | },
1755 | "thenify-all": {
1756 | "version": "1.6.0",
1757 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1758 | "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
1759 | "requires": {
1760 | "thenify": ">= 3.1.0 < 4"
1761 | }
1762 | },
1763 | "to-regex-range": {
1764 | "version": "5.0.1",
1765 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1766 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1767 | "dev": true,
1768 | "requires": {
1769 | "is-number": "^7.0.0"
1770 | }
1771 | },
1772 | "toidentifier": {
1773 | "version": "1.0.0",
1774 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1775 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
1776 | },
1777 | "tree-kill": {
1778 | "version": "1.2.2",
1779 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
1780 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
1781 | "dev": true
1782 | },
1783 | "trim-newlines": {
1784 | "version": "1.0.0",
1785 | "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
1786 | "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
1787 | "dev": true
1788 | },
1789 | "ts-node": {
1790 | "version": "8.10.2",
1791 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
1792 | "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
1793 | "requires": {
1794 | "arg": "^4.1.0",
1795 | "diff": "^4.0.1",
1796 | "make-error": "^1.1.1",
1797 | "source-map-support": "^0.5.17",
1798 | "yn": "3.1.1"
1799 | }
1800 | },
1801 | "ts-node-dev": {
1802 | "version": "1.0.0-pre.51",
1803 | "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.0.0-pre.51.tgz",
1804 | "integrity": "sha512-b+OMsGtxYDsPPN2CMKcIYSwffTSDFB4pzna+10mTwIvl6DLw04ge9VfyTycfKEQ2ZSWt+ecWCylNfZJIyUWs/Q==",
1805 | "dev": true,
1806 | "requires": {
1807 | "chokidar": "^3.4.0",
1808 | "dateformat": "~1.0.4-1.2.3",
1809 | "dynamic-dedupe": "^0.3.0",
1810 | "minimist": "^1.2.5",
1811 | "mkdirp": "^1.0.4",
1812 | "node-notifier": "^5.4.0",
1813 | "resolve": "^1.0.0",
1814 | "rimraf": "^2.6.1",
1815 | "source-map-support": "^0.5.12",
1816 | "tree-kill": "^1.2.2",
1817 | "ts-node": "^8.10.2",
1818 | "tsconfig": "^7.0.0"
1819 | },
1820 | "dependencies": {
1821 | "mkdirp": {
1822 | "version": "1.0.4",
1823 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1824 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1825 | "dev": true
1826 | },
1827 | "ts-node": {
1828 | "version": "8.10.2",
1829 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
1830 | "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
1831 | "dev": true,
1832 | "requires": {
1833 | "arg": "^4.1.0",
1834 | "diff": "^4.0.1",
1835 | "make-error": "^1.1.1",
1836 | "source-map-support": "^0.5.17",
1837 | "yn": "3.1.1"
1838 | }
1839 | }
1840 | }
1841 | },
1842 | "tsconfig": {
1843 | "version": "7.0.0",
1844 | "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
1845 | "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
1846 | "dev": true,
1847 | "requires": {
1848 | "@types/strip-bom": "^3.0.0",
1849 | "@types/strip-json-comments": "0.0.30",
1850 | "strip-bom": "^3.0.0",
1851 | "strip-json-comments": "^2.0.0"
1852 | },
1853 | "dependencies": {
1854 | "strip-bom": {
1855 | "version": "3.0.0",
1856 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
1857 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
1858 | "dev": true
1859 | }
1860 | }
1861 | },
1862 | "tslib": {
1863 | "version": "1.13.0",
1864 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
1865 | "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q=="
1866 | },
1867 | "type-is": {
1868 | "version": "1.6.18",
1869 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1870 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1871 | "requires": {
1872 | "media-typer": "0.3.0",
1873 | "mime-types": "~2.1.24"
1874 | }
1875 | },
1876 | "typeorm": {
1877 | "version": "0.2.25",
1878 | "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.25.tgz",
1879 | "integrity": "sha512-yzQ995fyDy5wolSLK9cmjUNcmQdixaeEm2TnXB5HN++uKbs9TiR6Y7eYAHpDlAE8s9J1uniDBgytecCZVFergQ==",
1880 | "requires": {
1881 | "app-root-path": "^3.0.0",
1882 | "buffer": "^5.1.0",
1883 | "chalk": "^2.4.2",
1884 | "cli-highlight": "^2.0.0",
1885 | "debug": "^4.1.1",
1886 | "dotenv": "^6.2.0",
1887 | "glob": "^7.1.2",
1888 | "js-yaml": "^3.13.1",
1889 | "mkdirp": "^1.0.3",
1890 | "reflect-metadata": "^0.1.13",
1891 | "sha.js": "^2.4.11",
1892 | "tslib": "^1.9.0",
1893 | "xml2js": "^0.4.17",
1894 | "yargonaut": "^1.1.2",
1895 | "yargs": "^13.2.1"
1896 | },
1897 | "dependencies": {
1898 | "debug": {
1899 | "version": "4.1.1",
1900 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
1901 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
1902 | "requires": {
1903 | "ms": "^2.1.1"
1904 | }
1905 | },
1906 | "mkdirp": {
1907 | "version": "1.0.4",
1908 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1909 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
1910 | },
1911 | "ms": {
1912 | "version": "2.1.2",
1913 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1914 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1915 | }
1916 | }
1917 | },
1918 | "typescript": {
1919 | "version": "3.9.6",
1920 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
1921 | "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
1922 | "dev": true
1923 | },
1924 | "unpipe": {
1925 | "version": "1.0.0",
1926 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1927 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1928 | },
1929 | "util-deprecate": {
1930 | "version": "1.0.2",
1931 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1932 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
1933 | },
1934 | "utils-merge": {
1935 | "version": "1.0.1",
1936 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1937 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1938 | },
1939 | "validate-npm-package-license": {
1940 | "version": "3.0.4",
1941 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
1942 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
1943 | "dev": true,
1944 | "requires": {
1945 | "spdx-correct": "^3.0.0",
1946 | "spdx-expression-parse": "^3.0.0"
1947 | }
1948 | },
1949 | "validator": {
1950 | "version": "12.0.0",
1951 | "resolved": "https://registry.npmjs.org/validator/-/validator-12.0.0.tgz",
1952 | "integrity": "sha512-r5zA1cQBEOgYlesRmSEwc9LkbfNLTtji+vWyaHzRZUxCTHdsX3bd+sdHfs5tGZ2W6ILGGsxWxCNwT/h3IY/3ng=="
1953 | },
1954 | "vary": {
1955 | "version": "1.1.2",
1956 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1957 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1958 | },
1959 | "which": {
1960 | "version": "1.3.1",
1961 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1962 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1963 | "dev": true,
1964 | "requires": {
1965 | "isexe": "^2.0.0"
1966 | }
1967 | },
1968 | "which-module": {
1969 | "version": "2.0.0",
1970 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
1971 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
1972 | },
1973 | "wrap-ansi": {
1974 | "version": "6.2.0",
1975 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
1976 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
1977 | "requires": {
1978 | "ansi-styles": "^4.0.0",
1979 | "string-width": "^4.1.0",
1980 | "strip-ansi": "^6.0.0"
1981 | },
1982 | "dependencies": {
1983 | "ansi-styles": {
1984 | "version": "4.2.1",
1985 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
1986 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
1987 | "requires": {
1988 | "@types/color-name": "^1.1.1",
1989 | "color-convert": "^2.0.1"
1990 | }
1991 | },
1992 | "color-convert": {
1993 | "version": "2.0.1",
1994 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1995 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1996 | "requires": {
1997 | "color-name": "~1.1.4"
1998 | }
1999 | },
2000 | "color-name": {
2001 | "version": "1.1.4",
2002 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
2003 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
2004 | }
2005 | }
2006 | },
2007 | "wrappy": {
2008 | "version": "1.0.2",
2009 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
2010 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
2011 | },
2012 | "x-xss-protection": {
2013 | "version": "1.3.0",
2014 | "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz",
2015 | "integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg=="
2016 | },
2017 | "xml2js": {
2018 | "version": "0.4.23",
2019 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
2020 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
2021 | "requires": {
2022 | "sax": ">=0.6.0",
2023 | "xmlbuilder": "~11.0.0"
2024 | }
2025 | },
2026 | "xmlbuilder": {
2027 | "version": "11.0.1",
2028 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
2029 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
2030 | },
2031 | "xtend": {
2032 | "version": "4.0.2",
2033 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
2034 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
2035 | "dev": true
2036 | },
2037 | "y18n": {
2038 | "version": "4.0.0",
2039 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
2040 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
2041 | },
2042 | "yargonaut": {
2043 | "version": "1.1.4",
2044 | "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz",
2045 | "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==",
2046 | "requires": {
2047 | "chalk": "^1.1.1",
2048 | "figlet": "^1.1.1",
2049 | "parent-require": "^1.0.0"
2050 | },
2051 | "dependencies": {
2052 | "ansi-regex": {
2053 | "version": "2.1.1",
2054 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
2055 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
2056 | },
2057 | "ansi-styles": {
2058 | "version": "2.2.1",
2059 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
2060 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
2061 | },
2062 | "chalk": {
2063 | "version": "1.1.3",
2064 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
2065 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
2066 | "requires": {
2067 | "ansi-styles": "^2.2.1",
2068 | "escape-string-regexp": "^1.0.2",
2069 | "has-ansi": "^2.0.0",
2070 | "strip-ansi": "^3.0.0",
2071 | "supports-color": "^2.0.0"
2072 | }
2073 | },
2074 | "strip-ansi": {
2075 | "version": "3.0.1",
2076 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
2077 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
2078 | "requires": {
2079 | "ansi-regex": "^2.0.0"
2080 | }
2081 | },
2082 | "supports-color": {
2083 | "version": "2.0.0",
2084 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
2085 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
2086 | }
2087 | }
2088 | },
2089 | "yargs": {
2090 | "version": "13.3.2",
2091 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
2092 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
2093 | "requires": {
2094 | "cliui": "^5.0.0",
2095 | "find-up": "^3.0.0",
2096 | "get-caller-file": "^2.0.1",
2097 | "require-directory": "^2.1.1",
2098 | "require-main-filename": "^2.0.0",
2099 | "set-blocking": "^2.0.0",
2100 | "string-width": "^3.0.0",
2101 | "which-module": "^2.0.0",
2102 | "y18n": "^4.0.0",
2103 | "yargs-parser": "^13.1.2"
2104 | },
2105 | "dependencies": {
2106 | "ansi-regex": {
2107 | "version": "4.1.0",
2108 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
2109 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
2110 | },
2111 | "camelcase": {
2112 | "version": "5.3.1",
2113 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
2114 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
2115 | },
2116 | "cliui": {
2117 | "version": "5.0.0",
2118 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
2119 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
2120 | "requires": {
2121 | "string-width": "^3.1.0",
2122 | "strip-ansi": "^5.2.0",
2123 | "wrap-ansi": "^5.1.0"
2124 | }
2125 | },
2126 | "emoji-regex": {
2127 | "version": "7.0.3",
2128 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
2129 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
2130 | },
2131 | "find-up": {
2132 | "version": "3.0.0",
2133 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
2134 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
2135 | "requires": {
2136 | "locate-path": "^3.0.0"
2137 | }
2138 | },
2139 | "is-fullwidth-code-point": {
2140 | "version": "2.0.0",
2141 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
2142 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
2143 | },
2144 | "locate-path": {
2145 | "version": "3.0.0",
2146 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
2147 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
2148 | "requires": {
2149 | "p-locate": "^3.0.0",
2150 | "path-exists": "^3.0.0"
2151 | }
2152 | },
2153 | "p-locate": {
2154 | "version": "3.0.0",
2155 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
2156 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
2157 | "requires": {
2158 | "p-limit": "^2.0.0"
2159 | }
2160 | },
2161 | "path-exists": {
2162 | "version": "3.0.0",
2163 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
2164 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
2165 | },
2166 | "string-width": {
2167 | "version": "3.1.0",
2168 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
2169 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
2170 | "requires": {
2171 | "emoji-regex": "^7.0.1",
2172 | "is-fullwidth-code-point": "^2.0.0",
2173 | "strip-ansi": "^5.1.0"
2174 | }
2175 | },
2176 | "strip-ansi": {
2177 | "version": "5.2.0",
2178 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
2179 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
2180 | "requires": {
2181 | "ansi-regex": "^4.1.0"
2182 | }
2183 | },
2184 | "wrap-ansi": {
2185 | "version": "5.1.0",
2186 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
2187 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
2188 | "requires": {
2189 | "ansi-styles": "^3.2.0",
2190 | "string-width": "^3.0.0",
2191 | "strip-ansi": "^5.0.0"
2192 | }
2193 | },
2194 | "yargs-parser": {
2195 | "version": "13.1.2",
2196 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
2197 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
2198 | "requires": {
2199 | "camelcase": "^5.0.0",
2200 | "decamelize": "^1.2.0"
2201 | }
2202 | }
2203 | }
2204 | },
2205 | "yargs-parser": {
2206 | "version": "18.1.3",
2207 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
2208 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
2209 | "requires": {
2210 | "camelcase": "^5.0.0",
2211 | "decamelize": "^1.2.0"
2212 | },
2213 | "dependencies": {
2214 | "camelcase": {
2215 | "version": "5.3.1",
2216 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
2217 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
2218 | }
2219 | }
2220 | },
2221 | "yn": {
2222 | "version": "3.1.1",
2223 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
2224 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
2225 | }
2226 | }
2227 | }
2228 |
--------------------------------------------------------------------------------