Skip to content
This repository has been archived by the owner on Mar 22, 2019. It is now read-only.

Modularize schemas #224

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"scripts": {
"build": "babel src/ -d dist/ --copy-files",
"start": "node dist/",
"dev": "nodemon --exec babel-node src/ -e js,graphql",
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js -e js,graphql",
"dev": "nodemon --exec babel-node src/ -e js,gql",
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js -e js,gql",
"lint": "eslint src --config .eslintrc.js",
"test": "nyc --reporter=text-lcov yarn run test:jest",
"test:cypress": "run-p --race test:before:*",
Expand Down Expand Up @@ -54,6 +54,7 @@
"jsonwebtoken": "~8.5.0",
"linkifyjs": "~2.1.8",
"lodash": "~4.17.11",
"merge-graphql-schemas": "^1.5.8",
"ms": "~2.1.1",
"neo4j-driver": "~1.7.3",
"neo4j-graphql-js": "~2.4.2",
Expand Down
9 changes: 2 additions & 7 deletions src/graphql-schema.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import fs from 'fs'
import path from 'path'
import userManagement from './resolvers/user_management.js'
import statistics from './resolvers/statistics.js'
import reports from './resolvers/reports.js'
import posts from './resolvers/posts.js'
import moderation from './resolvers/moderation.js'
import types from './types'

export const typeDefs = fs
.readFileSync(
process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql')
)
.toString('utf-8')
export const typeDefs = types

export const resolvers = {
Query: {
Expand Down
10 changes: 10 additions & 0 deletions src/schema.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
##########################################################
#
# ATTENTION! Please use the files inside src/types/
#
# This document is only used for merging
# and will not be processed by the system!
# It will be removed soon.
#
##########################################################

type Query {
isLoggedIn: Boolean!
"Get the currently logged in User based on the given JWT Token"
Expand Down
23 changes: 23 additions & 0 deletions src/types/badge.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
enum BadgeTypeEnum {
role
crowdfunding
}
enum BadgeStatusEnum {
permanent
temporary
}

type Badge {
id: ID!
key: String!
type: BadgeTypeEnum!
status: BadgeStatusEnum!
icon: String!

rewarded: [User]! @relation(name: "REWARDED", direction: "OUT")
}

type User {
badges: [Badge]! @relation(name: "REWARDED", direction: "IN")
badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)")
}
3 changes: 3 additions & 0 deletions src/types/blacklist.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type User {
blacklisted: [User]! @relation(name: "BLACKLISTED", direction: "OUT")
}
20 changes: 20 additions & 0 deletions src/types/category.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type Category {
id: ID!
name: String!
slug: String
icon: String!
posts: [Post]! @relation(name: "CATEGORIZED", direction: "IN")
postCount: Int! @cypher(statement: "MATCH (this)<-[:CATEGORIZED]-(r:Post) RETURN COUNT(r)")
}

type Post {
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
}

type Organization {
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
}

type User {
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
}
21 changes: 21 additions & 0 deletions src/types/comment.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
type Comment {
id: ID!
author: User @relation(name: "WROTE", direction: "IN")
content: String!
contentExcerpt: String
createdAt: String
updatedAt: String
deleted: Boolean
disabled: Boolean
disabledBy: User @relation(name: "DISABLED", direction: "IN")
}

type User {
comments: [Comment]! @relation(name: "WROTE", direction: "OUT")
commentsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment) WHERE NOT r.deleted = true RETURN COUNT(r)")
}

type Post {
comments: [Comment]! @relation(name: "COMMENTS", direction: "IN")
commentsCount: Int! @cypher(statement: "MATCH (this)<-[:COMMENTS]-(r:Comment) RETURN COUNT(r)")
}
4 changes: 4 additions & 0 deletions src/types/disable.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type Mutation {
disable(id: ID!): ID
enable(id: ID!): ID
}
37 changes: 37 additions & 0 deletions src/types/follow.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

enum FollowTypeEnum {
User
Organization
Project
}

type Mutation {
"Follow the given Type and ID"
follow(id: ID!, type: FollowTypeEnum): Boolean! @cypher(statement: """
MATCH (n {id: $id}), (u:User {id: $cypherParams.currentUserId})
WHERE $type IN labels(n) AND NOT $id = $cypherParams.currentUserId
MERGE (u)-[r:FOLLOWS]->(n)
RETURN COUNT(r) > 0
""")
"Unfollow the given Type and ID"
unfollow(id: ID!, type: FollowTypeEnum): Boolean! @cypher(statement: """
MATCH (:User {id: $cypherParams.currentUserId})-[r:FOLLOWS]->(n {id: $id})
WHERE $type IN labels(n)
DELETE r
RETURN COUNT(r) > 0
""")
}

type User {
following: [User]! @relation(name: "FOLLOWS", direction: "OUT")
followingCount: Int! @cypher(statement: "MATCH (this)-[:FOLLOWS]->(r:User) RETURN COUNT(DISTINCT r)")

followedBy: [User]! @relation(name: "FOLLOWS", direction: "IN")
followedByCount: Int! @cypher(statement: "MATCH (this)<-[:FOLLOWS]-(r:User) RETURN COUNT(DISTINCT r)")

"Is the currently logged in user following that user?"
followedByCurrentUser: Boolean! @cypher(statement: """
MATCH (this)<-[:FOLLOWS]-(u:User {id: $cypherParams.currentUserId})
RETURN COUNT(u) >= 1
""")
}
4 changes: 4 additions & 0 deletions src/types/friends.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type User {
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")
}
17 changes: 17 additions & 0 deletions src/types/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import fs from 'fs'
import path from 'path'
import { mergeTypes } from 'merge-graphql-schemas'

const loadSchema = file => {
return fs.readFileSync(path.join(__dirname, file)).toString('utf-8')
}

let typeDefs = []

fs.readdirSync(__dirname).forEach(file => {
if (file.split('.').pop() === 'gql') {
typeDefs.push(loadSchema(file))
}
})

export default mergeTypes(typeDefs, { all: true })
16 changes: 16 additions & 0 deletions src/types/location.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Location {
id: ID!
name: String!
nameEN: String
nameDE: String
nameFR: String
nameNL: String
nameIT: String
nameES: String
namePT: String
namePL: String
type: String!
lat: Float
lng: Float
parent: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
}
16 changes: 16 additions & 0 deletions src/types/organization.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Organization {
id: ID!
createdBy: User @relation(name: "CREATED_ORGA", direction: "IN")
ownedBy: [User] @relation(name: "OWNING_ORGA", direction: "IN")
name: String!
slug: String
description: String!
descriptionExcerpt: String
deleted: Boolean
disabled: Boolean
}

type User {
organizationsCreated: [Organization] @relation(name: "CREATED_ORGA", direction: "OUT")
organizationsOwned: [Organization] @relation(name: "OWNING_ORGA", direction: "OUT")
}
43 changes: 43 additions & 0 deletions src/types/post.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
enum VisibilityEnum {
public
friends
private
}

type Post {
id: ID!
author: User @relation(name: "WROTE", direction: "IN")
title: String!
slug: String
content: String!
contentExcerpt: String
image: String
visibility: VisibilityEnum
deleted: Boolean
disabled: Boolean
disabledBy: User @relation(name: "DISABLED", direction: "IN")
createdAt: String
updatedAt: String

relatedContributions: [Post]! @cypher(statement: """
MATCH (this)-[:TAGGED|CATEGORIZED]->(categoryOrTag)<-[:TAGGED|CATEGORIZED]-(post:Post)
WHERE (NOT exists(post.deleted) OR post.deleted = false)
AND (NOT exists(post.disabled) OR post.disabled = false)
RETURN DISTINCT post
LIMIT 10
""")
}

type User {
contributions: [Post]! @relation(name: "WROTE", direction: "OUT")
contributionsCount: Int! @cypher(statement: """
MATCH (this)-[:WROTE]->(r:Post)
WHERE (NOT exists(r.deleted) OR r.deleted = false)
AND (NOT exists(r.disabled) OR r.disabled = false)
RETURN COUNT(r)"""
)
}

type Comment {
post: Post @relation(name: "COMMENTS", direction: "OUT")
}
14 changes: 14 additions & 0 deletions src/types/report.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Mutation {
report(id: ID!, description: String): Report
}

type Report {
id: ID!
submitter: User @relation(name: "REPORTED", direction: "IN")
description: String
type: String! @cypher(statement: "MATCH (resource)<-[:REPORTED]-(this) RETURN labels(resource)[0]")
createdAt: String
comment: Comment @relation(name: "REPORTED", direction: "OUT")
post: Post @relation(name: "REPORTED", direction: "OUT")
user: User @relation(name: "REPORTED", direction: "OUT")
}
38 changes: 38 additions & 0 deletions src/types/shout.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
enum ShoutTypeEnum {
Post
Organization
Project
}

type Mutation {
"Shout the given Type and ID"
shout(id: ID!, type: ShoutTypeEnum): Boolean! @cypher(statement: """
MATCH (n {id: $id})<-[:WROTE]-(wu:User), (u:User {id: $cypherParams.currentUserId})
WHERE $type IN labels(n) AND NOT wu.id = $cypherParams.currentUserId
MERGE (u)-[r:SHOUTED]->(n)
RETURN COUNT(r) > 0
""")

"Unshout the given Type and ID"
unshout(id: ID!, type: ShoutTypeEnum): Boolean! @cypher(statement: """
MATCH (:User {id: $cypherParams.currentUserId})-[r:SHOUTED]->(n {id: $id})
WHERE $type IN labels(n)
DELETE r
RETURN COUNT(r) > 0
""")
}

type User {
shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT")
shoutedCount: Int! @cypher(statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)")
}
type Post {
shoutedBy: [User]! @relation(name: "SHOUTED", direction: "IN")
shoutedCount: Int! @cypher(statement: "MATCH (this)<-[:SHOUTED]-(r:User) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)")

"Has the currently logged in user shouted that post?"
shoutedByCurrentUser: Boolean! @cypher(statement: """
MATCH (this)<-[:SHOUTED]-(u:User {id: $cypherParams.currentUserId})
RETURN COUNT(u) >= 1
""")
}
16 changes: 16 additions & 0 deletions src/types/statistics.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type Query {
"Get the latest Network Statistics"
statistics: Statistics!
}

type Statistics {
countUsers: Int!
countPosts: Int!
countComments: Int!
countNotifications: Int!
countOrganizations: Int!
countProjects: Int!
countInvites: Int!
countFollows: Int!
countShouts: Int!
}
18 changes: 18 additions & 0 deletions src/types/tag.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
type Tag {
id: ID!
name: String!
taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN")
taggedOrganizations: [Organization]! @relation(name: "TAGGED", direction: "IN")
taggedCount: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p) RETURN COUNT(DISTINCT p)")
taggedCountUnique: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p)<-[:WROTE]-(u:User) RETURN COUNT(DISTINCT u)")
deleted: Boolean
disabled: Boolean
}

type Post {
tags: [Tag]! @relation(name: "TAGGED", direction: "OUT")
}

type Organization {
tags: [Tag]! @relation(name: "TAGGED", direction: "OUT")
}
Loading