fix easy types

This commit is contained in:
Ulf Gebhardt 2026-02-23 10:28:04 +01:00
parent fc5d3aca8e
commit a3db2ae89e
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
37 changed files with 337 additions and 379 deletions

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/require-await */
import { hashSync } from 'bcryptjs'
import { v4 as uuid } from 'uuid'
@ -18,7 +17,7 @@ const defaultAdmin = {
const createDefaultAdminUser = async () => {
const driver = getDriver()
const session = driver.session()
const createAdminTxResultPromise = session.writeTransaction(async (txc) => {
const createAdminTxResultPromise = session.writeTransaction((txc) => {
txc.run(
`MERGE (e:EmailAddress {
email: "${defaultAdmin.email}",

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -38,10 +37,10 @@ const swap = async function (next) {
}
}
export async function up(next) {
export function up(next) {
swap(next)
}
export async function down(next) {
export function down(next) {
swap(next)
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -42,7 +41,7 @@ export async function up(next) {
}
}
export async function down(next) {
export function down(next) {
// eslint-disable-next-line no-console
console.log('Irreversible migration')
next()

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -44,7 +43,7 @@ export async function up(next) {
}
}
export async function down(next) {
export function down(next) {
// eslint-disable-next-line no-console
console.log('Irreversible migration')
next()

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-return */
@ -65,6 +64,6 @@ export async function up(next) {
}
}
export async function down() {
export function down() {
throw new Error('Irreversible migration')
}

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-base-to-string */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { getDriver } from '@db/neo4j'
@ -31,9 +30,9 @@ export async function up(_next) {
eventEnd = date.toISOString()
}
await transaction.run(`
MATCH (e:Event { id: '${id}' })
SET e.eventStart = '${eventStart}'
SET (CASE WHEN exists(e.eventEnd) THEN e END).eventEnd = '${eventEnd}'
MATCH (e:Event { id: '${String(id)}' })
SET e.eventStart = '${String(eventStart)}'
SET (CASE WHEN exists(e.eventEnd) THEN e END).eventEnd = '${String(eventEnd)}'
RETURN e
`)
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-floating-promises */
import CONFIG from '@config/index'
@ -16,7 +15,7 @@ if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
process.exit(0)
// eslint-disable-next-line no-catch-all/no-catch-all
} catch (err) {
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) // eslint-disable-line no-console
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${String(err)}`) // eslint-disable-line no-console
process.exit(1)
}
})()

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-floating-promises */
import CONFIG from '@config/index'
@ -16,7 +15,7 @@ if (CONFIG.PRODUCTION && !CONFIG.PRODUCTION_DB_CLEAN_ALLOW) {
process.exit(0)
// eslint-disable-next-line no-catch-all/no-catch-all
} catch (err) {
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`) // eslint-disable-line no-console
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${String(err)}`) // eslint-disable-line no-console
process.exit(1)
}
})()

View File

