GraphQL schema and resolvers for rep service
This commit is contained in:
parent
3259cbf001
commit
1c738b6b02
|
@ -17,7 +17,8 @@
|
|||
"@nestjs/platform-express": "^10.0.0",
|
||||
"graphql": "^16.6.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.8.1"
|
||||
"rxjs": "^7.8.1",
|
||||
"ts-morph": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
|
@ -2097,6 +2098,53 @@
|
|||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.20.0.tgz",
|
||||
"integrity": "sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q==",
|
||||
"dependencies": {
|
||||
"fast-glob": "^3.2.12",
|
||||
"minimatch": "^7.4.3",
|
||||
"mkdirp": "^2.1.6",
|
||||
"path-browserify": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common/node_modules/minimatch": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
|
||||
"integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common/node_modules/mkdirp": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz",
|
||||
"integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==",
|
||||
"bin": {
|
||||
"mkdirp": "dist/cjs/src/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||
|
@ -3061,8 +3109,7 @@
|
|||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
|
@ -3492,6 +3539,11 @@
|
|||
"node": ">= 0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/code-block-writer": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
||||
"integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="
|
||||
},
|
||||
"node_modules/collect-v8-coverage": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
|
||||
|
@ -6596,6 +6648,11 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
|
@ -8010,6 +8067,15 @@
|
|||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-morph": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-19.0.0.tgz",
|
||||
"integrity": "sha512-D6qcpiJdn46tUqV45vr5UGM2dnIEuTGNxVhg0sk5NX11orcouwj6i1bMqZIz2mZTZB1Hcgy7C3oEVhAT+f6mbQ==",
|
||||
"dependencies": {
|
||||
"@ts-morph/common": "~0.20.0",
|
||||
"code-block-writer": "^12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
"@nestjs/platform-express": "^10.0.0",
|
||||
"graphql": "^16.6.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rxjs": "^7.8.1"
|
||||
"rxjs": "^7.8.1",
|
||||
"ts-morph": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { Module, Post } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
||||
import { join } from 'path';
|
||||
import { MemberResolver } from './services/reputation/components/member/member.resolver';
|
||||
import { PostResolver } from './services/reputation/components/post/post.resolver';
|
||||
import { CitationsResolver } from './services/reputation/components/citation/citation.resolver';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
driver: ApolloDriver,
|
||||
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
|
||||
sortSchema: true,
|
||||
typePaths: ['./**/*.graphql'],
|
||||
definitions: {
|
||||
path: join(process.cwd(), 'src/graphql.ts')
|
||||
},
|
||||
}),
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
providers: [AppService, MemberResolver, PostResolver, CitationsResolver],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
/*
|
||||
* -------------------------------------------------------
|
||||
* THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
|
||||
* -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export interface IQuery {
|
||||
citation(id: string): Nullable<Citation> | Promise<Nullable<Citation>>;
|
||||
citations(): Nullable<Citation>[] | Promise<Nullable<Citation>[]>;
|
||||
isNeutral(citationId: string): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
isPositive(citationId: string): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
isNegative(citationId: string): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
adjacentPost(citationId: string, postId: string): Nullable<Post> | Promise<Nullable<Post>>;
|
||||
members(): Nullable<Nullable<Member>[]> | Promise<Nullable<Nullable<Member>[]>>;
|
||||
member(id: string): Nullable<Member> | Promise<Nullable<Member>>;
|
||||
posts(): Nullable<Post>[] | Promise<Nullable<Post>[]>;
|
||||
post(id: string): Nullable<Post> | Promise<Nullable<Post>>;
|
||||
authorWeight(postId: string, authorId: string): Nullable<number> | Promise<Nullable<number>>;
|
||||
citationWeight(postId: string, citationId: string): Nullable<number> | Promise<Nullable<number>>;
|
||||
}
|
||||
|
||||
export interface Citation {
|
||||
id: string;
|
||||
sourcePost: Post;
|
||||
citedPost: Post;
|
||||
directional: boolean;
|
||||
impact: number;
|
||||
}
|
||||
|
||||
export interface IMutation {
|
||||
createCitation(citationId?: Nullable<string>, sourcePostId?: Nullable<string>, citedPostId?: Nullable<string>, impact?: Nullable<number>): Nullable<Citation> | Promise<Nullable<Citation>>;
|
||||
createMember(id?: Nullable<string>): Nullable<Member> | Promise<Nullable<Member>>;
|
||||
postRep(memberId: string, postId: string, amount: number): Nullable<LedgerEntry> | Promise<Nullable<LedgerEntry>>;
|
||||
citationRep(memberId: string, postId: string, citationId: string, amount: number): Nullable<LedgerEntry> | Promise<Nullable<LedgerEntry>>;
|
||||
createPost(id?: Nullable<string>, title?: Nullable<string>, content?: Nullable<string>, authorId?: Nullable<string>): Nullable<Post> | Promise<Nullable<Post>>;
|
||||
setAuthor(postId: string, authorId: string, weight: number): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
removeAuthor(postId: string, authorId: string): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
setCitation(postId: string, citationId: string, weight: number): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
removeCitation(postId: string, citationId: string): Nullable<boolean> | Promise<Nullable<boolean>>;
|
||||
}
|
||||
|
||||
export interface Member {
|
||||
id: string;
|
||||
reputation: number;
|
||||
ledger?: Nullable<Nullable<LedgerEntry>[]>;
|
||||
}
|
||||
|
||||
export interface LedgerEntry {
|
||||
timestamp?: Nullable<string>;
|
||||
type?: Nullable<string>;
|
||||
postId?: Nullable<string>;
|
||||
citationId?: Nullable<string>;
|
||||
change?: Nullable<number>;
|
||||
balance?: Nullable<number>;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
authors: Nullable<Member>[];
|
||||
citations: Nullable<Citation>[];
|
||||
authorsWeightTotal: number;
|
||||
citationsWeightTotal: number;
|
||||
data: string;
|
||||
}
|
||||
|
||||
type Nullable<T> = T | null;
|
|
@ -0,0 +1,64 @@
|
|||
import { Resolver, Query, Args, Mutation } from '@nestjs/graphql';
|
||||
import { Citation } from './citation';
|
||||
import { Post } from '../post/post';
|
||||
|
||||
@Resolver(of => Citation)
|
||||
export class CitationsResolver {
|
||||
|
||||
constructor() {}
|
||||
|
||||
@Query()
|
||||
citations() {
|
||||
return Citation.getAllCitations();
|
||||
}
|
||||
|
||||
@Query()
|
||||
citation(@Args('id') id: string) {
|
||||
return Citation.getCitation(id);
|
||||
}
|
||||
|
||||
@Query()
|
||||
isNeutral(@Args('citationId'!) id: string) {
|
||||
const citation = Citation.getCitation(id);
|
||||
if (!citation) return null;
|
||||
return citation.isNeutral();
|
||||
}
|
||||
|
||||
@Query()
|
||||
isPositive(@Args('citationId'!) id: string) {
|
||||
const citation = Citation.getCitation(id);
|
||||
if (!citation) return null;
|
||||
return citation.isPositive();
|
||||
}
|
||||
|
||||
@Query()
|
||||
isNegative(@Args('citationId'!) id: string) {
|
||||
const citation = Citation.getCitation(id);
|
||||
if (!citation) return null;
|
||||
return citation.isNegative();
|
||||
}
|
||||
|
||||
@Query()
|
||||
adjacentPost(
|
||||
@Args('citationId'!) citationId: string,
|
||||
@Args('postId'!) postId: string
|
||||
) {
|
||||
const citation = Citation.getCitation(citationId);
|
||||
const post = Post.getPost(postId);
|
||||
if (!citation || !post) return null;
|
||||
return citation.getAdjacent(post);
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
createCitation(
|
||||
@Args('citationId') id: string,
|
||||
@Args('sourcePostId'!) sourcePostId: string,
|
||||
@Args('citedPostId'!) citedPostId: string,
|
||||
@Args('impact'!) impact: number
|
||||
) {
|
||||
const sourcePost = Post.getPost(sourcePostId);
|
||||
const citedPost = Post.getPost(citedPostId);
|
||||
if (!sourcePost || !citedPost) return null;
|
||||
return new Citation(id, sourcePost, citedPost, impact);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
type Query {
|
||||
citation(id: String!): Citation
|
||||
citations: [Citation]!
|
||||
isNeutral(citationId: String!): Boolean
|
||||
isPositive(citationId: String!): Boolean
|
||||
isNegative(citationId: String!): Boolean
|
||||
adjacentPost(citationId: String!, postId: String!): Post
|
||||
}
|
||||
|
||||
type Citation {
|
||||
id: String!
|
||||
sourcePost: Post!
|
||||
citedPost: Post!
|
||||
directional: Boolean!
|
||||
impact: Int!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createCitation(
|
||||
citationId: String,
|
||||
sourcePostId: String,
|
||||
citedPostId: String,
|
||||
impact: Int
|
||||
): Citation
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
||||
import { Member } from "./member";
|
||||
|
||||
@Resolver(of => Member)
|
||||
export class MemberResolver {
|
||||
|
||||
constructor() {}
|
||||
|
||||
@Query()
|
||||
members() {
|
||||
return Member.getAllMembers();
|
||||
}
|
||||
|
||||
@Query()
|
||||
member(@Args('id') id: string) {
|
||||
return Member.getMember(id);
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
createMember(@Args('id') id?: string) {
|
||||
return new Member(id);
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
postRep(
|
||||
@Args('memberId'!) memberId: string,
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('amount'!) amount: number,
|
||||
) {
|
||||
const member = Member.getMember(memberId);
|
||||
if (!member) return null;
|
||||
return member.postReputation(postId, amount);
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
citationRep(
|
||||
@Args('memberId'!) memberId: string,
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('citationId'!) citationId: string,
|
||||
@Args('amount'!) amount: number,
|
||||
) {
|
||||
const member = Member.getMember(memberId);
|
||||
if (!member) return null;
|
||||
return member.citationReputation(postId, citationId, amount);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
|
||||
type Query {
|
||||
members: [Member]
|
||||
member(id: String!): Member
|
||||
}
|
||||
|
||||
type Member {
|
||||
id: String!
|
||||
reputation: Int!
|
||||
ledger: [LedgerEntry]
|
||||
}
|
||||
|
||||
type LedgerEntry {
|
||||
timestamp: String
|
||||
type: String
|
||||
postId: String
|
||||
citationId: String
|
||||
change: Int
|
||||
balance: Int
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createMember(id: String): Member
|
||||
postRep(
|
||||
memberId: String!,
|
||||
postId: String!,
|
||||
amount: Int!
|
||||
): LedgerEntry
|
||||
citationRep(
|
||||
memberId: String!,
|
||||
postId: String!,
|
||||
citationId: String!,
|
||||
amount: Int!
|
||||
): LedgerEntry
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
import { Resolver, Query, Args, Mutation } from "@nestjs/graphql";
|
||||
import { Post } from "./post";
|
||||
import { Member } from "../member/member";
|
||||
import { Citation } from "../citation/citation";
|
||||
|
||||
@Resolver(of => Post)
|
||||
export class PostResolver {
|
||||
|
||||
constructor() {}
|
||||
|
||||
@Query()
|
||||
posts() {
|
||||
return Post.getAllPosts();
|
||||
}
|
||||
|
||||
@Query()
|
||||
post(@Args('id') id: string) {
|
||||
return Post.getPost(id);
|
||||
}
|
||||
|
||||
@Query()
|
||||
authorWeight(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('authorId'!) authorId: string
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const author = Member.getMember(authorId);
|
||||
if (!post || !author) return null;
|
||||
return post.getWeight(author);
|
||||
}
|
||||
|
||||
@Query()
|
||||
citationWeight(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('citationId'!) citationId: string
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const citation = Citation.getCitation(citationId);
|
||||
if (!post || !citation) return null;
|
||||
return post.getWeight(citation);
|
||||
}
|
||||
|
||||
|
||||
@Mutation()
|
||||
createPost(
|
||||
@Args('id') id: string,
|
||||
@Args('title'!) title: string,
|
||||
@Args('content'!) content: string,
|
||||
@Args('authorId'!) authorId: string,
|
||||
) {
|
||||
const author = Member.getMember(authorId);
|
||||
if (!author) return null;
|
||||
return new Post(id, title, content, author);
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
setAuthor(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('authorId'!) authorId: string,
|
||||
@Args('weight'!) weight: number,
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const author = Member.getMember(authorId);
|
||||
if (!post || !author) return false;
|
||||
post.setAuthor(author, weight);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
removeAuthor(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('citationId'!) authorId: string,
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const author = Member.getMember(authorId);
|
||||
if (!post || !author) return false;
|
||||
post.removeAuthor(author);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
setCitation(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('citationId'!) citationId: string,
|
||||
@Args('weight'!) weight: number,
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const citation = Citation.getCitation(citationId);
|
||||
if (!post || !citation) return false;
|
||||
post.setCitation(citation, weight);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mutation()
|
||||
removeCitation(
|
||||
@Args('postId'!) postId: string,
|
||||
@Args('citationId'!) citationId: string,
|
||||
) {
|
||||
const post = Post.getPost(postId);
|
||||
const citation = Citation.getCitation(citationId);
|
||||
if (!post || !citation) return false;
|
||||
post.removeCitation(citation);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
type Query {
|
||||
posts: [Post]!
|
||||
post(id: String!): Post
|
||||
authorWeight(postId: String!, authorId: String!): Int
|
||||
citationWeight(postId: String!, citationId: String!): Int
|
||||
}
|
||||
|
||||
type Post {
|
||||
id: ID!
|
||||
title: String!
|
||||
content: String!
|
||||
authors: [Member]!
|
||||
citations: [Citation]!
|
||||
authorsWeightTotal: Int!
|
||||
citationsWeightTotal: Int!
|
||||
data: String!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createPost(id: String, title: String, content: String, authorId: String): Post
|
||||
setAuthor(postId: String!, authorId: String!, weight: Int!): Boolean
|
||||
removeAuthor(postId: String!, authorId: String!): Boolean
|
||||
setCitation(postId: String!, citationId: String!, weight: Int!): Boolean
|
||||
removeCitation(postId: String!, citationId: String!): Boolean
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
export class ReputationService {
|
||||
|
||||
}
|
Loading…
Reference in New Issue