From 9d518214ddbcbfdb8680c061ebca19dcbbd1906e Mon Sep 17 00:00:00 2001 From: Rafal Galka Date: Fri, 30 Oct 2020 15:15:26 +0100 Subject: [PATCH] feat(api): mongo closes #31 --- apps/api/.env.dist | 3 + apps/api/package.json | 3 + apps/api/src/app.module.ts | 10 +- apps/api/src/auth/auth.controller.spec.ts | 30 ---- apps/api/src/auth/auth.service.spec.ts | 5 +- apps/api/src/auth/auth.service.ts | 5 +- apps/api/src/auth/local.strategy.ts | 2 +- apps/api/src/config/index.ts | 4 + .../src/users/__tests__/users.service.mock.ts | 18 +- .../users/__tests__/users.testing.module.ts | 10 ++ apps/api/src/users/schema/index.ts | 1 + apps/api/src/users/schema/user.schema.ts | 17 ++ apps/api/src/users/users.module.ts | 3 + apps/api/src/users/users.service.spec.ts | 24 ++- apps/api/src/users/users.service.ts | 22 +-- libs/dto/auth/jwt-claims.dto.ts | 2 +- yarn.lock | 163 +++++++++++++++++- 17 files changed, 262 insertions(+), 60 deletions(-) create mode 100644 apps/api/.env.dist delete mode 100644 apps/api/src/auth/auth.controller.spec.ts create mode 100644 apps/api/src/users/__tests__/users.testing.module.ts create mode 100644 apps/api/src/users/schema/index.ts create mode 100644 apps/api/src/users/schema/user.schema.ts diff --git a/apps/api/.env.dist b/apps/api/.env.dist new file mode 100644 index 0000000..7baea7d --- /dev/null +++ b/apps/api/.env.dist @@ -0,0 +1,3 @@ +NODE_ENV=production +AUTH_SECRET= +MONGODB_URI= diff --git a/apps/api/package.json b/apps/api/package.json index 56bc5a8..1996839 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -25,8 +25,10 @@ "@nestjs/config": "^0.2.2", "@nestjs/core": "^6.11.7", "@nestjs/jwt": "^6.1.1", + "@nestjs/mongoose": "^7.0.2", "@nestjs/passport": "^6.1.1", "@nestjs/platform-express": "^6.11.7", + "mongoose": "^5.10.11", "passport": "^0.4.1", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", @@ -40,6 +42,7 @@ "@types/express": "^4.17.2", "@types/hapi__joi": "^16.0.9", "@types/jest": "^24.0.18", + "@types/mongoose": "^5.7.36", "@types/node": "^12.7.5", "@types/passport-jwt": "^3.0.3", "@types/passport-local": "^1.0.33", diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 0dc6e97..3cf01cc 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -1,5 +1,6 @@ import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { MongooseModule } from '@nestjs/mongoose'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { AuthModule } from './auth/auth.module'; @@ -15,6 +16,13 @@ import { UsersModule } from './users/users.module'; }), AuthModule, UsersModule, + MongooseModule.forRootAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => ({ + uri: configService.get('mongoDbUri'), + }), + inject: [ConfigService], + }), ], controllers: [AppController], providers: [AppService], diff --git a/apps/api/src/auth/auth.controller.spec.ts b/apps/api/src/auth/auth.controller.spec.ts deleted file mode 100644 index 661a650..0000000 --- a/apps/api/src/auth/auth.controller.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { configServiceMock } from '../config/__tests__/config.service.mock'; -import { usersServiceMockProvider } from '../users/__tests__/users.service.mock'; -import { AuthTestingModule } from './__tests__/auth.testing.module'; -import { AuthController } from './auth.controller'; -import { AuthService } from './auth.service'; - -describe('Auth Controller', () => { - let controller: AuthController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [AuthTestingModule], - controllers: [AuthController], - providers: [ - AuthService, - usersServiceMockProvider, - configServiceMock({ - auth: { secret: 'testsecret', tokenLifetime: '1s', refreshTokenLifetime: '2s' }, - }), - ], - }).compile(); - - controller = module.get(AuthController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/apps/api/src/auth/auth.service.spec.ts b/apps/api/src/auth/auth.service.spec.ts index 585875c..d894e05 100644 --- a/apps/api/src/auth/auth.service.spec.ts +++ b/apps/api/src/auth/auth.service.spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { configServiceMock } from '../config/__tests__/config.service.mock'; -import { usersServiceMockProvider } from '../users/__tests__/users.service.mock'; +import { UsersTestingModule } from '../users/__tests__/users.testing.module'; import { AuthTestingModule } from './__tests__/auth.testing.module'; import { AuthService } from './auth.service'; @@ -9,10 +9,9 @@ describe('AuthService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [AuthTestingModule], + imports: [AuthTestingModule, UsersTestingModule], providers: [ AuthService, - usersServiceMockProvider, configServiceMock({ auth: { secret: 'testsecret', tokenLifetime: '1s', refreshTokenLifetime: '2s' }, }), diff --git a/apps/api/src/auth/auth.service.ts b/apps/api/src/auth/auth.service.ts index bc9ca7c..0d0ac84 100644 --- a/apps/api/src/auth/auth.service.ts +++ b/apps/api/src/auth/auth.service.ts @@ -4,7 +4,8 @@ import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { existsSync, readFileSync, writeFileSync } from 'fs'; import { tmpdir } from 'os'; -import { User, UsersService } from '../users/users.service'; +import { User } from '../users/schema'; +import { UsersService } from '../users/users.service'; // TODO storage let refreshTokens: string[] = []; @@ -24,7 +25,7 @@ export class AuthService { } async validate(login: string, password: string): Promise { - const user = await this.users.findOne(login); + const user = await this.users.findByLogin(login); if (user && password === user.password) { return user; } diff --git a/apps/api/src/auth/local.strategy.ts b/apps/api/src/auth/local.strategy.ts index d4ece9e..4969efc 100644 --- a/apps/api/src/auth/local.strategy.ts +++ b/apps/api/src/auth/local.strategy.ts @@ -1,7 +1,7 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { IStrategyOptions, Strategy } from 'passport-local'; -import { User } from '../users/users.service'; +import { User } from '../users/schema'; import { AuthService } from './auth.service'; @Injectable() diff --git a/apps/api/src/config/index.ts b/apps/api/src/config/index.ts index b4ace2e..3ac5edb 100644 --- a/apps/api/src/config/index.ts +++ b/apps/api/src/config/index.ts @@ -10,6 +10,8 @@ export const configSchema = Joi.object({ AUTH_SECRET: Joi.string().required(), AUTH_TOKEN_LIFETIME: Joi.alternatives(Joi.string(), Joi.number()).default('1d'), AUTH_REFRESH_TOKEN_LIFETIME: Joi.alternatives(Joi.string(), Joi.number()).default('30d'), + + MONGODB_URI: Joi.string().required(), }); export interface Config { @@ -22,6 +24,7 @@ export interface Config { tokenLifetime: number | string; refreshTokenLifetime: number | string; }; + mongoDbUri: string; } export const configFactory = (): Config => { @@ -41,5 +44,6 @@ export const configFactory = (): Config => { tokenLifetime: process.env.AUTH_TOKEN_LIFETIME, refreshTokenLifetime: process.env.AUTH_REFRESH_TOKEN_LIFETIME, }, + mongoDbUri: process.env.MONGODB_URI, }; }; diff --git a/apps/api/src/users/__tests__/users.service.mock.ts b/apps/api/src/users/__tests__/users.service.mock.ts index 6723017..41b6fd1 100644 --- a/apps/api/src/users/__tests__/users.service.mock.ts +++ b/apps/api/src/users/__tests__/users.service.mock.ts @@ -1,16 +1,23 @@ import { Provider } from '@nestjs/common'; -import { User, UsersService } from '../users.service'; +import { getModelToken } from '@nestjs/mongoose'; +import { User } from '../schema/user.schema'; +import { UsersService } from '../users.service'; export class UsersServiceMock extends UsersService { protected readonly users: User[] = [ { - id: 1, + id: '1', login: 'demo', password: 'demo', }, + { + id: '2', + login: 'john', + password: 'doe', + }, ]; - async findOne(login: string): Promise { + async findByLogin(login: string): Promise { return this.users.find((user) => user.login === login); } } @@ -19,3 +26,8 @@ export const usersServiceMockProvider: Provider = { provide: UsersService, useClass: UsersServiceMock, }; + +export const userModelMockProvider: Provider = { + provide: getModelToken(User.name), + useValue: {}, +}; diff --git a/apps/api/src/users/__tests__/users.testing.module.ts b/apps/api/src/users/__tests__/users.testing.module.ts new file mode 100644 index 0000000..f71d518 --- /dev/null +++ b/apps/api/src/users/__tests__/users.testing.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { UsersService } from '../users.service'; +import { userModelMockProvider, usersServiceMockProvider } from './users.service.mock'; + +@Module({ + imports: [], + providers: [userModelMockProvider, usersServiceMockProvider], + exports: [UsersService], +}) +export class UsersTestingModule {} diff --git a/apps/api/src/users/schema/index.ts b/apps/api/src/users/schema/index.ts new file mode 100644 index 0000000..baedd6d --- /dev/null +++ b/apps/api/src/users/schema/index.ts @@ -0,0 +1 @@ +export * from './user.schema'; diff --git a/apps/api/src/users/schema/user.schema.ts b/apps/api/src/users/schema/user.schema.ts new file mode 100644 index 0000000..e73a56e --- /dev/null +++ b/apps/api/src/users/schema/user.schema.ts @@ -0,0 +1,17 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { Document } from 'mongoose'; + +export type UserDocument = User & Document; + +@Schema() +export class User { + id: string; + + @Prop({ required: true }) + login: string; + + @Prop({ required: true }) + password: string; +} + +export const UserSchema = SchemaFactory.createForClass(User); diff --git a/apps/api/src/users/users.module.ts b/apps/api/src/users/users.module.ts index 6204268..fb75365 100644 --- a/apps/api/src/users/users.module.ts +++ b/apps/api/src/users/users.module.ts @@ -1,7 +1,10 @@ import { Module } from '@nestjs/common'; +import { MongooseModule } from '@nestjs/mongoose'; +import { User, UserSchema } from './schema/user.schema'; import { UsersService } from './users.service'; @Module({ + imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])], exports: [UsersService], providers: [UsersService], }) diff --git a/apps/api/src/users/users.service.spec.ts b/apps/api/src/users/users.service.spec.ts index 62815ba..5960db8 100644 --- a/apps/api/src/users/users.service.spec.ts +++ b/apps/api/src/users/users.service.spec.ts @@ -1,12 +1,27 @@ +import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; +import { Model } from 'mongoose'; +import { User } from './schema'; +import { UserDocument } from './schema/user.schema'; import { UsersService } from './users.service'; describe('UsersService', () => { let service: UsersService; + let UserModel: Partial>; beforeEach(async () => { + UserModel = { + findOne: jest.fn(), + }; + const module: TestingModule = await Test.createTestingModule({ - providers: [UsersService], + providers: [ + UsersService, + { + provide: getModelToken(User.name), + useValue: UserModel, + }, + ], }).compile(); service = module.get(UsersService); @@ -15,4 +30,11 @@ describe('UsersService', () => { it('should be defined', () => { expect(service).toBeDefined(); }); + + it('findByLogin', async () => { + await service.findByLogin('john').then(() => { + expect(UserModel.findOne).toBeCalledWith({ login: 'john' }); + expect(UserModel.findOne).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/apps/api/src/users/users.service.ts b/apps/api/src/users/users.service.ts index 7e95a80..2770ae6 100644 --- a/apps/api/src/users/users.service.ts +++ b/apps/api/src/users/users.service.ts @@ -1,23 +1,13 @@ import { Injectable } from '@nestjs/common'; - -// TODO domain + storage -export interface User { - id: number; - login: string; - password: string; -} +import { InjectModel } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { User, UserDocument } from './schema'; @Injectable() export class UsersService { - protected readonly users: User[] = [ - { - id: 1, - login: 'demo', - password: 'demo', - }, - ]; + constructor(@InjectModel(User.name) protected userModel: Model) {} - async findOne(login: string): Promise { - return this.users.find((user) => user.login === login); + async findByLogin(login: string): Promise { + return this.userModel.findOne({ login }); } } diff --git a/libs/dto/auth/jwt-claims.dto.ts b/libs/dto/auth/jwt-claims.dto.ts index e465459..fb0930a 100644 --- a/libs/dto/auth/jwt-claims.dto.ts +++ b/libs/dto/auth/jwt-claims.dto.ts @@ -1,4 +1,4 @@ export interface JwtClaimsDto { - sub: number; + sub: string; login: string; } diff --git a/yarn.lock b/yarn.lock index f6d048d..bd5735d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1891,6 +1891,11 @@ "@types/jsonwebtoken" "7.2.8" jsonwebtoken "8.4.0" +"@nestjs/mongoose@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nestjs/mongoose/-/mongoose-7.0.2.tgz#cfb087de6e75e3fdc2e3a490abfa737009128da0" + integrity sha512-EXTLgZ3OuzE7ZDH628+otNxzKTaoQmgEC/KeUc/k1Na96BfTT1IUqMWaWEnzkI1ALLJQOsjKKDc0RgJ0nebZPg== + "@nestjs/passport@^6.1.1": version "6.1.1" resolved "https://registry.yarnpkg.com/@nestjs/passport/-/passport-6.1.1.tgz#991b8736c0ebffabb85a6455f0288055e5b52755" @@ -2110,6 +2115,13 @@ "@types/connect" "*" "@types/node" "*" +"@types/bson@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.0.3.tgz#30889d2ffde6262abbe38659364c631454999fbf" + integrity sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw== + dependencies: + "@types/node" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -2229,6 +2241,22 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/mongodb@*": + version "3.5.32" + resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.5.32.tgz#c3f72a9a157922e6b9a05690552abe8479e79232" + integrity sha512-lBV8D5S5UNlWihHYQkEebqQTRazm5SglwQ126ls03eeYk2NJN4P72udUxJtyuKSmSFKvhLeekfNoPcyFa3BNdQ== + dependencies: + "@types/bson" "*" + "@types/node" "*" + +"@types/mongoose@^5.7.36": + version "5.7.36" + resolved "https://registry.yarnpkg.com/@types/mongoose/-/mongoose-5.7.36.tgz#2dae28c63041c6afba8a83ea02969f463b3f1021" + integrity sha512-ggFXgvkHgCNlT35B9d/heDYfSqOSwTmQjkRoR32sObGV5Xjd0N0WWuYlLzqeCg94j4hYN/OZxZ1VNNLltX/IVQ== + dependencies: + "@types/mongodb" "*" + "@types/node" "*" + "@types/node@*", "@types/node@>= 8": version "13.7.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d" @@ -3578,6 +3606,14 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" + integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -3590,6 +3626,11 @@ bluebird@3.5.0: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" integrity sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw= +bluebird@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== + bluebird@^3.1.1, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3779,6 +3820,11 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +bson@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.5.tgz#2aaae98fcdf6750c0848b0cba1ddec3c73060a34" + integrity sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg== + btoa-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" @@ -5334,6 +5380,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +denque@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" + integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -8640,6 +8691,11 @@ jws@^3.1.5, jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +kareem@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.1.tgz#def12d9c941017fabfb00f873af95e9c99e1be87" + integrity sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw== + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -9316,6 +9372,11 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" +memory-pager@^1.0.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" + integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== + meow@^3.3.0, meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -9607,6 +9668,41 @@ moment@2.24.0: resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== +mongodb@3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.2.tgz#1154a4ac107bf1375112d83a29c5cf97704e96b6" + integrity sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA== + dependencies: + bl "^2.2.1" + bson "^1.1.4" + denque "^1.4.1" + require_optional "^1.0.1" + safe-buffer "^5.1.2" + optionalDependencies: + saslprep "^1.0.0" + +mongoose-legacy-pluralize@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" + integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== + +mongoose@^5.10.11: + version "5.10.11" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.10.11.tgz#4bef4a85d35f38eb45a0af27b276d2bfd2196b5c" + integrity sha512-R5BFitKW94/S/Z48w+X+qi/eto66jWBcVEVA8nYVkBoBAPFGq7JSYP/0uso+ZHs+7XjSzTuui+SUllzxIrf9yA== + dependencies: + bson "^1.1.4" + kareem "2.3.1" + mongodb "3.6.2" + mongoose-legacy-pluralize "1.0.2" + mpath "0.7.0" + mquery "3.2.2" + ms "2.1.2" + regexp-clone "1.0.0" + safe-buffer "5.2.1" + sift "7.0.1" + sliced "1.0.1" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -9619,6 +9715,22 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mpath@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.7.0.tgz#20e8102e276b71709d6e07e9f8d4d0f641afbfb8" + integrity sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg== + +mquery@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.2.tgz#e1383a3951852ce23e37f619a9b350f1fb3664e7" + integrity sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q== + dependencies: + bluebird "3.5.1" + debug "3.1.0" + regexp-clone "^1.0.0" + safe-buffer "5.1.2" + sliced "1.0.1" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9629,7 +9741,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.0.0, ms@^2.1.1: +ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -11686,6 +11798,11 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp-clone@1.0.0, regexp-clone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-1.0.0.tgz#222db967623277056260b992626354a04ce9bf63" + integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw== + regexp.prototype.flags@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -11861,6 +11978,14 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +require_optional@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" + integrity sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g== + dependencies: + resolve-from "^2.0.0" + semver "^5.1.0" + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -11873,6 +11998,11 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -12030,6 +12160,11 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -12062,6 +12197,13 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +saslprep@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" + integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== + dependencies: + sparse-bitfield "^3.0.3" + sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" @@ -12137,7 +12279,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -12283,6 +12425,11 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +sift@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08" + integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g== + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -12334,6 +12481,11 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" +sliced@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E= + slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -12475,6 +12627,13 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sparse-bitfield@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" + integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= + dependencies: + memory-pager "^1.0.2" + spawn-command@^0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"