2021-04-12 18:05:09 +00:00
|
|
|
import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
|
|
|
|
2021-04-14 00:57:32 +00:00
|
|
|
const createItem = async (parent, { title, text, url, parentId }, { me, models }) => {
|
|
|
|
if (!me) {
|
|
|
|
throw new AuthenticationError('You must be logged in')
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
title,
|
|
|
|
url,
|
|
|
|
text,
|
|
|
|
user: {
|
|
|
|
connect: {
|
|
|
|
name: me.name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parentId) {
|
|
|
|
data.parent = {
|
|
|
|
connect: {
|
|
|
|
id: parseInt(parentId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-17 18:15:18 +00:00
|
|
|
const item = await models.item.create({ data })
|
|
|
|
item.comments = []
|
|
|
|
return item
|
|
|
|
}
|
|
|
|
|
|
|
|
function nestComments (flat, parentId) {
|
|
|
|
const result = []
|
|
|
|
let added = 0
|
|
|
|
for (let i = 0; i < flat.length;) {
|
|
|
|
if (!flat[i].comments) flat[i].comments = []
|
|
|
|
if (Number(flat[i].parentId) === Number(parentId)) {
|
|
|
|
result.push(flat[i])
|
|
|
|
added++
|
|
|
|
i++
|
|
|
|
} else if (result.length > 0) {
|
|
|
|
const item = result[result.length - 1]
|
|
|
|
const [nested, newAdded] = nestComments(flat.slice(i), item.id)
|
|
|
|
if (newAdded === 0) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
item.comments.push(...nested)
|
|
|
|
i += newAdded
|
|
|
|
added += newAdded
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [result, added]
|
2021-04-14 00:57:32 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 22:14:32 +00:00
|
|
|
// we have to do our own query because ltree is unsupported
|
|
|
|
const SELECT =
|
|
|
|
`SELECT id, created_at as "createdAt", updated_at as "updatedAt", title,
|
|
|
|
text, url, "userId", "parentId", ltree2text("path") AS "path"`
|
|
|
|
|
2021-04-12 18:05:09 +00:00
|
|
|
export default {
|
|
|
|
Query: {
|
|
|
|
items: async (parent, args, { models }) => {
|
2021-04-14 23:56:29 +00:00
|
|
|
return await models.$queryRaw(`
|
2021-04-22 22:14:32 +00:00
|
|
|
${SELECT}
|
2021-04-14 23:56:29 +00:00
|
|
|
FROM "Item"
|
2021-04-15 19:41:02 +00:00
|
|
|
WHERE "parentId" IS NULL`)
|
2021-04-14 23:56:29 +00:00
|
|
|
},
|
|
|
|
item: async (parent, { id }, { models }) => {
|
2021-04-22 22:14:32 +00:00
|
|
|
return (await models.$queryRaw(`
|
|
|
|
${SELECT}
|
2021-04-14 23:56:29 +00:00
|
|
|
FROM "Item"
|
2021-04-22 22:14:32 +00:00
|
|
|
WHERE id = ${id}`))[0]
|
2021-04-14 23:56:29 +00:00
|
|
|
},
|
2021-04-22 22:14:32 +00:00
|
|
|
userItems: async (parent, { userId }, { models }) => {
|
2021-04-12 18:05:09 +00:00
|
|
|
return await models.$queryRaw(`
|
2021-04-22 22:14:32 +00:00
|
|
|
${SELECT}
|
2021-04-12 18:05:09 +00:00
|
|
|
FROM "Item"
|
2021-04-22 22:14:32 +00:00
|
|
|
WHERE "userId" = ${userId} AND "parentId" IS NULL
|
|
|
|
ORDER BY created_at DESC`)
|
2021-04-15 19:41:02 +00:00
|
|
|
},
|
2021-04-17 18:15:18 +00:00
|
|
|
comments: async (parent, { parentId }, { models }) => {
|
|
|
|
const flat = await models.$queryRaw(`
|
2021-04-22 22:14:32 +00:00
|
|
|
${SELECT}
|
2021-04-17 18:15:18 +00:00
|
|
|
FROM "Item"
|
|
|
|
WHERE path <@ (SELECT path FROM "Item" where id = ${parentId}) AND id != ${parentId}
|
|
|
|
ORDER BY "path"`)
|
|
|
|
return nestComments(flat, parentId)[0]
|
|
|
|
},
|
2021-04-22 22:14:32 +00:00
|
|
|
userComments: async (parent, { userId }, { models }) => {
|
|
|
|
return await models.$queryRaw(`
|
|
|
|
${SELECT}
|
|
|
|
FROM "Item"
|
|
|
|
WHERE "userId" = ${userId} AND "parentId" IS NOT NULL
|
|
|
|
ORDER BY created_at DESC`)
|
|
|
|
},
|
2021-04-15 19:41:02 +00:00
|
|
|
root: async (parent, { id }, { models }) => {
|
2021-04-22 22:14:32 +00:00
|
|
|
return (await models.$queryRaw(`
|
|
|
|
${SELECT}
|
2021-04-15 19:41:02 +00:00
|
|
|
FROM "Item"
|
2021-04-22 22:14:32 +00:00
|
|
|
WHERE id = (
|
|
|
|
SELECT ltree2text(subltree(path, 0, 1))::integer
|
|
|
|
FROM "Item"
|
|
|
|
WHERE id = ${id})`))[0]
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
Mutation: {
|
2021-04-14 00:57:32 +00:00
|
|
|
createLink: async (parent, { title, url }, { me, models }) => {
|
|
|
|
if (!title) {
|
|
|
|
throw new UserInputError('Link must have title', { argumentName: 'title' })
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 00:57:32 +00:00
|
|
|
if (!url) {
|
|
|
|
throw new UserInputError('Link must have url', { argumentName: 'url' })
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 00:57:32 +00:00
|
|
|
return await createItem(parent, { title, url }, { me, models })
|
|
|
|
},
|
|
|
|
createDiscussion: async (parent, { title, text }, { me, models }) => {
|
|
|
|
if (!title) {
|
|
|
|
throw new UserInputError('Link must have title', { argumentName: 'title' })
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 00:57:32 +00:00
|
|
|
return await createItem(parent, { title, text }, { me, models })
|
|
|
|
},
|
|
|
|
createComment: async (parent, { text, parentId }, { me, models }) => {
|
|
|
|
if (!text) {
|
|
|
|
throw new UserInputError('Comment must have text', { argumentName: 'text' })
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!parentId) {
|
2021-04-14 23:56:29 +00:00
|
|
|
throw new UserInputError('Comment must have parent', { argumentName: 'text' })
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 00:57:32 +00:00
|
|
|
return await createItem(parent, { text, parentId }, { me, models })
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
Item: {
|
|
|
|
user: async (item, args, { models }) =>
|
|
|
|
await models.user.findUnique({ where: { id: item.userId } }),
|
2021-04-14 23:56:29 +00:00
|
|
|
ncomments: async (item, args, { models }) => {
|
|
|
|
const [{ count }] = await models.$queryRaw`
|
|
|
|
SELECT count(*)
|
|
|
|
FROM "Item"
|
2021-04-15 19:41:02 +00:00
|
|
|
WHERE path <@ text2ltree(${item.path}) AND id != ${item.id}`
|
2021-04-14 23:56:29 +00:00
|
|
|
return count
|
|
|
|
},
|
2021-04-14 00:57:32 +00:00
|
|
|
sats: () => 0
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
|
|
|
}
|