diff --git a/packages/server/src/resolvers/index.ts b/packages/server/src/resolvers/index.ts deleted file mode 100644 index 1e4821a..0000000 --- a/packages/server/src/resolvers/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as G from "../generated/graphql"; -import { history } from "./history"; -import { mutation } from "./mutation"; -import { query } from "./query"; -import { - res, - resDelete, - resFork, - resHistory, - resNormal, - resTopic, -} from "./res"; -import { subscription } from "./subscription"; -import { token, tokenGeneral } from "./token"; -import { topic, topicFork, topicNormal, topicOne, topicSearch } from "./topic"; -import { DateTimeResolver } from "graphql-scalars"; - -export const resolvers: G.Resolvers = { - DateTime: DateTimeResolver, - History: history, - Mutation: mutation, - Query: query, - Res: res, - ResNormal: resNormal, - ResHistory: resHistory, - ResTopic: resTopic, - ResDelete: resDelete, - ResFork: resFork, - Subscription: subscription, - Token: token, - TokenGeneral: tokenGeneral, - Topic: topic, - TopicSearch: topicSearch, - TopicFork: topicFork, - TopicOne: topicOne, - TopicNormal: topicNormal, -}; diff --git a/packages/server/src/resolvers/res.ts b/packages/server/src/resolvers/res.ts deleted file mode 100644 index 19ac541..0000000 --- a/packages/server/src/resolvers/res.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as G from "../generated/graphql"; -import { getHistory, getProfile, getRes, getTopic } from "../usecases"; - -const resBase: Pick = { - topic: async (res, _args, context, _info) => { - const topic = await getTopic({ id: res.topicID }, context.ports); - return topic; - }, -}; - -export const resNormal: G.ResNormalResolvers = { - ...resBase, - reply: async (res, _args, context, _info) => { - if (res.replyID !== null) { - const reply = await getRes({ id: res.replyID }, context.ports); - return reply; - } else { - return null; - } - }, - profile: async (res, _args, context, _info) => { - if (res.profileID !== null) { - const profile = await getProfile({ id: res.profileID }, context.ports); - return profile; - } else { - return null; - } - }, -}; - -export const resHistory: G.ResHistoryResolvers = { - ...resBase, - history: async (res, _args, context, _info) => { - const history = await getHistory({ id: res.historyID }, context.ports); - return history; - }, -}; - -export const resTopic: G.ResTopicResolvers = { - ...resBase, -}; - -export const resFork: G.ResForkResolvers = { - ...resBase, - fork: async (res, _args, context, _info) => { - const fork = await getTopic({ id: res.forkID }, context.ports); - if (fork.type !== "fork") { - throw new Error(); - } - return fork; - }, -}; - -export const resDelete: G.ResDeleteResolvers = { - ...resBase, -}; diff --git a/packages/server/src/resolvers/subscription.ts b/packages/server/src/resolvers/subscription.ts deleted file mode 100644 index bd8fb19..0000000 --- a/packages/server/src/resolvers/subscription.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as G from "../generated/graphql"; -import * as ixa from "ix/asynciterable"; -import * as ixaOps from "ix/asynciterable/operators"; - -export const subscription: G.SubscriptionResolvers = { - resAdded: { - subscribe: (_parent, args, context, _info) => - ixa.from(context.ports.resRepo.subscribeInsertEvent(args.topic)).pipe( - ixaOps.map((data) => ({ - resAdded: { - count: data.count, - res: data.res.toAPI(context.ports.authContainer.getTokenOrNull()), - }, - })) - ), - }, -}; diff --git a/packages/server/src/resolvers/topic.ts b/packages/server/src/resolvers/topic.ts deleted file mode 100644 index d02bb03..0000000 --- a/packages/server/src/resolvers/topic.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as G from "../generated/graphql"; -import { getTopic } from "../usecases"; -import * as O from "fp-ts/Option"; - -export const topic: G.TopicResolvers = { - __resolveType(obj) { - switch (obj.type) { - case "normal": - return "TopicNormal"; - case "one": - return "TopicOne"; - case "fork": - return "TopicFork"; - } - }, - subscribe: async (topic, _args, context, _info) => { - // TODO: N+1 - const token = context.ports.authContainer.getTokenOrNull(); - if (O.isNone(token)) { - return null; - } - return await context.ports.topicRepo.getSubscription( - topic.id, - token.value.user - ); - }, -}; - -export const topicSearch: G.TopicSearchResolvers = { - __resolveType(obj) { - switch (obj.type) { - case "normal": - return "TopicNormal"; - case "one": - return "TopicOne"; - } - }, -}; - -export const topicFork: G.TopicForkResolvers = { - parent: async (token, _args, context, _info) => { - const parent = await getTopic({ id: token.parentID }, context.ports); - if (parent.type !== "normal") { - throw new Error(); - } - return parent; - }, - subscribe: topic.subscribe, -}; - -export const topicOne: G.TopicOneResolvers = { - subscribe: topic.subscribe, -}; - -export const topicNormal: G.TopicNormalResolvers = { - subscribe: topic.subscribe, -}; diff --git a/packages/server/src/schema/res/resolvers/ResBase.ts b/packages/server/src/schema/res/resolvers/ResBase.ts new file mode 100644 index 0000000..3430b77 --- /dev/null +++ b/packages/server/src/schema/res/resolvers/ResBase.ts @@ -0,0 +1,9 @@ +import { getTopic } from "../../../usecases"; +import type { ResResolvers } from "./../../types.generated"; + +export const ResBase: Omit = { + topic: async (res, _args, context, _info) => { + const topic = await getTopic({ id: res.topicID }, context.ports); + return topic; + }, +}; diff --git a/packages/server/src/schema/res/resolvers/ResDelete.ts b/packages/server/src/schema/res/resolvers/ResDelete.ts index feac80b..336dac0 100644 --- a/packages/server/src/schema/res/resolvers/ResDelete.ts +++ b/packages/server/src/schema/res/resolvers/ResDelete.ts @@ -1,13 +1,6 @@ -import type { ResDeleteResolvers } from './../../types.generated'; - export const ResDelete: ResDeleteResolvers = { - /* Implement ResDelete resolver logic here */ - date: () => { /* ResDelete.date resolver is required because ResDelete.date exists but ResDeleteMapper.date does not */ }, - dv: () => { /* ResDelete.dv resolver is required because ResDelete.dv exists but ResDeleteMapper.dv does not */ }, - hash: () => { /* ResDelete.hash resolver is required because ResDelete.hash exists but ResDeleteMapper.hash does not */ }, - id: () => { /* ResDelete.id resolver is required because ResDelete.id exists but ResDeleteMapper.id does not */ }, - replyCount: () => { /* ResDelete.replyCount resolver is required because ResDelete.replyCount exists but ResDeleteMapper.replyCount does not */ }, - self: () => { /* ResDelete.self resolver is required because ResDelete.self exists but ResDeleteMapper.self does not */ }, - topic: () => { /* ResDelete.topic resolver is required because ResDelete.topic exists but ResDeleteMapper.topic does not */ }, - uv: () => { /* ResDelete.uv resolver is required because ResDelete.uv exists but ResDeleteMapper.uv does not */ }, - voteFlag: () => { /* ResDelete.voteFlag resolver is required because ResDelete.voteFlag exists but ResDeleteMapper.voteFlag does not */ } - }; \ No newline at end of file +import type { ResDeleteResolvers } from "./../../types.generated"; +import { ResBase } from "./ResBase"; + +export const ResDelete: ResDeleteResolvers = { + ...ResBase, +}; diff --git a/packages/server/src/schema/res/resolvers/ResFork.ts b/packages/server/src/schema/res/resolvers/ResFork.ts index d2ec54c..7c2df03 100644 --- a/packages/server/src/schema/res/resolvers/ResFork.ts +++ b/packages/server/src/schema/res/resolvers/ResFork.ts @@ -1,14 +1,14 @@ -import type { ResForkResolvers } from './../../types.generated'; - export const ResFork: ResForkResolvers = { - /* Implement ResFork resolver logic here */ - date: () => { /* ResFork.date resolver is required because ResFork.date exists but ResForkMapper.date does not */ }, - dv: () => { /* ResFork.dv resolver is required because ResFork.dv exists but ResForkMapper.dv does not */ }, - hash: () => { /* ResFork.hash resolver is required because ResFork.hash exists but ResForkMapper.hash does not */ }, - id: () => { /* ResFork.id resolver is required because ResFork.id exists but ResForkMapper.id does not */ }, - replyCount: () => { /* ResFork.replyCount resolver is required because ResFork.replyCount exists but ResForkMapper.replyCount does not */ }, - self: () => { /* ResFork.self resolver is required because ResFork.self exists but ResForkMapper.self does not */ }, - topic: () => { /* ResFork.topic resolver is required because ResFork.topic exists but ResForkMapper.topic does not */ }, - uv: () => { /* ResFork.uv resolver is required because ResFork.uv exists but ResForkMapper.uv does not */ }, - voteFlag: () => { /* ResFork.voteFlag resolver is required because ResFork.voteFlag exists but ResForkMapper.voteFlag does not */ }, - fork: () => { /* ResFork.fork resolver is required because ResFork.fork exists but ResForkMapper.fork does not */ } - }; \ No newline at end of file +import { getTopic } from "../../../usecases"; +import type { ResForkResolvers } from "./../../types.generated"; +import { ResBase } from "./ResBase"; + +export const ResFork: ResForkResolvers = { + ...ResBase, + fork: async (res, _args, context, _info) => { + const fork = await getTopic({ id: res.forkID }, context.ports); + if (fork.type !== "fork") { + throw new Error(); + } + return fork; + }, +}; diff --git a/packages/server/src/schema/res/resolvers/ResHistory.ts b/packages/server/src/schema/res/resolvers/ResHistory.ts index ce82d48..f6e9a33 100644 --- a/packages/server/src/schema/res/resolvers/ResHistory.ts +++ b/packages/server/src/schema/res/resolvers/ResHistory.ts @@ -1,14 +1,11 @@ -import type { ResHistoryResolvers } from './../../types.generated'; - export const ResHistory: ResHistoryResolvers = { - /* Implement ResHistory resolver logic here */ - date: () => { /* ResHistory.date resolver is required because ResHistory.date exists but ResHistoryMapper.date does not */ }, - dv: () => { /* ResHistory.dv resolver is required because ResHistory.dv exists but ResHistoryMapper.dv does not */ }, - hash: () => { /* ResHistory.hash resolver is required because ResHistory.hash exists but ResHistoryMapper.hash does not */ }, - id: () => { /* ResHistory.id resolver is required because ResHistory.id exists but ResHistoryMapper.id does not */ }, - replyCount: () => { /* ResHistory.replyCount resolver is required because ResHistory.replyCount exists but ResHistoryMapper.replyCount does not */ }, - self: () => { /* ResHistory.self resolver is required because ResHistory.self exists but ResHistoryMapper.self does not */ }, - topic: () => { /* ResHistory.topic resolver is required because ResHistory.topic exists but ResHistoryMapper.topic does not */ }, - uv: () => { /* ResHistory.uv resolver is required because ResHistory.uv exists but ResHistoryMapper.uv does not */ }, - voteFlag: () => { /* ResHistory.voteFlag resolver is required because ResHistory.voteFlag exists but ResHistoryMapper.voteFlag does not */ }, - history: () => { /* ResHistory.history resolver is required because ResHistory.history exists but ResHistoryMapper.history does not */ } - }; \ No newline at end of file +import { getHistory } from "../../../usecases"; +import type { ResHistoryResolvers } from "./../../types.generated"; +import { ResBase } from "./ResBase"; + +export const ResHistory: ResHistoryResolvers = { + ...ResBase, + history: async (res, _args, context, _info) => { + const history = await getHistory({ id: res.historyID }, context.ports); + return history; + }, +}; diff --git a/packages/server/src/schema/res/resolvers/ResNormal.ts b/packages/server/src/schema/res/resolvers/ResNormal.ts index 29fa310..2ba862c 100644 --- a/packages/server/src/schema/res/resolvers/ResNormal.ts +++ b/packages/server/src/schema/res/resolvers/ResNormal.ts @@ -1,15 +1,23 @@ -import type { ResNormalResolvers } from './../../types.generated'; - export const ResNormal: ResNormalResolvers = { - /* Implement ResNormal resolver logic here */ - date: () => { /* ResNormal.date resolver is required because ResNormal.date exists but ResNormalMapper.date does not */ }, - dv: () => { /* ResNormal.dv resolver is required because ResNormal.dv exists but ResNormalMapper.dv does not */ }, - hash: () => { /* ResNormal.hash resolver is required because ResNormal.hash exists but ResNormalMapper.hash does not */ }, - id: () => { /* ResNormal.id resolver is required because ResNormal.id exists but ResNormalMapper.id does not */ }, - replyCount: () => { /* ResNormal.replyCount resolver is required because ResNormal.replyCount exists but ResNormalMapper.replyCount does not */ }, - self: () => { /* ResNormal.self resolver is required because ResNormal.self exists but ResNormalMapper.self does not */ }, - topic: () => { /* ResNormal.topic resolver is required because ResNormal.topic exists but ResNormalMapper.topic does not */ }, - uv: () => { /* ResNormal.uv resolver is required because ResNormal.uv exists but ResNormalMapper.uv does not */ }, - voteFlag: () => { /* ResNormal.voteFlag resolver is required because ResNormal.voteFlag exists but ResNormalMapper.voteFlag does not */ }, - profile: () => { /* ResNormal.profile resolver is required because ResNormal.profile exists but ResNormalMapper.profile does not */ }, - reply: () => { /* ResNormal.reply resolver is required because ResNormal.reply exists but ResNormalMapper.reply does not */ } - }; \ No newline at end of file +import { getProfile, getRes } from "../../../usecases"; +import type { ResNormalResolvers } from "./../../types.generated"; +import { ResBase } from "./ResBase"; + +export const ResNormal: ResNormalResolvers = { + ...ResBase, + reply: async (res, _args, context, _info) => { + if (res.replyID !== null) { + const reply = await getRes({ id: res.replyID }, context.ports); + return reply; + } else { + return null; + } + }, + profile: async (res, _args, context, _info) => { + if (res.profileID !== null) { + const profile = await getProfile({ id: res.profileID }, context.ports); + return profile; + } else { + return null; + } + }, +}; diff --git a/packages/server/src/schema/res/resolvers/ResTopic.ts b/packages/server/src/schema/res/resolvers/ResTopic.ts index 22a19cd..be488ea 100644 --- a/packages/server/src/schema/res/resolvers/ResTopic.ts +++ b/packages/server/src/schema/res/resolvers/ResTopic.ts @@ -1,5 +1,6 @@ -import type { ResTopicResolvers } from './../../types.generated'; - export const ResTopic: ResTopicResolvers = { - /* Implement ResTopic resolver logic here */ - topic: () => { /* ResTopic.topic resolver is required because ResTopic.topic exists but ResTopicMapper.topic does not */ } - }; \ No newline at end of file +import type { ResTopicResolvers } from "./../../types.generated"; +import { ResBase } from "./ResBase"; + +export const ResTopic: ResTopicResolvers = { + ...ResBase, +}; diff --git a/packages/server/src/schema/res/resolvers/Subscription/resAdded.ts b/packages/server/src/schema/res/resolvers/Subscription/resAdded.ts index 511b3ae..50f9b34 100644 --- a/packages/server/src/schema/res/resolvers/Subscription/resAdded.ts +++ b/packages/server/src/schema/res/resolvers/Subscription/resAdded.ts @@ -1,4 +1,15 @@ -import type { SubscriptionResolvers } from './../../../types.generated'; - export const resAdded: NonNullable = { - subscribe: async (_parent, _arg, _ctx) => { /* Implement Subscription.resAdded resolver logic here */ }, - } \ No newline at end of file +import type { SubscriptionResolvers } from "./../../../types.generated"; +import * as ixa from "ix/asynciterable"; +import * as ixaOps from "ix/asynciterable/operators"; + +export const resAdded: NonNullable = { + subscribe: (_parent, args, context, _info) => + ixa.from(context.ports.resRepo.subscribeInsertEvent(args.topic)).pipe( + ixaOps.map((data) => ({ + resAdded: { + count: data.count, + res: data.res.toAPI(context.ports.authContainer.getTokenOrNull()), + }, + })) + ), +}; diff --git a/packages/server/src/schema/resolveTypes.ts b/packages/server/src/schema/resolveTypes.ts index ca68854..00a1009 100644 --- a/packages/server/src/schema/resolveTypes.ts +++ b/packages/server/src/schema/resolveTypes.ts @@ -27,4 +27,26 @@ export const resolveTypes: Resolvers = { } }, }, + Topic: { + __resolveType(obj) { + switch (obj.type) { + case "normal": + return "TopicNormal"; + case "one": + return "TopicOne"; + case "fork": + return "TopicFork"; + } + }, + }, + TopicSearch: { + __resolveType(obj) { + switch (obj.type) { + case "normal": + return "TopicNormal"; + case "one": + return "TopicOne"; + } + }, + }, }; diff --git a/packages/server/src/schema/topic/resolvers/TopicBase.ts b/packages/server/src/schema/topic/resolvers/TopicBase.ts new file mode 100644 index 0000000..ef0468f --- /dev/null +++ b/packages/server/src/schema/topic/resolvers/TopicBase.ts @@ -0,0 +1,16 @@ +import type { TopicResolvers } from "./../../types.generated"; +import * as O from "fp-ts/lib/Option"; + +export const TopicBase: Omit = { + subscribe: async (topic, _args, context, _info) => { + // TODO: N+1 + const token = context.ports.authContainer.getTokenOrNull(); + if (O.isNone(token)) { + return null; + } + return await context.ports.topicRepo.getSubscription( + topic.id, + token.value.user + ); + }, +}; diff --git a/packages/server/src/schema/topic/resolvers/TopicFork.ts b/packages/server/src/schema/topic/resolvers/TopicFork.ts index 8563b47..c5d887a 100644 --- a/packages/server/src/schema/topic/resolvers/TopicFork.ts +++ b/packages/server/src/schema/topic/resolvers/TopicFork.ts @@ -1,12 +1,14 @@ -import type { TopicForkResolvers } from './../../types.generated'; - export const TopicFork: TopicForkResolvers = { - /* Implement TopicFork resolver logic here */ - active: () => { /* TopicFork.active resolver is required because TopicFork.active exists but TopicForkMapper.active does not */ }, - date: () => { /* TopicFork.date resolver is required because TopicFork.date exists but TopicForkMapper.date does not */ }, - id: () => { /* TopicFork.id resolver is required because TopicFork.id exists but TopicForkMapper.id does not */ }, - resCount: () => { /* TopicFork.resCount resolver is required because TopicFork.resCount exists but TopicForkMapper.resCount does not */ }, - subscribe: () => { /* TopicFork.subscribe resolver is required because TopicFork.subscribe exists but TopicForkMapper.subscribe does not */ }, - title: () => { /* TopicFork.title resolver is required because TopicFork.title exists but TopicForkMapper.title does not */ }, - update: () => { /* TopicFork.update resolver is required because TopicFork.update exists but TopicForkMapper.update does not */ }, - parent: () => { /* TopicFork.parent resolver is required because TopicFork.parent exists but TopicForkMapper.parent does not */ } - }; \ No newline at end of file +import { getTopic } from "../../../usecases"; +import type { TopicForkResolvers } from "./../../types.generated"; +import { TopicBase } from "./TopicBase"; + +export const TopicFork: TopicForkResolvers = { + ...TopicBase, + parent: async (token, _args, context, _info) => { + const parent = await getTopic({ id: token.parentID }, context.ports); + if (parent.type !== "normal") { + throw new Error(); + } + return parent; + }, +}; diff --git a/packages/server/src/schema/topic/resolvers/TopicNormal.ts b/packages/server/src/schema/topic/resolvers/TopicNormal.ts index 1137325..effd473 100644 --- a/packages/server/src/schema/topic/resolvers/TopicNormal.ts +++ b/packages/server/src/schema/topic/resolvers/TopicNormal.ts @@ -1,5 +1,6 @@ -import type { TopicNormalResolvers } from './../../types.generated'; - export const TopicNormal: TopicNormalResolvers = { - /* Implement TopicNormal resolver logic here */ - subscribe: () => { /* TopicNormal.subscribe resolver is required because TopicNormal.subscribe exists but TopicNormalMapper.subscribe does not */ } - }; \ No newline at end of file +import type { TopicNormalResolvers } from "./../../types.generated"; +import { TopicSearchBase } from "./TopicSearchBase"; + +export const TopicNormal: TopicNormalResolvers = { + ...TopicSearchBase, +}; diff --git a/packages/server/src/schema/topic/resolvers/TopicOne.ts b/packages/server/src/schema/topic/resolvers/TopicOne.ts index 75c02d1..fb24373 100644 --- a/packages/server/src/schema/topic/resolvers/TopicOne.ts +++ b/packages/server/src/schema/topic/resolvers/TopicOne.ts @@ -1,5 +1,6 @@ -import type { TopicOneResolvers } from './../../types.generated'; - export const TopicOne: TopicOneResolvers = { - /* Implement TopicOne resolver logic here */ - subscribe: () => { /* TopicOne.subscribe resolver is required because TopicOne.subscribe exists but TopicOneMapper.subscribe does not */ } - }; \ No newline at end of file +import type { TopicOneResolvers } from "./../../types.generated"; +import { TopicSearchBase } from "./TopicSearchBase"; + +export const TopicOne: TopicOneResolvers = { + ...TopicSearchBase, +}; diff --git a/packages/server/src/schema/topic/resolvers/TopicSearchBase.ts b/packages/server/src/schema/topic/resolvers/TopicSearchBase.ts new file mode 100644 index 0000000..5a8843b --- /dev/null +++ b/packages/server/src/schema/topic/resolvers/TopicSearchBase.ts @@ -0,0 +1,6 @@ +import type { TopicSearchResolvers } from "./../../types.generated"; +import { TopicBase } from "./TopicBase"; + +export const TopicSearchBase: Omit = { + ...TopicBase, +};