@ -3,7 +3,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable n/no-unpublished-import */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
import { faker } from '@faker-js/faker'

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -29,7 +28,7 @@ export const defaultVerificationBadge = {
export default {
Query: {
Badge: async (object, args, context, resolveInfo) =>
Badge: (object, args, context, resolveInfo) =>
neo4jgraphql(object, args, context, resolveInfo),
},
@ -172,7 +171,7 @@ export default {
},
},
Badge: {
isDefault: async (parent, _params, _context, _resolveInfo) =>
isDefault: (parent, _params, _context, _resolveInfo) =>
[defaultTrophyBadge.id, defaultVerificationBadge.id].includes(parent.id),
},
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import scrape from './embeds/scraper'
@ -6,7 +5,7 @@ import { undefinedToNullResolver } from './helpers/Resolver'
export default {
Query: {
embed: async (_object, { url }, _context, _resolveInfo) => {
embed: (_object, { url }, _context, _resolveInfo) => {
return scrape(url)
},
},
@ -25,7 +24,7 @@ export default {
'lang',
'html',
]),
sources: async (parent, _params, _context, _resolveInfo) => {
sources: (parent, _params, _context, _resolveInfo) => {
return typeof parent.sources === 'undefined' ? [] : parent.sources
},
},

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
@ -53,7 +52,7 @@ const fetchEmbed = async (url) => {
json = await response.json()
// eslint-disable-next-line no-catch-all/no-catch-all
} catch (err) {
error(`Error fetching embed data: ${err.message}`)
error(`Error fetching embed data: ${String(err.message)}`)
return {}
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -6,7 +5,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable @typescript-eslint/no-use-before-define */
import { v4 as uuid } from 'uuid'
import { CATEGORIES_MIN, CATEGORIES_MAX } from '@constants/categories'
@ -20,6 +18,35 @@ import { createOrUpdateLocations } from './users/location'
import type { Context } from '@src/context'
const removeUserFromGroupWriteTxResultPromise = async (session, groupId, userId) => {
return session.writeTransaction(async (transaction) => {
const removeUserFromGroupCypher = `
MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId})
DELETE membership
WITH user, group
OPTIONAL MATCH (author:User)-[:WROTE]->(p:Post)-[:IN]->(group)
WHERE NOT group.groupType = 'public'
AND NOT author.id = $userId
WITH user, collect(p) AS posts
FOREACH (post IN posts |
MERGE (user)-[:CANNOT_SEE]->(post))
RETURN user {.*}, NULL as membership
`
const transactionResponse = await transaction.run(removeUserFromGroupCypher, {
groupId,
userId,
})
const [result] = transactionResponse.records.map((record) => {
return { user: record.get('user'), membership: record.get('membership') }
})
if (!result) {
throw new UserInputError('User is not a member of this group')
}
return result
})
}
export default {
Query: {
Group: async (_object, params, context: Context, _resolveInfo) => {
@ -488,13 +515,13 @@ export default {
membersCount: '<-[:MEMBER_OF]-(related:User)',
},
}),
name: async (parent, _args, context: Context, _resolveInfo) => {
name: (parent, _args, context: Context, _resolveInfo) => {
if (!context.user) {
return parent.groupType === 'hidden' ? '' : parent.name
}
return parent.name
},
about: async (parent, _args, context: Context, _resolveInfo) => {
about: (parent, _args, context: Context, _resolveInfo) => {
if (!context.user) {
return parent.groupType === 'hidden' ? '' : parent.about
}
@ -502,32 +529,3 @@ export default {
},
},
}
const removeUserFromGroupWriteTxResultPromise = async (session, groupId, userId) => {
return session.writeTransaction(async (transaction) => {
const removeUserFromGroupCypher = `
MATCH (user:User {id: $userId})-[membership:MEMBER_OF]->(group:Group {id: $groupId})
DELETE membership
WITH user, group
OPTIONAL MATCH (author:User)-[:WROTE]->(p:Post)-[:IN]->(group)
WHERE NOT group.groupType = 'public'
AND NOT author.id = $userId
WITH user, collect(p) AS posts
FOREACH (post IN posts |
MERGE (user)-[:CANNOT_SEE]->(post))
RETURN user {.*}, NULL as membership
`
const transactionResponse = await transaction.run(removeUserFromGroupCypher, {
groupId,
userId,
})
const [result] = transactionResponse.records.map((record) => {
return { user: record.get('user'), membership: record.get('membership') }
})
if (!result) {
throw new UserInputError('User is not a member of this group')
}
return result
})
}

View File

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-dynamic-delete */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -11,7 +9,7 @@
export const undefinedToNullResolver = (list) => {
const resolvers = {}
list.forEach((key) => {
resolvers[key] = async (parent) => {
resolvers[key] = (parent) => {
return typeof parent[key] === 'undefined' ? null : parent[key]
}
})
@ -37,7 +35,7 @@ export default function Resolver(type, options: any = {}) {
try {
let response = await session.readTransaction(async (txc) => {
const cypher = `
MATCH(:${type} {${idAttribute}: $id})${connection}
MATCH(:${String(type)} {${String(idAttribute)}: $id})${String(connection)}
RETURN related {.*} as related
`
const result = await txc.run(cypher, { id, cypherParams })
@ -62,7 +60,7 @@ export default function Resolver(type, options: any = {}) {
try {
return await session.readTransaction(async (txc) => {
const nodeCondition = condition.replace('this', 'this {id: $id}')
const cypher = `${nodeCondition} as ${key}`
const cypher = `${String(nodeCondition)} as ${key}`
const result = await txc.run(cypher, { id, cypherParams })
const [response] = result.records.map((r) => r.get(key))
return response
@ -85,7 +83,7 @@ export default function Resolver(type, options: any = {}) {
return await session.readTransaction(async (txc) => {
const id = parent[idAttribute]
const cypher = `
MATCH(u:${type} {${idAttribute}: $id})${connection}
MATCH(u:${String(type)} {${String(idAttribute)}: $id})${String(connection)}
RETURN COUNT(DISTINCT(related)) as count
`
const result = await txc.run(cypher, { id, cypherParams })
@ -141,7 +139,7 @@ export const convertObjectToCypherMapLiteral = (params, addSpaceInfrontIfMapIsNo
let mapLiteral = ''
paramsEntries.forEach((ele, index) => {
mapLiteral += index === 0 ? '{' : ''
mapLiteral += `${ele[0]}: "${ele[1]}"`
mapLiteral += `${ele[0]}: "${String(ele[1])}"`
mapLiteral += index < paramsEntries.length - 1 ? ', ' : '}'
})
mapLiteral = (addSpaceInfrontIfMapIsNotEmpty && mapLiteral.length > 0 ? ' ' : '') + mapLiteral

View File

@ -2,9 +2,31 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-use-before-define */
import { UserInputError } from '@graphql/errors'
const validateEventDate = (dateString) => {
const date = new Date(dateString)
if (date.toString() === 'Invalid Date')
throw new UserInputError('Event start date must be a valid date!')
if (date.toISOString() !== dateString)
throw new UserInputError('Event start date must be in ISO format!')
const now = new Date()
if (date.getTime() < now.getTime()) {
throw new UserInputError('Event start date must be in the future!')
}
}
const validateEventEnd = (start, end) => {
const endDate = new Date(end)
if (endDate.toString() === 'Invalid Date')
throw new UserInputError('Event end date must be a valid date!')
if (endDate.toISOString() !== end)
throw new UserInputError('Event end date must be in ISO format!')
const startDate = new Date(start)
if (endDate < startDate)
throw new UserInputError('Event end date must be a after event start date!')
}
export const validateEventParams = (params) => {
let locationName = null
if (params.postType && params.postType === 'Event') {
@ -34,26 +56,3 @@ export const validateEventParams = (params) => {
delete params.eventInput
return locationName
}
const validateEventDate = (dateString) => {
const date = new Date(dateString)
if (date.toString() === 'Invalid Date')
throw new UserInputError('Event start date must be a valid date!')
if (date.toISOString() !== dateString)
throw new UserInputError('Event start date must be in ISO format!')
const now = new Date()
if (date.getTime() < now.getTime()) {
throw new UserInputError('Event start date must be in the future!')
}
}
const validateEventEnd = (start, end) => {
const endDate = new Date(end)
if (endDate.toString() === 'Invalid Date')
throw new UserInputError('Event end date must be a valid date!')
if (endDate.toISOString() !== end)
throw new UserInputError('Event end date must be in ISO format!')
const startDate = new Date(start)
if (endDate < startDate)
throw new UserInputError('Event end date must be a after event start date!')
}

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import crypto from 'node:crypto'
import { join as joinPath } from 'node:path/posix'
@ -15,6 +13,16 @@ type UrlResolver = (
}: Pick<Context, 'config'>,
) => string
const chain: (...methods: UrlResolver[]) => UrlResolver = (...methods) => {
return (parent, args, context) => {
let { url } = parent
for (const method of methods) {
url = method({ url }, args, context)
}
return url
}
}
const pointUrlToImagor: (opts: { transformations: UrlResolver[] }) => UrlResolver =
({ transformations }) =>
({ url }, _args, context) => {
@ -59,22 +67,12 @@ const resize: UrlResolver = ({ url }, { height, width }) => {
if (!(height || width)) {
return url
}
const window = `/fit-in/${width ?? FALLBACK_MAXIMUM_LENGTH}x${height ?? FALLBACK_MAXIMUM_LENGTH}`
const window = `/fit-in/${String(width ?? FALLBACK_MAXIMUM_LENGTH)}x${String(height ?? FALLBACK_MAXIMUM_LENGTH)}`
const newUrl = new URL(url)
newUrl.pathname = window + newUrl.pathname
return newUrl.href
}
const chain: (...methods: UrlResolver[]) => UrlResolver = (...methods) => {
return (parent, args, context) => {
let { url } = parent
for (const method of methods) {
url = method({ url }, args, context)
}
return url
}
}
export default {
Image: {
...Resolver('Image', {

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/no-shadow */
import path from 'node:path'
@ -41,6 +40,17 @@ export const images = (config: S3Config) => {
return image
}
const uploadImageFile = async (uploadPromise: Promise<FileUpload> | undefined) => {
if (!uploadPromise) return undefined
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const upload = await uploadPromise
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
const { name, ext } = path.parse(upload.filename)
const uniqueFilename = `${uuid()}-${slug(name)}${ext}`
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return await s3.uploadFile({ ...upload, uniqueFilename })
}
const mergeImage: Images['mergeImage'] = async (
resource,
relationshipType,
@ -84,17 +94,6 @@ export const images = (config: S3Config) => {
return mergedImage
}
const uploadImageFile = async (uploadPromise: Promise<FileUpload> | undefined) => {
if (!uploadPromise) return undefined
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const upload = await uploadPromise
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
const { name, ext } = path.parse(upload.filename)
const uniqueFilename = `${uuid()}-${slug(name)}${ext}`
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return await s3.uploadFile({ ...upload, uniqueFilename })
}
const images = {
deleteImage,
mergeImage,

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
@ -16,7 +15,7 @@ import Resolver from './helpers/Resolver'
import type { File } from './attachments/attachments'
const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
const setMessagesAsDistributed = (undistributedMessagesIds, session) => {
return session.writeTransaction(async (transaction) => {
const setDistributedCypher = `
MATCH (m:Message) WHERE m.id IN $undistributedMessagesIds

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -45,8 +43,8 @@ export default {
default:
orderByClause = ''
}
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${args.offset}` : ''
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${args.first}` : ''
const offset = args.offset && typeof args.offset === 'number' ? `SKIP ${String(args.offset)}` : ''
const limit = args.first && typeof args.first === 'number' ? `LIMIT ${String(args.first)}` : ''
const readTxResultPromise = session.readTransaction(async (transaction) => {
const notificationsTransactionResponse = await transaction.run(
@ -145,9 +143,9 @@ export default {
},
},
NOTIFIED: {
id: async (parent) => {
id: (parent) => {
// serialize an ID to help the client update the cache
return `${parent.reason}/${parent.from.id}/${parent.to.id}`
return `${String(parent.reason)}/${String(parent.from.id)}/${String(parent.to.id)}`
},
},
}

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -186,7 +185,7 @@ export default {
SET post.sortDate = toString(datetime())
SET post.clickedCount = 0
SET post.viewedTeaserCount = 0
SET post:${params.postType}
SET post:${String(params.postType)}
WITH post
MATCH (author:User {id: $userId})
MERGE (post)<-[:WROTE]-(author)
@ -260,7 +259,7 @@ export default {
updatePostCypher += `
REMOVE post:Article
REMOVE post:Event
SET post:${params.postType}
SET post:${String(params.postType)}
WITH post
`
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -80,8 +79,8 @@ export default {
const filterClause = filterClauses.join(' ')
const offset =
params.offset && typeof params.offset === 'number' ? `SKIP ${params.offset}` : ''
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : ''
params.offset && typeof params.offset === 'number' ? `SKIP ${String(params.offset)}` : ''
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${String(params.first)}` : ''
const reportsReadTxPromise = session.readTransaction(async (transaction) => {
const reportsTransactionResponse = await transaction.run(

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/require-await */
export default {
Query: {
availableRoles: async (_parent, _args, _context, _resolveInfo) => {
availableRoles: (_parent, _args, _context, _resolveInfo) => {
return ['admin', 'moderator', 'user']
},
},

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
@ -38,7 +37,7 @@ export default {
},
},
Query: {
Room: async (object, params, context, resolveInfo) => {
Room: (object, params, context, resolveInfo) => {
if (!params.filter) params.filter = {}
params.filter.users_some = {
id: context.user.id,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
import { queryString } from './searches/queryString'
@ -10,16 +8,16 @@ import { queryString } from './searches/queryString'
// see http://lucene.apache.org/core/8_3_1/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description
const cypherTemplate = (setup) => `
CALL db.index.fulltext.queryNodes('${setup.fulltextIndex}', $query)
CALL db.index.fulltext.queryNodes('${String(setup.fulltextIndex)}', $query)
YIELD node AS resource, score
${setup.match}
${setup.whereClause}
${setup.withClause}
${String(setup.match)}
${String(setup.whereClause)}
${String(setup.withClause)}
RETURN
${setup.returnClause}
${String(setup.returnClause)}
AS result
SKIP toInteger($skip)
${setup.limit}
${String(setup.limit)}
`
const simpleWhereClause =
@ -148,7 +146,7 @@ const multiSearchMap = [
export default {
Query: {
searchPosts: async (_parent, args, context, _resolveInfo) => {
searchPosts: (_parent, args, context, _resolveInfo) => {
const { query, postsOffset, firstPosts } = args
let userId = null
if (context.user) userId = context.user.id
@ -171,7 +169,7 @@ export default {
}),
}
},
searchUsers: async (_parent, args, context, _resolveInfo) => {
searchUsers: (_parent, args, context, _resolveInfo) => {
const { query, usersOffset, firstUsers } = args
return {
userCount: getSearchResults(
@ -190,7 +188,7 @@ export default {
}),
}
},
searchHashtags: async (_parent, args, context, _resolveInfo) => {
searchHashtags: (_parent, args, context, _resolveInfo) => {
const { query, hashtagsOffset, firstHashtags } = args
return {
hashtagCount: getSearchResults(
@ -209,7 +207,7 @@ export default {
}),
}
},
searchGroups: async (_parent, args, context, _resolveInfo) => {
searchGroups: (_parent, args, context, _resolveInfo) => {
const { query, groupsOffset, firstGroups } = args
let userId = null
if (context.user) userId = context.user.id

View File

@ -2,48 +2,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-use-before-define */
export function queryString(str) {
const normalizedString = normalizeWhitespace(str)
const escapedString = escapeSpecialCharacters(normalizedString)
return `
${matchWholeText(escapedString)}
${matchEachWordExactly(escapedString)}
${matchSomeWordsExactly(escapedString)}
${matchBeginningOfWords(escapedString)}
`
}
const matchWholeText = (str, boost = 8) => {
return `"${str}"^${boost}`
}
const matchEachWordExactly = (str, boost = 4) => {
if (!str.includes(' ')) return ''
const tmp = str
.split(' ')
.map((s, i) => (i === 0 ? `"${s}"` : `AND "${s}"`))
.join(' ')
return `(${tmp})^${boost}`
}
const matchSomeWordsExactly = (str, boost = 2) => {
if (!str.includes(' ')) return ''
return str
.split(' ')
.map((s) => `"${s}"^${boost}`)
.join(' ')
}
const matchBeginningOfWords = (str) => {
return str
.split(' ')
.filter((s) => s.length >= 2)
.map((s) => s + '*')
.join(' ')
}
export function normalizeWhitespace(str) {
// delete the first character if it is !, @ or #
@ -56,3 +15,43 @@ export function normalizeWhitespace(str) {
export function escapeSpecialCharacters(str) {
return str.replace(/(["[\]&|\\{}+!()^~*?:/-])/g, '\\$1')
}
const matchWholeText = (str, boost = 8) => {
return `"${String(str)}"^${String(boost)}`
}
const matchEachWordExactly = (str, boost = 4) => {
if (!str.includes(' ')) return ''
const tmp = str
.split(' ')
.map((s, i) => (i === 0 ? `"${String(s)}"` : `AND "${String(s)}"`))
.join(' ')
return `(${tmp})^${String(boost)}`
}
const matchSomeWordsExactly = (str, boost = 2) => {
if (!str.includes(' ')) return ''
return str
.split(' ')
.map((s) => `"${String(s)}"^${String(boost)}`)
.join(' ')
}
const matchBeginningOfWords = (str) => {
return str
.split(' ')
.filter((s) => s.length >= 2)
.map((s) => s + '*')
.join(' ')
}
export function queryString(str) {
const normalizedString = normalizeWhitespace(str)
const escapedString = escapeSpecialCharacters(normalizedString)
return `
${matchWholeText(escapedString)}
${matchEachWordExactly(escapedString)}
${matchSomeWordsExactly(escapedString)}
${matchBeginningOfWords(escapedString)}
`
}

View File

@ -2,7 +2,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-use-before-define */
const byCreationDate = (a, b) => {
if (a.createdAt < b.createdAt) return -1
if (a.createdAt > b.createdAt) return 1
return 0
}
export default {
Query: {
userData: async (_object, _args, context, _resolveInfo) => {
@ -53,9 +59,3 @@ export default {
},
},
}
const byCreationDate = (a, b) => {
if (a.createdAt < b.createdAt) return -1
if (a.createdAt > b.createdAt) return 1
return 0
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -215,11 +214,11 @@ export default {
await Promise.all(
resource.map(async (node) => {
if (!allowedLabels.includes(node)) {
throw new UserInputError(`Invalid resource type: ${node}`)
throw new UserInputError(`Invalid resource type: ${String(node)}`)
}
const txResult = await transaction.run(
`
MATCH (resource:${node})<-[:WROTE]-(author:User {id: $userId})
MATCH (resource:${String(node)})<-[:WROTE]-(author:User {id: $userId})
OPTIONAL MATCH (resource)<-[:COMMENTS]-(comment:Comment)
SET resource.deleted = true
SET resource.content = 'UNAVAILABLE'
@ -371,7 +370,7 @@ export default {
if (slot >= TROPHY_BADGES_SELECTED_MAX || slot < 0) {
throw new Error(
`Invalid slot! There is only ${TROPHY_BADGES_SELECTED_MAX} badge-slots to fill`,
`Invalid slot! There is only ${String(TROPHY_BADGES_SELECTED_MAX)} badge-slots to fill`,
)
}

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/restrict-plus-operands */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
@ -19,7 +18,7 @@ const REQUEST_TIMEOUT = 3000
const createLocation = async (session, mapboxData) => {
const data = {
id: mapboxData.id + (mapboxData.address ? `-${mapboxData.address}` : ''),
id: mapboxData.id + (mapboxData.address ? `-${String(mapboxData.address)}` : ''),
nameEN: mapboxData.text_en,
nameDE: mapboxData.text_de,
nameFR: mapboxData.text_fr,
@ -77,9 +76,9 @@ export const createOrUpdateLocations = async (
if (locationName !== null) {
const response: any = await fetch(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
locationName,
String(locationName),
)}.json?access_token=${
context.config.MAPBOX_TOKEN
String(context.config.MAPBOX_TOKEN)
}&types=region,place,country,address&language=${locales.join(',')}`,
{
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
@ -115,7 +114,7 @@ export const createOrUpdateLocations = async (
let parent = data
if (parent.address) {
parent.id += `-${parent.address}`
parent.id += `-${String(parent.address)}`
}
if (data.context) {
@ -147,7 +146,7 @@ export const createOrUpdateLocations = async (
await session.writeTransaction((transaction) => {
return transaction.run(
`
MATCH (node:${nodeLabel} {id: $nodeId})
MATCH (node:${String(nodeLabel)} {id: $nodeId})
OPTIONAL MATCH (node)-[relationship:IS_IN]->(:Location)
DELETE relationship
WITH node
@ -162,7 +161,7 @@ export const createOrUpdateLocations = async (
export const queryLocations = async ({ place, lang }, context: Context) => {
const res: any = await fetch(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${context.config.MAPBOX_TOKEN}&types=region,place,country&language=${lang}`,
`https://api.mapbox.com/geocoding/v5/mapbox.places/${String(place)}.json?access_token=${String(context.config.MAPBOX_TOKEN)}&types=region,place,country&language=${String(lang)}`,
{
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
},

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
@ -9,33 +8,33 @@ import { DESCRIPTION_EXCERPT_HTML_LENGTH } from '@constants/groups'
import type { IMiddlewareResolver } from 'graphql-middleware/dist/types'
const createGroup: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const createGroup: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.descriptionExcerpt = trunc(args.description, DESCRIPTION_EXCERPT_HTML_LENGTH).html
return resolve(root, args, context, info)
}
const updateGroup: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const updateGroup: IMiddlewareResolver = (resolve, root, args, context, info) => {
if (args.description)
args.descriptionExcerpt = trunc(args.description, DESCRIPTION_EXCERPT_HTML_LENGTH).html
return resolve(root, args, context, info)
}
const createPost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const createPost: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.contentExcerpt = trunc(args.content, 120).html
return resolve(root, args, context, info)
}
const updatePost: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const updatePost: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.contentExcerpt = trunc(args.content, 120).html
return resolve(root, args, context, info)
}
const createComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const createComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.contentExcerpt = trunc(args.content, 180).html
return resolve(root, args, context, info)
}
const updateComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const updateComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.contentExcerpt = trunc(args.content, 180).html
return resolve(root, args, context, info)
}

View File

@ -4,7 +4,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable security/detect-object-injection */
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import {
@ -43,136 +42,6 @@ const publishNotifications = async (
return emailsSent
}
const handleJoinGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
'emailNotificationsGroupMemberJoined',
)
}
return user
}
const handleLeaveGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
'emailNotificationsGroupMemberLeft',
)
}
return user
}
const handleChangeGroupMemberRole: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
'emailNotificationsGroupMemberRoleChanged',
)
}
return user
}
const handleRemoveUserFromGroup: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
'emailNotificationsGroupMemberRemoved',
)
}
return user
}
const handleContentDataOfPost: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId } = args
const idsOfUsers = extractMentionedUsers(args.content)
const post = await resolve(root, args, context, resolveInfo)
if (post) {
const sentEmails: string[] = await publishNotifications(
context,
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
'emailNotificationsMention',
)
sentEmails.concat(
await publishNotifications(
context,
notifyFollowingUsers(post.id, groupId, context),
'emailNotificationsFollowingUsers',
sentEmails,
),
)
await publishNotifications(
context,
notifyGroupMembersOfNewPost(post.id, groupId, context),
'emailNotificationsPostInGroup',
sentEmails,
)
}
return post
}
const handleContentDataOfComment: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { content } = args
let idsOfMentionedUsers = extractMentionedUsers(content)
const comment = await resolve(root, args, context, resolveInfo)
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
const sentEmails: string[] = await publishNotifications(
context,
notifyUsersOfMention(
'Comment',
comment.id,
idsOfMentionedUsers,
'mentioned_in_comment',
context,
),
'emailNotificationsMention',
)
await publishNotifications(
context,
notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context),
'emailNotificationsCommentOnObservedPost',
sentEmails,
)
return comment
}
const postAuthorOfComment = async (commentId, { context }) => {
const session = context.driver.session()
let postAuthorId
@ -448,6 +317,136 @@ const notifyUsersOfComment = async (label, commentId, reason, context) => {
}
}
const handleJoinGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
'emailNotificationsGroupMemberJoined',
)
}
return user
}
const handleLeaveGroup: IMiddlewareResolver = async (resolve, root, args, context, resolveInfo) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
'emailNotificationsGroupMemberLeft',
)
}
return user
}
const handleChangeGroupMemberRole: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
'emailNotificationsGroupMemberRoleChanged',
)
}
return user
}
const handleRemoveUserFromGroup: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId, userId } = args
const user = await resolve(root, args, context, resolveInfo)
if (user) {
await publishNotifications(
context,
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
'emailNotificationsGroupMemberRemoved',
)
}
return user
}
const handleContentDataOfPost: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { groupId } = args
const idsOfUsers = extractMentionedUsers(args.content)
const post = await resolve(root, args, context, resolveInfo)
if (post) {
const sentEmails: string[] = await publishNotifications(
context,
notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context),
'emailNotificationsMention',
)
sentEmails.concat(
await publishNotifications(
context,
notifyFollowingUsers(post.id, groupId, context),
'emailNotificationsFollowingUsers',
sentEmails,
),
)
await publishNotifications(
context,
notifyGroupMembersOfNewPost(post.id, groupId, context),
'emailNotificationsPostInGroup',
sentEmails,
)
}
return post
}
const handleContentDataOfComment: IMiddlewareResolver = async (
resolve,
root,
args,
context,
resolveInfo,
) => {
const { content } = args
let idsOfMentionedUsers = extractMentionedUsers(content)
const comment = await resolve(root, args, context, resolveInfo)
const [postAuthor] = await postAuthorOfComment(comment.id, { context })
idsOfMentionedUsers = idsOfMentionedUsers.filter((id) => id !== postAuthor.id)
const sentEmails: string[] = await publishNotifications(
context,
notifyUsersOfMention(
'Comment',
comment.id,
idsOfMentionedUsers,
'mentioned_in_comment',
context,
),
'emailNotificationsMention',
)
await publishNotifications(
context,
notifyUsersOfComment('Comment', comment.id, 'commented_on_post', context),
'emailNotificationsCommentOnObservedPost',
sentEmails,
)
return comment
}
const handleCreateMessage: IMiddlewareResolver = async (
resolve,
root,

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unnecessary-type-conversion */
@ -22,27 +21,27 @@ const neode = getNeode()
const isAuthenticated = rule({
cache: 'contextual',
})(async (_parent, _args, ctx, _info) => {
})((_parent, _args, ctx, _info) => {
return !!ctx?.user?.id
})
const isModerator = rule()(async (_parent, _args, { user }: Context, _info) => {
const isModerator = rule()((_parent, _args, { user }: Context, _info) => {
return !!(user && (user.role === 'moderator' || user.role === 'admin'))
})
const isAdmin = rule()(async (_parent, _args, { user }: Context, _info) => {
const isAdmin = rule()((_parent, _args, { user }: Context, _info) => {
return !!(user?.role === 'admin')
})
const onlyYourself = rule({
cache: 'no_cache',
})(async (_parent, args, context: Context, _info) => {
})((_parent, args, context: Context, _info) => {
return context.user?.id === args.id
})
const isMyOwn = rule({
cache: 'no_cache',
})(async (parent, _args, { user }: Context, _info) => {
})((parent, _args, { user }: Context, _info) => {
return !!(user && user.id === parent.id)
})
@ -362,21 +361,21 @@ const isAuthor = rule({
const isDeletingOwnAccount = rule({
cache: 'no_cache',
})(async (_parent, args, context: Context, _info) => {
})((_parent, args, context: Context, _info) => {
return context.user?.id === args.id
})
const noEmailFilter = rule({
cache: 'no_cache',
})(async (_, args) => {
})((_, args) => {
return !('email' in args)
})
const publicRegistration = rule()(
async (_parent, _args, context: Context) => context.config.PUBLIC_REGISTRATION,
(_parent, _args, context: Context) => context.config.PUBLIC_REGISTRATION,
)
const inviteRegistration = rule()(async (_parent, args, context: Context) => {
const inviteRegistration = rule()((_parent, args, context: Context) => {
if (!context.config.INVITE_REGISTRATION) return false
const { inviteCode } = args
return validateInviteCode(context, inviteCode)

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import slugify from 'slugify'
slugify.extend({ Ä: 'AE', ä: 'ae', Ö: 'OE', ö: 'oe', Ü: 'UE', ü: 'ue', ß: 'ss' })
@ -16,7 +15,7 @@ export default async function uniqueSlug(str: string, isUnique: IsUnique) {
let uniqueSlug: string
do {
count += 1
uniqueSlug = `${slug}-${count}`
uniqueSlug = `${slug}-${String(count)}`
} while (!(await isUnique(uniqueSlug)))
return uniqueSlug
}

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
@ -8,7 +7,7 @@ const isModerator = ({ user }) => {
return user && (user.role === 'moderator' || user.role === 'admin')
}
const setDefaultFilters: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const setDefaultFilters: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.deleted = false
if (!isModerator(context)) {
@ -17,7 +16,7 @@ const setDefaultFilters: IMiddlewareResolver = async (resolve, root, args, conte
return resolve(root, args, context, info)
}
const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const obfuscate: IMiddlewareResolver = (resolve, root, args, context, info) => {
if (root.deleted || (!isModerator(context) && root.disabled)) {
root.content = 'UNAVAILABLE'
root.contentExcerpt = 'UNAVAILABLE'
@ -31,7 +30,7 @@ const obfuscate: IMiddlewareResolver = async (resolve, root, args, context, info
return resolve(root, args, context, info)
}
const mutationDefaults: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const mutationDefaults: IMiddlewareResolver = (resolve, root, args, context, info) => {
args.disabled = false
// TODO: remove as soon as our factories don't need this anymore
if (typeof args.deleted !== 'boolean') {

View File

@ -2,16 +2,15 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import type { IMiddlewareResolver } from 'graphql-middleware/dist/types'
const createRelatedCypher = (relation) => `
MATCH (user:User { id: $currentUser})
MATCH (post:Post { id: $postId})
OPTIONAL MATCH (post)<-[r:${relation}]-(u:User)
OPTIONAL MATCH (post)<-[r:${String(relation)}]-(u:User)
WHERE NOT u.disabled AND NOT u.deleted
WITH user, post, count(DISTINCT u) AS count
MERGE (user)-[relation:${relation} { }]->(post)
MERGE (user)-[relation:${String(relation)} { }]->(post)
ON CREATE
SET relation.count = 1,
relation.createdAt = toString(datetime()),

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
@ -16,7 +14,7 @@ const validateCreateComment: IMiddlewareResolver = async (resolve, root, args, c
const { postId } = args
if (!args.content || content.length < COMMENT_MIN_LENGTH) {
throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`)
throw new UserInputError(`Comment must be at least ${String(COMMENT_MIN_LENGTH)} character long!`)
}
const session = context.driver.session()
try {
@ -43,16 +41,16 @@ const validateCreateComment: IMiddlewareResolver = async (resolve, root, args, c
}
}
const validateUpdateComment: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const validateUpdateComment: IMiddlewareResolver = (resolve, root, args, context, info) => {
const content = args.content.replace(/<(?:.|\n)*?>/gm, '').trim()
if (!args.content || content.length < COMMENT_MIN_LENGTH) {
throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`)
throw new UserInputError(`Comment must be at least ${String(COMMENT_MIN_LENGTH)} character long!`)
}
return resolve(root, args, context, info)
}
const validateReport: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const validateReport: IMiddlewareResolver = (resolve, root, args, context, info) => {
const { resourceId } = args
const { user } = context
if (resourceId === user.id) throw new Error('You cannot report yourself!')
@ -92,14 +90,14 @@ const validateReview: IMiddlewareResolver = async (resolve, root, args, context,
existingReportedResource = existingReportedResource[0]
if (!existingReportedResource.filed)
throw new Error(
`Before starting the review process, please report the ${existingReportedResource.label}!`,
`Before starting the review process, please report the ${String(existingReportedResource.label)}!`,
)
const authorId =
existingReportedResource.label !== 'User' && existingReportedResource.author
? existingReportedResource.author.properties.id
: null
if (authorId && authorId === user.id)
throw new Error(`You cannot review your own ${existingReportedResource.label}!`)
throw new Error(`You cannot review your own ${String(existingReportedResource.label)}!`)
} finally {
await session.close()
}
@ -107,7 +105,7 @@ const validateReview: IMiddlewareResolver = async (resolve, root, args, context,
return resolve(root, args, context, info)
}
export const validateNotifyUsers = async (label: string, reason: string): Promise<void> => {
export const validateNotifyUsers = (label: string, reason: string): void => {
const reasonsAllowed = [
'mentioned_in_post',
'mentioned_in_comment',
@ -124,10 +122,10 @@ export const validateNotifyUsers = async (label: string, reason: string): Promis
}
}
const validateUpdateUser: IMiddlewareResolver = async (resolve, root, params, context, info) => {
const validateUpdateUser: IMiddlewareResolver = (resolve, root, params, context, info) => {
const { name } = params
if (typeof name === 'string' && name.trim().length < USERNAME_MIN_LENGTH)
throw new UserInputError(`Username must be at least ${USERNAME_MIN_LENGTH} character long!`)
throw new UserInputError(`Username must be at least ${String(USERNAME_MIN_LENGTH)} character long!`)
return resolve(root, params, context, info)
}

View File

@ -1,7 +1,6 @@
/* eslint-disable security/detect-object-injection */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable promise/prefer-await-to-callbacks */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
@ -47,7 +46,7 @@ const fields = [
{ field: 'descriptionExcerpt' },
]
const mutationXss: IMiddlewareResolver = async (resolve, root, args, context, info) => {
const mutationXss: IMiddlewareResolver = (resolve, root, args, context, info) => {
args = walkRecursive(args, fields, info.fieldName, cleanHtml)
return resolve(root, args, context, info)
}

View File

@ -102,8 +102,7 @@ const createServer = async (options?: CreateServerOptions) => {
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
// eslint-disable-next-line @typescript-eslint/require-await
async serverWillStart() {
serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose()