Browse Source

add graphql and episodes provider

feature/add-graphql
Christian Ziermann 4 years ago
parent
commit
fd8fbe0e81
14 changed files with 17198 additions and 10041 deletions
  1. +4
    -1
      nest-cli.json
  2. +16883
    -10024
      package-lock.json
  3. +7
    -1
      package.json
  4. +0
    -5
      schemas/dto/create-episode.dto.ts
  5. +69
    -0
      schemas/dto/episode-create.dto.ts
  6. +16
    -0
      schemas/dto/episode-enclosure-create.dto.ts
  7. +13
    -0
      schemas/entity/episode-enclosure.entity.ts
  8. +48
    -1
      schemas/entity/episode.entity.ts
  9. +10
    -4
      schemas/enum/itunes-episode-type.enum.ts
  10. +11
    -2
      src/app.module.ts
  11. +18
    -0
      src/episode/episode.resolver.spec.ts
  12. +23
    -0
      src/episode/episode.resolver.ts
  13. +9
    -3
      src/episode/episode.service.ts
  14. +87
    -0
      src/schema.gql

+ 4
- 1
nest-cli.json View File

@@ -1,4 +1,7 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["@nestjs/graphql/plugin"]
}
}

+ 16883
- 10024
package-lock.json
File diff suppressed because it is too large
View File


+ 7
- 1
package.json View File

