diff --git a/src/config.ts b/src/config.ts index 5c3a8fe..76a0706 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,6 +2,6 @@ import * as dotenv from 'dotenv'; import * as path from 'path'; export function loadConfig() { - delete process.env.NODE_ENV; - dotenv.config({ path: path.join(__dirname, '../.env') }); + delete process.env.NODE_ENV; + dotenv.config({ path: path.join(__dirname, '../.env') }); } diff --git a/src/index.ts b/src/index.ts index 7110443..15f2efd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,16 +6,16 @@ import { Logger } from '../src/logger'; import { getServer } from './server'; async function bootstrap() { - await loadConfig(); + await loadConfig(); - const server = getServer(); - await server.start(); + const server = getServer(); + await server.start(); } bootstrap().catch((error: Error) => { - Logger.error(error); - if (error.stack) { - Logger.error(error.stack.split('\n')); - } - process.exit(1); + Logger.error(error); + if (error.stack) { + Logger.error(error.stack.split('\n')); + } + process.exit(1); }); diff --git a/src/interfaces/account-settings.ts b/src/interfaces/account-settings.ts index d78fe08..b3e2277 100644 --- a/src/interfaces/account-settings.ts +++ b/src/interfaces/account-settings.ts @@ -1,3 +1,3 @@ export interface AccountSettings { - itemsPerPage: number; + itemsPerPage: number; } diff --git a/src/logger.ts b/src/logger.ts index db17d11..dc4bfb0 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -5,33 +5,33 @@ import * as util from 'util'; import { getBindingError } from 'warthog'; export class Logger { - static info(...args: any[]) { - args = args.length === 1 ? args[0] : args; - console.log(util.inspect(args, { showHidden: false, depth: null })); - } - - static error(...args: any[]) { - args = args.length === 1 ? args[0] : args; - console.error(util.inspect(args, { showHidden: false, depth: null })); - } - - // static debug(...args: any[]) { - // console.debug(args); - // } - - static log(...args: any[]) { - console.log(args); - } - - static warn(...args: any[]) { - console.warn(args); - } - - // This takes a raw GraphQL error and pulls out the relevant info - static logGraphQLError(error: Error) { - console.error( - util.inspect(getBindingError(error), { showHidden: false, depth: null }) - ); - } + static info(...args: any[]) { + args = args.length === 1 ? args[0] : args; + console.log(util.inspect(args, { showHidden: false, depth: null })); + } + + static error(...args: any[]) { + args = args.length === 1 ? args[0] : args; + console.error(util.inspect(args, { showHidden: false, depth: null })); + } + + // static debug(...args: any[]) { + // console.debug(args); + // } + + static log(...args: any[]) { + console.log(args); + } + + static warn(...args: any[]) { + console.warn(args); + } + + // This takes a raw GraphQL error and pulls out the relevant info + static logGraphQLError(error: Error) { + console.error( + util.inspect(getBindingError(error), { showHidden: false, depth: null }) + ); + } } /* eslint-enable no-console */ diff --git a/src/modules/collection-item/collection-item.model.ts b/src/modules/collection-item/collection-item.model.ts index 16bd54b..e887890 100644 --- a/src/modules/collection-item/collection-item.model.ts +++ b/src/modules/collection-item/collection-item.model.ts @@ -5,53 +5,53 @@ import { Review } from '../review/review.model'; @Model() export class CollectionItem extends BaseModel { - @StringField({ nullable: true }) - customTitle?: string; - - @StringField({ nullable: true }) - customArtist?: string; - - @ManyToOne(() => User, (user: User) => user.collection) - user!: User; - - @ManyToOne(() => Item, (item: Item) => item.collectionItem) - itemDetails!: Item; - - @IntField({ nullable: true, default: 0 }) - plays?: number; - - // needs to be nullable for writes - // FIXME: This is calling the database even though apiOnly is true - // (Only occurs for mutation collectionItems, not collectionItem) - // TODO: The other problem seems to be that this.itemDetails doesn't exist by the time the resolver responds - // @StringField({ apiOnly: true, nullable: true }) - // get artist(): string { - // return this.itemDetails.artist; - // } - - // these fields are not required for the field resolvers to work - // however they may be required to make fields nullable - // @StringField({ apiOnly: true, nullable: true }) - // get title(): string { - // return this.itemDetails.title; - // } - - @StringField({ apiOnly: true, nullable: true }) - get mbid(): string | undefined { - return this.itemDetails.mbid; - } - - @OneToMany(() => Review, (review: Review) => review.collectionItem) - reviews?: Review[]; - - // FIXME: warthog codegen fails when using optional chaining - // @StringField({ apiOnly: true, nullable: true }) - // get rating(): string | undefined { - // return this.reviews?.pop()?.rating; // TODO: Do we need the second question mark? - // } - - // @StringField({ apiOnly: true, nullable: true }) - // get review(): string | undefined { - // return this.reviews?.pop()?.reviewText; - // } + @StringField({ nullable: true }) + customTitle?: string; + + @StringField({ nullable: true }) + customArtist?: string; + + @ManyToOne(() => User, (user: User) => user.collection) + user!: User; + + @ManyToOne(() => Item, (item: Item) => item.collectionItem) + itemDetails!: Item; + + @IntField({ nullable: true, default: 0 }) + plays?: number; + + // needs to be nullable for writes + // FIXME: This is calling the database even though apiOnly is true + // (Only occurs for mutation collectionItems, not collectionItem) + // TODO: The other problem seems to be that this.itemDetails doesn't exist by the time the resolver responds + // @StringField({ apiOnly: true, nullable: true }) + // get artist(): string { + // return this.itemDetails.artist; + // } + + // these fields are not required for the field resolvers to work + // however they may be required to make fields nullable + // @StringField({ apiOnly: true, nullable: true }) + // get title(): string { + // return this.itemDetails.title; + // } + + @StringField({ apiOnly: true, nullable: true }) + get mbid(): string | undefined { + return this.itemDetails.mbid; + } + + @OneToMany(() => Review, (review: Review) => review.collectionItem) + reviews?: Review[]; + + // FIXME: warthog codegen fails when using optional chaining + // @StringField({ apiOnly: true, nullable: true }) + // get rating(): string | undefined { + // return this.reviews?.pop()?.rating; // TODO: Do we need the second question mark? + // } + + // @StringField({ apiOnly: true, nullable: true }) + // get review(): string | undefined { + // return this.reviews?.pop()?.reviewText; + // } } diff --git a/src/modules/collection-item/collection-item.resolver.ts b/src/modules/collection-item/collection-item.resolver.ts index a3dfb8d..9fb9e6e 100644 --- a/src/modules/collection-item/collection-item.resolver.ts +++ b/src/modules/collection-item/collection-item.resolver.ts @@ -1,23 +1,23 @@ import { - Arg, - Args, - Mutation, - Query, - Resolver, - FieldResolver, - Root, - Ctx, + Arg, + Args, + Mutation, + Query, + Resolver, + FieldResolver, + Root, + Ctx, } from 'type-graphql'; import { Inject } from 'typedi'; import { Fields, StandardDeleteResponse, UserId, BaseContext } from 'warthog'; import { - CollectionItemCreateInput, - CollectionItemCreateManyArgs, - CollectionItemUpdateArgs, - CollectionItemWhereArgs, - CollectionItemWhereInput, - CollectionItemWhereUniqueInput, + CollectionItemCreateInput, + CollectionItemCreateManyArgs, + CollectionItemUpdateArgs, + CollectionItemWhereArgs, + CollectionItemWhereInput, + CollectionItemWhereUniqueInput, } from '../../../generated'; import { CollectionItem } from './collection-item.model'; @@ -27,137 +27,137 @@ import { Item } from '../item/item.model'; @Resolver(CollectionItem) export class CollectionItemResolver { - constructor( - @Inject('CollectionItemService') - public readonly service: CollectionItemService - ) {} - - @Query(() => [CollectionItem]) - async collectionItems( - @Args() { where, orderBy, limit, offset }: CollectionItemWhereArgs, - @Fields() fields: string[] - ): Promise { - // TODO: Be able to use fields here without breaking artist/title fieldResolvers - return this.service.find(where, orderBy, limit, offset); - } - - @Query(() => CollectionItem) - async collectionItem( - @Arg('where') where: CollectionItemWhereUniqueInput - ): Promise { - return this.service.findOne(where); - } - - @FieldResolver(() => String) - async artist( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load( - collectionItem - ); - return itemDetails.artist; - } - - @FieldResolver(() => String) - async title( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load( - collectionItem - ); - return itemDetails.title; - } - - // TODO: "Cannot return null for non-nullable field CollectionItem.mbid." - // @FieldResolver(() => String) - // async mbid(@Root() collectionItem: CollectionItem, @Ctx() ctx: BaseContext): Promise { - // let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load(collectionItem); - // if(itemDetails.mbid) { - // return itemDetails.mbid; - // } - // else { - // return ''; - // } - // } - - @FieldResolver(() => String) - async rating( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - let reviews = await ctx.dataLoader.loaders.CollectionItem.reviews.load( - collectionItem - ); - if (reviews.length > 0) { - return reviews[reviews.length - 1].rating; - } else { - return ''; - } - } - - @FieldResolver(() => String) - async reviewBody( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - // TODO: Only loas the most recent review - let reviews = await ctx.dataLoader.loaders.CollectionItem.reviews.load( - collectionItem - ); - if (reviews.length > 0) { - return reviews[reviews.length - 1].body; - } else { - return ''; - } - } - - @FieldResolver(() => [Item]) - itemDetails( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - return ctx.dataLoader.loaders.CollectionItem.itemDetails.load(collectionItem); - } - - @FieldResolver(() => [Item]) - reviews( - @Root() collectionItem: CollectionItem, - @Ctx() ctx: BaseContext - ): Promise { - return ctx.dataLoader.loaders.CollectionItem.reviews.load(collectionItem); - } - - @Mutation(() => CollectionItem) - async createCollectionItem( - @Arg('data') data: CollectionItemCreateInput, - @UserId() userId: string - ): Promise { - return this.service.create(data, userId); - } - - @Mutation(() => [CollectionItem]) - async createManyCollectionItems( - @Args() { data }: CollectionItemCreateManyArgs, - @UserId() userId: string - ): Promise { - return this.service.createMany(data, userId); - } - - @Mutation(() => CollectionItem) - async updateCollectionItem( - @Args() { data, where }: CollectionItemUpdateArgs, - @UserId() userId: string - ): Promise { - return this.service.update(data, where, userId); - } - - @Mutation(() => StandardDeleteResponse) - async deleteCollectionItem( - @Arg('where') where: CollectionItemWhereUniqueInput, - @UserId() userId: string - ): Promise { - return this.service.delete(where, userId); - } + constructor( + @Inject('CollectionItemService') + public readonly service: CollectionItemService + ) {} + + @Query(() => [CollectionItem]) + async collectionItems( + @Args() { where, orderBy, limit, offset }: CollectionItemWhereArgs, + @Fields() fields: string[] + ): Promise { + // TODO: Be able to use fields here without breaking artist/title fieldResolvers + return this.service.find(where, orderBy, limit, offset); + } + + @Query(() => CollectionItem) + async collectionItem( + @Arg('where') where: CollectionItemWhereUniqueInput + ): Promise { + return this.service.findOne(where); + } + + @FieldResolver(() => String) + async artist( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load( + collectionItem + ); + return itemDetails.artist; + } + + @FieldResolver(() => String) + async title( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load( + collectionItem + ); + return itemDetails.title; + } + + // TODO: "Cannot return null for non-nullable field CollectionItem.mbid." + // @FieldResolver(() => String) + // async mbid(@Root() collectionItem: CollectionItem, @Ctx() ctx: BaseContext): Promise { + // let itemDetails = await ctx.dataLoader.loaders.CollectionItem.itemDetails.load(collectionItem); + // if(itemDetails.mbid) { + // return itemDetails.mbid; + // } + // else { + // return ''; + // } + // } + + @FieldResolver(() => String) + async rating( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + let reviews = await ctx.dataLoader.loaders.CollectionItem.reviews.load( + collectionItem + ); + if (reviews.length > 0) { + return reviews[reviews.length - 1].rating; + } else { + return ''; + } + } + + @FieldResolver(() => String) + async reviewBody( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + // TODO: Only loas the most recent review + let reviews = await ctx.dataLoader.loaders.CollectionItem.reviews.load( + collectionItem + ); + if (reviews.length > 0) { + return reviews[reviews.length - 1].body; + } else { + return ''; + } + } + + @FieldResolver(() => [Item]) + itemDetails( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + return ctx.dataLoader.loaders.CollectionItem.itemDetails.load(collectionItem); + } + + @FieldResolver(() => [Item]) + reviews( + @Root() collectionItem: CollectionItem, + @Ctx() ctx: BaseContext + ): Promise { + return ctx.dataLoader.loaders.CollectionItem.reviews.load(collectionItem); + } + + @Mutation(() => CollectionItem) + async createCollectionItem( + @Arg('data') data: CollectionItemCreateInput, + @UserId() userId: string + ): Promise { + return this.service.create(data, userId); + } + + @Mutation(() => [CollectionItem]) + async createManyCollectionItems( + @Args() { data }: CollectionItemCreateManyArgs, + @UserId() userId: string + ): Promise { + return this.service.createMany(data, userId); + } + + @Mutation(() => CollectionItem) + async updateCollectionItem( + @Args() { data, where }: CollectionItemUpdateArgs, + @UserId() userId: string + ): Promise { + return this.service.update(data, where, userId); + } + + @Mutation(() => StandardDeleteResponse) + async deleteCollectionItem( + @Arg('where') where: CollectionItemWhereUniqueInput, + @UserId() userId: string + ): Promise { + return this.service.delete(where, userId); + } } diff --git a/src/modules/collection-item/collection-item.service.ts b/src/modules/collection-item/collection-item.service.ts index 6924bb4..cce50ab 100644 --- a/src/modules/collection-item/collection-item.service.ts +++ b/src/modules/collection-item/collection-item.service.ts @@ -7,12 +7,12 @@ import { CollectionItem } from './collection-item.model'; @Service('CollectionItemService') export class CollectionItemService extends BaseService { - constructor( - @InjectRepository(CollectionItem) - protected readonly repository: Repository - ) { - super(CollectionItem, repository); - } + constructor( + @InjectRepository(CollectionItem) + protected readonly repository: Repository + ) { + super(CollectionItem, repository); + } - async getWithItemDetails() {} + async getWithItemDetails() {} } diff --git a/src/modules/item/item.model.ts b/src/modules/item/item.model.ts index afc2da7..18507a7 100644 --- a/src/modules/item/item.model.ts +++ b/src/modules/item/item.model.ts @@ -3,30 +3,30 @@ import { CollectionItem } from '../collection-item/collection-item.model'; @Model() export class Item extends BaseModel { - @StringField({ nullable: true }) - mbid?: string; + @StringField({ nullable: true }) + mbid?: string; - @IntField({ nullable: true }) - rymId?: number; + @IntField({ nullable: true }) + rymId?: number; - @StringField({ nullable: true }) - spotifyId?: string; + @StringField({ nullable: true }) + spotifyId?: string; - @StringField() - title!: string; + @StringField() + title!: string; - @StringField({ nullable: true }) - disambiguation?: string; + @StringField({ nullable: true }) + disambiguation?: string; - @StringField() - artist!: string; + @StringField() + artist!: string; - @StringField({ nullable: true }) - coverArt?: string; + @StringField({ nullable: true }) + coverArt?: string; - @OneToMany( - () => CollectionItem, - (collectionItem: CollectionItem) => collectionItem.itemDetails - ) - collectionItem?: CollectionItem[]; + @OneToMany( + () => CollectionItem, + (collectionItem: CollectionItem) => collectionItem.itemDetails + ) + collectionItem?: CollectionItem[]; } diff --git a/src/modules/item/item.resolver.ts b/src/modules/item/item.resolver.ts index 158642c..9680007 100644 --- a/src/modules/item/item.resolver.ts +++ b/src/modules/item/item.resolver.ts @@ -3,12 +3,12 @@ import { Inject } from 'typedi'; import { Fields, StandardDeleteResponse, UserId } from 'warthog'; import { - ItemCreateInput, - ItemCreateManyArgs, - ItemUpdateArgs, - ItemWhereArgs, - ItemWhereInput, - ItemWhereUniqueInput, + ItemCreateInput, + ItemCreateManyArgs, + ItemUpdateArgs, + ItemWhereArgs, + ItemWhereInput, + ItemWhereUniqueInput, } from '../../../generated'; import { Item } from './item.model'; @@ -16,50 +16,50 @@ import { ItemService } from './item.service'; @Resolver(Item) export class ItemResolver { - constructor(@Inject('ItemService') public readonly service: ItemService) {} + constructor(@Inject('ItemService') public readonly service: ItemService) {} - @Query(() => [Item]) - async items( - @Args() { where, orderBy, limit, offset }: ItemWhereArgs, - @Fields() fields: string[] - ): Promise { - return this.service.find(where, orderBy, limit, offset, fields); - } + @Query(() => [Item]) + async items( + @Args() { where, orderBy, limit, offset }: ItemWhereArgs, + @Fields() fields: string[] + ): Promise { + return this.service.find(where, orderBy, limit, offset, fields); + } - @Query(() => Item) - async item(@Arg('where') where: ItemWhereUniqueInput): Promise { - return this.service.findOne(where); - } + @Query(() => Item) + async item(@Arg('where') where: ItemWhereUniqueInput): Promise { + return this.service.findOne(where); + } - @Mutation(() => Item) - async createItem( - @Arg('data') data: ItemCreateInput, - @UserId() userId: string - ): Promise { - return this.service.create(data, userId); - } + @Mutation(() => Item) + async createItem( + @Arg('data') data: ItemCreateInput, + @UserId() userId: string + ): Promise { + return this.service.create(data, userId); + } - @Mutation(() => [Item]) - async createManyItems( - @Args() { data }: ItemCreateManyArgs, - @UserId() userId: string - ): Promise { - return this.service.createMany(data, userId); - } + @Mutation(() => [Item]) + async createManyItems( + @Args() { data }: ItemCreateManyArgs, + @UserId() userId: string + ): Promise { + return this.service.createMany(data, userId); + } - @Mutation(() => Item) - async updateItem( - @Args() { data, where }: ItemUpdateArgs, - @UserId() userId: string - ): Promise { - return this.service.update(data, where, userId); - } + @Mutation(() => Item) + async updateItem( + @Args() { data, where }: ItemUpdateArgs, + @UserId() userId: string + ): Promise { + return this.service.update(data, where, userId); + } - @Mutation(() => StandardDeleteResponse) - async deleteItem( - @Arg('where') where: ItemWhereUniqueInput, - @UserId() userId: string - ): Promise { - return this.service.delete(where, userId); - } + @Mutation(() => StandardDeleteResponse) + async deleteItem( + @Arg('where') where: ItemWhereUniqueInput, + @UserId() userId: string + ): Promise { + return this.service.delete(where, userId); + } } diff --git a/src/modules/item/item.service.ts b/src/modules/item/item.service.ts index 71afb24..933c392 100644 --- a/src/modules/item/item.service.ts +++ b/src/modules/item/item.service.ts @@ -7,7 +7,7 @@ import { Item } from './item.model'; @Service('ItemService') export class ItemService extends BaseService { - constructor(@InjectRepository(Item) protected readonly repository: Repository) { - super(Item, repository); - } + constructor(@InjectRepository(Item) protected readonly repository: Repository) { + super(Item, repository); + } } diff --git a/src/modules/review/review.model.ts b/src/modules/review/review.model.ts index 77f1df2..4d9ee52 100644 --- a/src/modules/review/review.model.ts +++ b/src/modules/review/review.model.ts @@ -3,18 +3,18 @@ import { CollectionItem } from '../collection-item/collection-item.model'; @Model() export class Review extends BaseModel { - @ManyToOne( - () => CollectionItem, - (collectionItem: CollectionItem) => collectionItem.reviews - ) - collectionItem!: CollectionItem; + @ManyToOne( + () => CollectionItem, + (collectionItem: CollectionItem) => collectionItem.reviews + ) + collectionItem!: CollectionItem; - @StringField({ nullable: true }) - rating?: string; + @StringField({ nullable: true }) + rating?: string; - @StringField({ nullable: true }) - title?: string; + @StringField({ nullable: true }) + title?: string; - @StringField({ nullable: true }) - body?: string; + @StringField({ nullable: true }) + body?: string; } diff --git a/src/modules/review/review.resolver.ts b/src/modules/review/review.resolver.ts index 7fa3847..1515abe 100644 --- a/src/modules/review/review.resolver.ts +++ b/src/modules/review/review.resolver.ts @@ -3,12 +3,12 @@ import { Inject } from 'typedi'; import { Fields, StandardDeleteResponse, UserId } from 'warthog'; import { - ReviewCreateInput, - ReviewCreateManyArgs, - ReviewUpdateArgs, - ReviewWhereArgs, - ReviewWhereInput, - ReviewWhereUniqueInput, + ReviewCreateInput, + ReviewCreateManyArgs, + ReviewUpdateArgs, + ReviewWhereArgs, + ReviewWhereInput, + ReviewWhereUniqueInput, } from '../../../generated'; import { Review } from './review.model'; @@ -16,50 +16,50 @@ import { ReviewService } from './review.service'; @Resolver(Review) export class ReviewResolver { - constructor(@Inject('ReviewService') public readonly service: ReviewService) {} + constructor(@Inject('ReviewService') public readonly service: ReviewService) {} - @Query(() => [Review]) - async reviews( - @Args() { where, orderBy, limit, offset }: ReviewWhereArgs, - @Fields() fields: string[] - ): Promise { - return this.service.find(where, orderBy, limit, offset, fields); - } + @Query(() => [Review]) + async reviews( + @Args() { where, orderBy, limit, offset }: ReviewWhereArgs, + @Fields() fields: string[] + ): Promise { + return this.service.find(where, orderBy, limit, offset, fields); + } - @Query(() => Review) - async review(@Arg('where') where: ReviewWhereUniqueInput): Promise { - return this.service.findOne(where); - } + @Query(() => Review) + async review(@Arg('where') where: ReviewWhereUniqueInput): Promise { + return this.service.findOne(where); + } - @Mutation(() => Review) - async createReview( - @Arg('data') data: ReviewCreateInput, - @UserId() userId: string - ): Promise { - return this.service.create(data, userId); - } + @Mutation(() => Review) + async createReview( + @Arg('data') data: ReviewCreateInput, + @UserId() userId: string + ): Promise { + return this.service.create(data, userId); + } - @Mutation(() => [Review]) - async createManyReviews( - @Args() { data }: ReviewCreateManyArgs, - @UserId() userId: string - ): Promise { - return this.service.createMany(data, userId); - } + @Mutation(() => [Review]) + async createManyReviews( + @Args() { data }: ReviewCreateManyArgs, + @UserId() userId: string + ): Promise { + return this.service.createMany(data, userId); + } - @Mutation(() => Review) - async updateReview( - @Args() { data, where }: ReviewUpdateArgs, - @UserId() userId: string - ): Promise { - return this.service.update(data, where, userId); - } + @Mutation(() => Review) + async updateReview( + @Args() { data, where }: ReviewUpdateArgs, + @UserId() userId: string + ): Promise { + return this.service.update(data, where, userId); + } - @Mutation(() => StandardDeleteResponse) - async deleteReview( - @Arg('where') where: ReviewWhereUniqueInput, - @UserId() userId: string - ): Promise { - return this.service.delete(where, userId); - } + @Mutation(() => StandardDeleteResponse) + async deleteReview( + @Arg('where') where: ReviewWhereUniqueInput, + @UserId() userId: string + ): Promise { + return this.service.delete(where, userId); + } } diff --git a/src/modules/review/review.service.ts b/src/modules/review/review.service.ts index fc3e91d..41cfcdd 100644 --- a/src/modules/review/review.service.ts +++ b/src/modules/review/review.service.ts @@ -7,9 +7,9 @@ import { Review } from './review.model'; @Service('ReviewService') export class ReviewService extends BaseService { - constructor( - @InjectRepository(Review) protected readonly repository: Repository - ) { - super(Review, repository); - } + constructor( + @InjectRepository(Review) protected readonly repository: Repository + ) { + super(Review, repository); + } } diff --git a/src/modules/user/user.model.ts b/src/modules/user/user.model.ts index 7bb4c7a..f86675a 100644 --- a/src/modules/user/user.model.ts +++ b/src/modules/user/user.model.ts @@ -4,27 +4,27 @@ import { AccountSettings } from '../../interfaces/account-settings'; @Model() export class User extends BaseModel { - @StringField({ unique: true }) - username!: string; + @StringField({ unique: true }) + username!: string; - @EmailField({ nullable: true }) - email?: string; + @EmailField({ nullable: true }) + email?: string; - @StringField({ writeonly: true }) - password!: string; + @StringField({ writeonly: true }) + password!: string; - @StringField({ dbOnly: true }) - salt!: string; + @StringField({ dbOnly: true }) + salt!: string; - @StringField({ nullable: true }) - bio?: string; + @StringField({ nullable: true }) + bio?: string; - @JSONField({ nullable: true }) - accountSettings?: AccountSettings; + @JSONField({ nullable: true }) + accountSettings?: AccountSettings; - @OneToMany( - () => CollectionItem, - (collectionItem: CollectionItem) => collectionItem.user - ) - collection?: CollectionItem[]; + @OneToMany( + () => CollectionItem, + (collectionItem: CollectionItem) => collectionItem.user + ) + collection?: CollectionItem[]; } diff --git a/src/modules/user/user.resolver.ts b/src/modules/user/user.resolver.ts index a46a6ef..5522ec9 100644 --- a/src/modules/user/user.resolver.ts +++ b/src/modules/user/user.resolver.ts @@ -1,24 +1,24 @@ import { - Arg, - Args, - Mutation, - Query, - Resolver, - FieldResolver, - Root, - Ctx, - Authorized, + Arg, + Args, + Mutation, + Query, + Resolver, + FieldResolver, + Root, + Ctx, + Authorized, } from 'type-graphql'; import { Inject } from 'typedi'; import { Fields, StandardDeleteResponse, UserId, BaseContext } from 'warthog'; import { - UserCreateInput, - UserCreateManyArgs, - UserUpdateArgs, - UserWhereArgs, - UserWhereInput, - UserWhereUniqueInput, + UserCreateInput, + UserCreateManyArgs, + UserUpdateArgs, + UserWhereArgs, + UserWhereInput, + UserWhereUniqueInput, } from '../../../generated'; import { User } from './user.model'; @@ -27,56 +27,56 @@ import { CollectionItem } from '../collection-item/collection-item.model'; @Resolver(User) export class UserResolver { - constructor(@Inject('UserService') public readonly service: UserService) {} + constructor(@Inject('UserService') public readonly service: UserService) {} - @Query(() => [User]) - async users( - @Args() { where, orderBy, limit, offset }: UserWhereArgs, - @Fields() fields: string[] - ): Promise { - return this.service.find(where, orderBy, limit, offset, fields); - } + @Query(() => [User]) + async users( + @Args() { where, orderBy, limit, offset }: UserWhereArgs, + @Fields() fields: string[] + ): Promise { + return this.service.find(where, orderBy, limit, offset, fields); + } - @Query(() => User) - async user(@Arg('where') where: UserWhereUniqueInput): Promise { - return this.service.findOne(where); - } + @Query(() => User) + async user(@Arg('where') where: UserWhereUniqueInput): Promise { + return this.service.findOne(where); + } - @FieldResolver(() => [CollectionItem]) - collection(@Root() user: User, @Ctx() ctx: BaseContext): Promise { - return ctx.dataLoader.loaders.User.collection.load(user); - } + @FieldResolver(() => [CollectionItem]) + collection(@Root() user: User, @Ctx() ctx: BaseContext): Promise { + return ctx.dataLoader.loaders.User.collection.load(user); + } - @Authorized('signedIn') - @Mutation(() => User) - async createUser( - @Arg('data') data: UserCreateInput, - @UserId() userId: string - ): Promise { - return this.service.create(data, userId); - } + @Authorized('signedIn') + @Mutation(() => User) + async createUser( + @Arg('data') data: UserCreateInput, + @UserId() userId: string + ): Promise { + return this.service.create(data, userId); + } - @Mutation(() => [User]) - async createManyUsers( - @Args() { data }: UserCreateManyArgs, - @UserId() userId: string - ): Promise { - return this.service.createMany(data, userId); - } + @Mutation(() => [User]) + async createManyUsers( + @Args() { data }: UserCreateManyArgs, + @UserId() userId: string + ): Promise { + return this.service.createMany(data, userId); + } - @Mutation(() => User) - async updateUser( - @Args() { data, where }: UserUpdateArgs, - @UserId() userId: string - ): Promise { - return this.service.update(data, where, userId); - } + @Mutation(() => User) + async updateUser( + @Args() { data, where }: UserUpdateArgs, + @UserId() userId: string + ): Promise { + return this.service.update(data, where, userId); + } - @Mutation(() => StandardDeleteResponse) - async deleteUser( - @Arg('where') where: UserWhereUniqueInput, - @UserId() userId: string - ): Promise { - return this.service.delete(where, userId); - } + @Mutation(() => StandardDeleteResponse) + async deleteUser( + @Arg('where') where: UserWhereUniqueInput, + @UserId() userId: string + ): Promise { + return this.service.delete(where, userId); + } } diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 5d9b26c..71da865 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -9,33 +9,33 @@ import { CollectionItem } from '../collection-item/collection-item.model'; @Service('UserService') export class UserService extends BaseService { - constructor(@InjectRepository(User) protected readonly repository: Repository) { - super(User, repository); - } + constructor(@InjectRepository(User) protected readonly repository: Repository) { + super(User, repository); + } - async create(user: UserCreateInput, userId: string) { - const salt = await bcrypt.genSalt(); - user.password = await bcrypt.hash(user.password, salt); - const collection: CollectionItem[] = []; + async create(user: UserCreateInput, userId: string) { + const salt = await bcrypt.genSalt(); + user.password = await bcrypt.hash(user.password, salt); + const collection: CollectionItem[] = []; - const payload = { - ...user, - salt, - collection, - }; + const payload = { + ...user, + salt, + collection, + }; - return super.create(payload, userId); - } + return super.create(payload, userId); + } - // TODO: Sign in - // async validateUserPassword(authCredentialsInput: UserCreateInput): Promise { - // const { username, password } = authCredentialsInput; - // const user = await this.findOne({username}); + // TODO: Sign in + // async validateUserPassword(authCredentialsInput: UserCreateInput): Promise { + // const { username, password } = authCredentialsInput; + // const user = await this.findOne({username}); - // if (user && user.password === bcrypt.hash(user.password, user.salt)) { - // return user.username; - // } else { - // return 'user not found'; - // } - // } + // if (user && user.password === bcrypt.hash(user.password, user.salt)) { + // return user.username; + // } else { + // return 'user not found'; + // } + // } } diff --git a/src/server.ts b/src/server.ts index c059d16..4b9bc7e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -5,32 +5,32 @@ import { BaseContext, Server, authChecker } from 'warthog'; import { Logger } from './logger'; interface Context extends BaseContext { - user: { - email: string; - id: string; - permissions: string; - }; + user: { + email: string; + id: string; + permissions: string; + }; } export function getServer(AppOptions = {}, dbOptions = {}) { - return new Server( - { - authChecker, - // Inject a fake user. In a real app you'd parse a JWT to add the user - context: (request: any) => { - const userId = JSON.stringify(request.headers).length.toString(); + return new Server( + { + authChecker, + // Inject a fake user. In a real app you'd parse a JWT to add the user + context: (request: any) => { + const userId = JSON.stringify(request.headers).length.toString(); - return { - user: { - id: `user:${userId}`, - permissions: ['signedIn'], - }, - }; - }, - introspection: true, - logger: Logger, - ...AppOptions, - }, - dbOptions - ); + return { + user: { + id: `user:${userId}`, + permissions: ['signedIn'], + }, + }; + }, + introspection: true, + logger: Logger, + ...AppOptions, + }, + dbOptions + ); }