@@ -23,14 +23,19 @@
"dependencies": {
"@nestjs/common": "^7.0.0",
"@nestjs/core": "^7.0.0",
"@nestjs/graphql": "^7.7.0",
"@nestjs/mongoose": "^7.0.2",
"@nestjs/platform-express": "^7.0.0",
"@types/podcast": "^1.3.0",
"apollo-server-express": "^2.18.2",
"graphql": "^15.3.0",
"graphql-tools": "^6.2.4",
"mongoose": "^5.10.9",
"podcast": "^1.3.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.5.4"
"rxjs": "^6.5.4",
"uuid": "^8.3.0"
},
"devDependencies": {
"@nestjs/cli": "^7.0.0",
@@ -41,6 +46,7 @@
"@types/mongoose": "^5.7.36",
"@types/node": "^13.9.1",
"@types/supertest": "^2.0.8",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "3.9.1",
"@typescript-eslint/parser": "3.9.1",
"eslint": "7.7.0",

+ 0
- 5
schemas/dto/create-episode.dto.ts View File

@@ -1,5 +0,0 @@
import { Episode } from "schemas/entity/episode.entity";

export class CreateEpisodeDto extends Episode {

}

+ 69
- 0
schemas/dto/episode-create.dto.ts View File

@@ -0,0 +1,69 @@
import { Field, InputType } from '@nestjs/graphql';
import { ItunesEpisodeTypeEnum } from 'schemas/enum/itunes-episode-type.enum';
import { EpisodeEnclosureCreateDto } from './episode-enclosure-create.dto';

@InputType()
export class EpisodeCreateDto {
@Field({ nullable: true })
title?: string;

@Field({ nullable: true })
description?: string;

@Field()
url: string;

@Field({ nullable: true })
guid?: string;

@Field(type => [String], { nullable: true })
categories?: string[];

@Field({ nullable: true })
author?: string;

@Field()
date: Date;

@Field({ nullable: true })
lat?: number;

@Field({ nullable: true })
long?: number;

@Field(type => EpisodeEnclosureCreateDto, { nullable: true })
enclosure?: EpisodeEnclosureCreateDto;

@Field({ nullable: true })
content?: string;

@Field({ nullable: true })
itunesAuthor?: string;

@Field({ nullable: true })
itunesExplicit?: boolean;

@Field({ nullable: true })
itunesSubtitle?: string;

@Field({ nullable: true })
itunesSummary?: string;

@Field({ nullable: true })
itunesDuration?: number;

@Field({ nullable: true })
itunesImage?: string;

@Field({ nullable: true })
itunesSeason?: number;

@Field({ nullable: true })
itunesEpisode?: number;

@Field({ nullable: true })
itunesTitle?: string;

@Field(type => ItunesEpisodeTypeEnum, { nullable: true })
itunesEpisodeType?: ItunesEpisodeTypeEnum;
}

+ 16
- 0
schemas/dto/episode-enclosure-create.dto.ts View File

@@ -0,0 +1,16 @@
import { Field, InputType } from '@nestjs/graphql';

@InputType()
export class EpisodeEnclosureCreateDto {
@Field()
url: string;

@Field({nullable: true})
file?: string;

@Field({nullable: true})
size?: number;

@Field({nullable: true})
type?: string;
}

schemas/entity/episode-enclosure.ts → schemas/entity/episode-enclosure.entity.ts View File

@@ -1,18 +1,31 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import Podcast from 'podcast';
import { Document } from 'mongoose';
import { Field, ID, InputType, ObjectType } from '@nestjs/graphql';

export type EpisodeEnclosureDocument = EpisodeEnclosure & Document;

@Schema()
@ObjectType()
export class EpisodeEnclosure implements Podcast.ItemEnclosure {
@Prop()
@Field(type => ID)
id: string;

@Prop()
@Field()
url: string;

@Prop()
@Field({ nullable: true })
file?: string;

@Prop()
@Field({ nullable: true })
size?: number;

@Prop()
@Field({ nullable: true })
type?: string;
}


+ 48
- 1
schemas/entity/episode.entity.ts View File

@@ -1,54 +1,101 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import Podcast from 'podcast';
import { ItunesEpisodeTypeEnum } from 'schemas/enum/itunes-episode-type.enum';
import { EpisodeEnclosure } from './episode-enclosure';
import { EpisodeEnclosure } from './episode-enclosure.entity';
import { Document } from 'mongoose';
import { Field, ID, ObjectType } from '@nestjs/graphql';

export type EpisodeDocument = Episode & Document;

@Schema()
@ObjectType()
export class Episode implements Podcast.Item {
@Prop()
@Field(type => ID)
id: string;

@Prop()
@Field({ nullable: true })
title?: string;

@Prop()
@Field({ nullable: true })
description?: string;

@Prop()
@Field()
url: string;

@Prop()
@Field({ nullable: true })
guid?: string;

@Prop([String])
@Field(type => [String], {nullable: true})
categories?: string[];

@Prop()
@Field({ nullable: true })
author?: string;

@Prop()
@Field()
date: Date;

@Prop()
@Field({ nullable: true })
lat?: number;

@Prop()
@Field({ nullable: true })
long?: number;

@Prop(EpisodeEnclosure)
@Field(type => EpisodeEnclosure, {nullable: true})
enclosure?: EpisodeEnclosure;

@Prop()
@Field({ nullable: true })
content?: string;

@Prop()
@Field({ nullable: true })
itunesAuthor?: string;

@Prop()
@Field({ nullable: true })
itunesExplicit?: boolean;

@Prop()
@Field({ nullable: true })
itunesSubtitle?: string;

@Prop()
@Field({ nullable: true })
itunesSummary?: string;

@Prop()
@Field({ nullable: true })
itunesDuration?: number;

@Prop()
@Field({ nullable: true })
itunesImage?: string;

@Prop()
@Field({ nullable: true })
itunesSeason?: number;

@Prop()
@Field({ nullable: true })
itunesEpisode?: number;

@Prop()
@Field({ nullable: true })
itunesTitle?: string;

@Prop(ItunesEpisodeTypeEnum)
@Field(type => ItunesEpisodeTypeEnum, {nullable: true})
itunesEpisodeType?: ItunesEpisodeTypeEnum;
}


+ 10
- 4
schemas/enum/itunes-episode-type.enum.ts View File

@@ -1,5 +1,11 @@
import { registerEnumType } from '@nestjs/graphql';

export enum ItunesEpisodeTypeEnum {
FULL = "full",
TRAILER = "trailer",
BONUS = "bonus",
}
FULL = 'full',
TRAILER = 'trailer',
BONUS = 'bonus',
}

registerEnumType(ItunesEpisodeTypeEnum, {
name: 'ItunesEpisodeTypeEnum',
});

+ 11
- 2
src/app.module.ts View File

@@ -3,12 +3,21 @@ import { MongooseModule } from '@nestjs/mongoose';
import { Episode, EpisodeSchema } from 'schemas/entity/episode.entity';
import { AppService } from './app.service';
import { EpisodeService } from './episode/episode.service';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { EpisodeResolver } from './episode/episode.resolver';

@Module({
imports: [
MongooseModule.forFeature([{ name: Episode.name, schema: EpisodeSchema }]),
MongooseModule.forRoot('mongodb://localhost:27017/test')
MongooseModule.forRoot('mongodb://localhost:27017/test'),
GraphQLModule.forRoot({
debug: false,
playground: true,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: true,
}),
],
providers: [AppService, EpisodeService],
providers: [AppService, EpisodeService, EpisodeResolver],
})
export class AppModule {}

+ 18
- 0
src/episode/episode.resolver.spec.ts View File

@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { EpisodeResolver } from './episode.resolver';

describe('EpisodeResolver', () => {
let resolver: EpisodeResolver;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [EpisodeResolver],
}).compile();

resolver = module.get<EpisodeResolver>(EpisodeResolver);
});

it('should be defined', () => {
expect(resolver).toBeDefined();
});
});

+ 23
- 0
src/episode/episode.resolver.ts View File

@@ -0,0 +1,23 @@
import { Resolver, Query, Args, Mutation } from '@nestjs/graphql';
import { EpisodeCreateDto } from 'schemas/dto/episode-create.dto';
import { Episode } from 'schemas/entity/episode.entity';
import { EpisodeService } from './episode.service';

@Resolver()
export class EpisodeResolver {
constructor(protected episodeService: EpisodeService) {}

@Query(returns => [Episode])
async listEpisodes(): Promise<Episode[]> {
return this.episodeService.findAll();
}

@Mutation(returns => Episode)
async createEpisode(
@Args('episodeCreateDto') episodeCreateDto: EpisodeCreateDto,
) {
const episode = await this.episodeService.create(episodeCreateDto);
return episode;
}

}

+ 9
- 3
src/episode/episode.service.ts View File

@@ -1,20 +1,26 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { CreateEpisodeDto } from 'schemas/dto/create-episode.dto';
import { EpisodeCreateDto } from 'schemas/dto/episode-create.dto';
import { Episode, EpisodeDocument } from 'schemas/entity/episode.entity';
import { v4 as uuid } from 'uuid';

@Injectable()
export class EpisodeService {
constructor(
@InjectModel(Episode.name) private episodeModel: Model<EpisodeDocument>,
) {}
async create(createEpisodeDto: CreateEpisodeDto): Promise<Episode> {
const createdEpisode = new this.episodeModel(createEpisodeDto);
async create(episodeCreateDto: EpisodeCreateDto): Promise<Episode> {
const createdEpisode = new this.episodeModel(episodeCreateDto);
createdEpisode.id = uuid();
return createdEpisode.save();
}

async findAll(): Promise<Episode[]> {
return this.episodeModel.find().exec();
}

async findOneById(): Promise<Episode[]> {
return this.episodeModel.find().exec();
}
}

+ 87
- 0
src/schema.gql View File

@@ -0,0 +1,87 @@
# ------------------------------------------------------
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------

type EpisodeEnclosure {
id: ID!
url: String!
file: String
size: Float
type: String
}

type Episode {
id: ID!
title: String
description: String
url: String!
guid: String
categories: [String!]
author: String
date: DateTime!
lat: Float
long: Float
enclosure: EpisodeEnclosure
content: String
itunesAuthor: String
itunesExplicit: Boolean
itunesSubtitle: String
itunesSummary: String
itunesDuration: Float
itunesImage: String
itunesSeason: Float
itunesEpisode: Float
itunesTitle: String
itunesEpisodeType: ItunesEpisodeTypeEnum
}

"""
A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.
"""
scalar DateTime

enum ItunesEpisodeTypeEnum {
FULL
TRAILER
BONUS
type
}

type Query {
listEpisodes: [Episode!]!
}

type Mutation {
createEpisode(episodeCreateDto: EpisodeCreateDto!): Episode!
}

input EpisodeCreateDto {
title: String
description: String
url: String!
guid: String
categories: [String!]
author: String
date: DateTime!
lat: Float
long: Float
enclosure: EpisodeEnclosureCreateDto
content: String
itunesAuthor: String
itunesExplicit: Boolean
itunesSubtitle: String
itunesSummary: String
itunesDuration: Float
itunesImage: String
itunesSeason: Float
itunesEpisode: Float
itunesTitle: String
itunesEpisodeType: ItunesEpisodeTypeEnum
}

input EpisodeEnclosureCreateDto {
url: String!
file: String
size: Float
type: String
}

Loading…
Cancel
Save