upgrade to prisma 4
This commit is contained in:
parent
5fb5b5c5e5
commit
7542dd6cc4
@ -12,8 +12,36 @@ import search from './search'
|
|||||||
import rewards from './rewards'
|
import rewards from './rewards'
|
||||||
import referrals from './referrals'
|
import referrals from './referrals'
|
||||||
import price from './price'
|
import price from './price'
|
||||||
import { GraphQLJSONObject } from 'graphql-type-json'
|
import { GraphQLJSONObject as JSONObject } from 'graphql-type-json'
|
||||||
import admin from './admin'
|
import admin from './admin'
|
||||||
|
import { GraphQLScalarType, Kind } from 'graphql'
|
||||||
|
|
||||||
|
const date = new GraphQLScalarType({
|
||||||
|
name: 'Date',
|
||||||
|
description: 'Date custom scalar type',
|
||||||
|
serialize (value) {
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return value.toISOString() // Convert outgoing Date to string for JSON
|
||||||
|
} else if (typeof value === 'string') {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
throw Error('GraphQL Date Scalar serializer expected a `Date` object got `' + typeof value + '` ' + value)
|
||||||
|
},
|
||||||
|
parseValue (value) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return new Date(value) // Convert incoming string to Date
|
||||||
|
}
|
||||||
|
throw new Error('GraphQL Date Scalar parser expected a `string`')
|
||||||
|
},
|
||||||
|
parseLiteral (ast) {
|
||||||
|
if (ast.kind === Kind.STRING) {
|
||||||
|
// Convert hard-coded AST string to integer and then to Date
|
||||||
|
return new Date(ast.value)
|
||||||
|
}
|
||||||
|
// Invalid hard-coded value (not an integer)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export default [user, item, message, wallet, lnurl, notifications, invite, sub,
|
export default [user, item, message, wallet, lnurl, notifications, invite, sub,
|
||||||
upload, search, growth, rewards, referrals, price, admin, { JSONObject: GraphQLJSONObject }]
|
upload, search, growth, rewards, referrals, price, admin, { JSONObject }, { Date: date }]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { GraphQLError } from 'graphql'
|
import { GraphQLError } from 'graphql'
|
||||||
import { inviteSchema, ssValidate } from '../../lib/validate'
|
import { inviteSchema, ssValidate } from '../../lib/validate'
|
||||||
|
import { msatsToSats } from '../../lib/format'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
@ -59,7 +60,7 @@ export default {
|
|||||||
},
|
},
|
||||||
poor: async (invite, args, { me, models }) => {
|
poor: async (invite, args, { me, models }) => {
|
||||||
const user = await models.user.findUnique({ where: { id: invite.userId } })
|
const user = await models.user.findUnique({ where: { id: invite.userId } })
|
||||||
return user.msats < invite.gift * 1000
|
return msatsToSats(user.msats) < invite.gift
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,12 @@ async function comments (me, models, id, sort) {
|
|||||||
const filter = await commentFilterClause(me, models)
|
const filter = await commentFilterClause(me, models)
|
||||||
if (me) {
|
if (me) {
|
||||||
const [{ item_comments_with_me: comments }] = await models.$queryRawUnsafe(
|
const [{ item_comments_with_me: comments }] = await models.$queryRawUnsafe(
|
||||||
'SELECT item_comments_with_me($1, $2, $3, $4, $5)', Number(id), Number(me.id), COMMENT_DEPTH_LIMIT, filter, orderBy)
|
'SELECT item_comments_with_me($1::INTEGER, $2::INTEGER, $3::INTEGER, $4, $5)', Number(id), Number(me.id), COMMENT_DEPTH_LIMIT, filter, orderBy)
|
||||||
return comments
|
return comments
|
||||||
}
|
}
|
||||||
|
|
||||||
const [{ item_comments: comments }] = await models.$queryRawUnsafe(
|
const [{ item_comments: comments }] = await models.$queryRawUnsafe(
|
||||||
'SELECT item_comments($1, $2, $3, $4)', Number(id), COMMENT_DEPTH_LIMIT, filter, orderBy)
|
'SELECT item_comments($1::INTEGER, $2::INTEGER, $3, $4)', Number(id), COMMENT_DEPTH_LIMIT, filter, orderBy)
|
||||||
return comments
|
return comments
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ export default {
|
|||||||
itemRepetition: async (parent, { parentId }, { me, models }) => {
|
itemRepetition: async (parent, { parentId }, { me, models }) => {
|
||||||
if (!me) return 0
|
if (!me) return 0
|
||||||
// how many of the parents starting at parentId belong to me
|
// how many of the parents starting at parentId belong to me
|
||||||
const [{ item_spam: count }] = await models.$queryRawUnsafe(`SELECT item_spam($1, $2, '${ITEM_SPAM_INTERVAL}')`,
|
const [{ item_spam: count }] = await models.$queryRawUnsafe(`SELECT item_spam($1::INTEGER, $2::INTEGER, '${ITEM_SPAM_INTERVAL}')`,
|
||||||
Number(parentId), Number(me.id))
|
Number(parentId), Number(me.id))
|
||||||
|
|
||||||
return count
|
return count
|
||||||
@ -621,7 +621,7 @@ export default {
|
|||||||
throw new GraphQLError('item does not belong to you', { extensions: { code: 'FORBIDDEN' } })
|
throw new GraphQLError('item does not belong to you', { extensions: { code: 'FORBIDDEN' } })
|
||||||
}
|
}
|
||||||
const [item] = await serialize(models,
|
const [item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(`${SELECT} FROM update_poll($1, $2, $3, $4, $5, $6, $7) AS "Item"`,
|
models.$queryRawUnsafe(`${SELECT} FROM update_poll($1, $2::INTEGER, $3, $4, $5::INTEGER, $6, $7::INTEGER) AS "Item"`,
|
||||||
sub || 'bitcoin', Number(id), title, text, Number(boost || 0), options, Number(fwdUser?.id)))
|
sub || 'bitcoin', Number(id), title, text, Number(boost || 0), options, Number(fwdUser?.id)))
|
||||||
|
|
||||||
await createMentions(item, models)
|
await createMentions(item, models)
|
||||||
@ -629,7 +629,7 @@ export default {
|
|||||||
return item
|
return item
|
||||||
} else {
|
} else {
|
||||||
const [item] = await serialize(models,
|
const [item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(`${SELECT} FROM create_poll($1, $2, $3, $4, $5, $6, $7, $8, '${ITEM_SPAM_INTERVAL}') AS "Item"`,
|
models.$queryRawUnsafe(`${SELECT} FROM create_poll($1, $2, $3, $4::INTEGER, $5::INTEGER, $6::INTEGER, $7, $8::INTEGER, '${ITEM_SPAM_INTERVAL}') AS "Item"`,
|
||||||
sub || 'bitcoin', title, text, 1, Number(boost || 0), Number(me.id), options, Number(fwdUser?.id)))
|
sub || 'bitcoin', title, text, 1, Number(boost || 0), Number(me.id), options, Number(fwdUser?.id)))
|
||||||
|
|
||||||
await createMentions(item, models)
|
await createMentions(item, models)
|
||||||
@ -659,12 +659,12 @@ export default {
|
|||||||
}
|
}
|
||||||
([item] = await serialize(models,
|
([item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(
|
models.$queryRawUnsafe(
|
||||||
`${SELECT} FROM update_job($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) AS "Item"`,
|
`${SELECT} FROM update_job($1::INTEGER, $2, $3, $4, $5::INTEGER, $6, $7, $8, $9::INTEGER, $10::"Status") AS "Item"`,
|
||||||
Number(id), title, url, text, Number(maxBid), company, loc, remote, Number(logo), status)))
|
Number(id), title, url, text, Number(maxBid), company, loc, remote, Number(logo), status)))
|
||||||
} else {
|
} else {
|
||||||
([item] = await serialize(models,
|
([item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(
|
models.$queryRawUnsafe(
|
||||||
`${SELECT} FROM create_job($1, $2, $3, $4, $5, $6, $7, $8, $9) AS "Item"`,
|
`${SELECT} FROM create_job($1, $2, $3, $4::INTEGER, $5::INTEGER, $6, $7, $8, $9::INTEGER) AS "Item"`,
|
||||||
title, url, text, Number(me.id), Number(maxBid), company, loc, remote, Number(logo))))
|
title, url, text, Number(me.id), Number(maxBid), company, loc, remote, Number(logo))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,7 +702,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$queryRawUnsafe(`${SELECT} FROM poll_vote($1, $2) AS "Item"`,
|
models.$queryRawUnsafe(`${SELECT} FROM poll_vote($1::INTEGER, $2::INTEGER) AS "Item"`,
|
||||||
Number(id), Number(me.id)))
|
Number(id), Number(me.id)))
|
||||||
|
|
||||||
return id
|
return id
|
||||||
@ -724,7 +724,7 @@ export default {
|
|||||||
throw new GraphQLError('cannot zap your self', { extensions: { code: 'BAD_INPUT' } })
|
throw new GraphQLError('cannot zap your self', { extensions: { code: 'BAD_INPUT' } })
|
||||||
}
|
}
|
||||||
|
|
||||||
const [{ item_act: vote }] = await serialize(models, models.$queryRaw`SELECT item_act(${Number(id)}, ${me.id}, 'TIP', ${Number(sats)})`)
|
const [{ item_act: vote }] = await serialize(models, models.$queryRaw`SELECT item_act(${Number(id)}::INTEGER, ${me.id}::INTEGER, 'TIP', ${Number(sats)}::INTEGER)`)
|
||||||
|
|
||||||
const updatedItem = await models.item.findUnique({ where: { id: Number(id) } })
|
const updatedItem = await models.item.findUnique({ where: { id: Number(id) } })
|
||||||
const title = `your ${updatedItem.title ? 'post' : 'reply'} ${updatedItem.fwdUser ? 'forwarded' : 'stacked'} ${Math.floor(Number(updatedItem.msats) / 1000)} sats${updatedItem.fwdUser ? ` to @${updatedItem.fwdUser.name}` : ''}`
|
const title = `your ${updatedItem.title ? 'post' : 'reply'} ${updatedItem.fwdUser ? 'forwarded' : 'stacked'} ${Math.floor(Number(updatedItem.msats) / 1000)} sats${updatedItem.fwdUser ? ` to @${updatedItem.fwdUser.name}` : ''}`
|
||||||
@ -755,7 +755,7 @@ export default {
|
|||||||
throw new GraphQLError('cannot downvote your self', { extensions: { code: 'BAD_INPUT' } })
|
throw new GraphQLError('cannot downvote your self', { extensions: { code: 'BAD_INPUT' } })
|
||||||
}
|
}
|
||||||
|
|
||||||
await serialize(models, models.$queryRaw`SELECT item_act(${Number(id)}, ${me.id}, 'DONT_LIKE_THIS', ${DONT_LIKE_THIS_COST})`)
|
await serialize(models, models.$queryRaw`SELECT item_act(${Number(id)}::INTEGER, ${me.id}::INTEGER, 'DONT_LIKE_THIS', ${DONT_LIKE_THIS_COST}::INTEGER)`)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -818,7 +818,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options = await models.$queryRaw`
|
const options = await models.$queryRaw`
|
||||||
SELECT "PollOption".id, option, count("PollVote"."userId") as count,
|
SELECT "PollOption".id, option, count("PollVote"."userId")::INTEGER as count,
|
||||||
coalesce(bool_or("PollVote"."userId" = ${me?.id}), 'f') as "meVoted"
|
coalesce(bool_or("PollVote"."userId" = ${me?.id}), 'f') as "meVoted"
|
||||||
FROM "PollOption"
|
FROM "PollOption"
|
||||||
LEFT JOIN "PollVote" on "PollVote"."pollOptionId" = "PollOption".id
|
LEFT JOIN "PollVote" on "PollVote"."pollOptionId" = "PollOption".id
|
||||||
@ -826,6 +826,7 @@ export default {
|
|||||||
GROUP BY "PollOption".id
|
GROUP BY "PollOption".id
|
||||||
ORDER BY "PollOption".id ASC
|
ORDER BY "PollOption".id ASC
|
||||||
`
|
`
|
||||||
|
|
||||||
const poll = {}
|
const poll = {}
|
||||||
poll.options = options
|
poll.options = options
|
||||||
poll.meVoted = options.some(o => o.meVoted)
|
poll.meVoted = options.some(o => o.meVoted)
|
||||||
@ -856,7 +857,9 @@ export default {
|
|||||||
},
|
},
|
||||||
meSats: async (item, args, { me, models }) => {
|
meSats: async (item, args, { me, models }) => {
|
||||||
if (!me) return 0
|
if (!me) return 0
|
||||||
if (typeof item.meMsats === 'number') return msatsToSats(item.meMsats)
|
if (typeof item.meMsats !== 'undefined') {
|
||||||
|
return msatsToSats(item.meMsats)
|
||||||
|
}
|
||||||
|
|
||||||
const { _sum: { msats } } = await models.itemAct.aggregate({
|
const { _sum: { msats } } = await models.itemAct.aggregate({
|
||||||
_sum: {
|
_sum: {
|
||||||
@ -1035,7 +1038,7 @@ export const updateItem = async (parent, { id, data: { sub, title, url, text, bo
|
|||||||
|
|
||||||
const [item] = await serialize(models,
|
const [item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(
|
models.$queryRawUnsafe(
|
||||||
`${SELECT} FROM update_item($1, $2, $3, $4, $5, $6, $7, $8) AS "Item"`,
|
`${SELECT} FROM update_item($1, $2::INTEGER, $3, $4, $5, $6::INTEGER, $7::INTEGER, $8::INTEGER) AS "Item"`,
|
||||||
old.parentId ? null : sub || 'bitcoin', Number(id), title, url, text,
|
old.parentId ? null : sub || 'bitcoin', Number(id), title, url, text,
|
||||||
Number(boost || 0), bounty ? Number(bounty) : null, Number(fwdUser?.id)))
|
Number(boost || 0), bounty ? Number(bounty) : null, Number(fwdUser?.id)))
|
||||||
|
|
||||||
@ -1071,7 +1074,7 @@ const createItem = async (parent, { sub, title, url, text, boost, forward, bount
|
|||||||
const [item] = await serialize(
|
const [item] = await serialize(
|
||||||
models,
|
models,
|
||||||
models.$queryRawUnsafe(
|
models.$queryRawUnsafe(
|
||||||
`${SELECT} FROM create_item($1, $2, $3, $4, $5, $6, $7, $8, $9, '${ITEM_SPAM_INTERVAL}') AS "Item"`,
|
`${SELECT} FROM create_item($1, $2, $3, $4, $5::INTEGER, $6::INTEGER, $7::INTEGER, $8::INTEGER, $9::INTEGER, '${ITEM_SPAM_INTERVAL}') AS "Item"`,
|
||||||
parentId ? null : sub || 'bitcoin',
|
parentId ? null : sub || 'bitcoin',
|
||||||
title,
|
title,
|
||||||
url,
|
url,
|
||||||
|
@ -16,7 +16,7 @@ export default {
|
|||||||
`, Number(me.id))
|
`, Number(me.id))
|
||||||
|
|
||||||
const [{ totalReferrals }] = await models.$queryRawUnsafe(`
|
const [{ totalReferrals }] = await models.$queryRawUnsafe(`
|
||||||
SELECT count(*) as "totalReferrals"
|
SELECT count(*)::INTEGER as "totalReferrals"
|
||||||
FROM users
|
FROM users
|
||||||
WHERE ${intervalClause(when, 'users', true)}
|
WHERE ${intervalClause(when, 'users', true)}
|
||||||
"referrerId" = $1
|
"referrerId" = $1
|
||||||
|
@ -43,7 +43,7 @@ export default {
|
|||||||
|
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$queryRawUnsafe(
|
models.$queryRawUnsafe(
|
||||||
'SELECT donate($1, $2)',
|
'SELECT donate($1::INTEGER, $2::INTEGER)',
|
||||||
sats, Number(me.id)))
|
sats, Number(me.id)))
|
||||||
|
|
||||||
return sats
|
return sats
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
const { GraphQLError } = require('graphql')
|
const { GraphQLError } = require('graphql')
|
||||||
const retry = require('async-retry')
|
const retry = require('async-retry')
|
||||||
|
const Prisma = require('@prisma/client')
|
||||||
|
|
||||||
async function serialize (models, call) {
|
async function serialize (models, call) {
|
||||||
return await retry(async bail => {
|
return await retry(async bail => {
|
||||||
try {
|
try {
|
||||||
const [, result] = await models.$transaction([
|
const [, result] = await models.$transaction(
|
||||||
models.$executeRawUnsafe(SERIALIZE),
|
[models.$executeRaw`SELECT ASSERT_SERIALIZED()`, call],
|
||||||
call
|
{ isolationLevel: Prisma.TransactionIsolationLevel.Serializable })
|
||||||
])
|
|
||||||
return result
|
return result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
@ -56,6 +56,4 @@ async function serialize (models, call) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const SERIALIZE = 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'
|
|
||||||
|
|
||||||
module.exports = serialize
|
module.exports = serialize
|
||||||
|
@ -193,7 +193,7 @@ export default {
|
|||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
||||||
} else if (by === 'posts') {
|
} else if (by === 'posts') {
|
||||||
users = await models.$queryRawUnsafe(`
|
users = await models.$queryRawUnsafe(`
|
||||||
SELECT users.*, count(*) as nposts
|
SELECT users.*, count(*)::INTEGER as nposts
|
||||||
FROM users
|
FROM users
|
||||||
JOIN "Item" on "Item"."userId" = users.id
|
JOIN "Item" on "Item"."userId" = users.id
|
||||||
WHERE "Item".created_at <= $1 AND "Item"."parentId" IS NULL
|
WHERE "Item".created_at <= $1 AND "Item"."parentId" IS NULL
|
||||||
@ -205,7 +205,7 @@ export default {
|
|||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
||||||
} else if (by === 'comments') {
|
} else if (by === 'comments') {
|
||||||
users = await models.$queryRawUnsafe(`
|
users = await models.$queryRawUnsafe(`
|
||||||
SELECT users.*, count(*) as ncomments
|
SELECT users.*, count(*)::INTEGER as ncomments
|
||||||
FROM users
|
FROM users
|
||||||
JOIN "Item" on "Item"."userId" = users.id
|
JOIN "Item" on "Item"."userId" = users.id
|
||||||
WHERE "Item".created_at <= $1 AND "Item"."parentId" IS NOT NULL
|
WHERE "Item".created_at <= $1 AND "Item"."parentId" IS NOT NULL
|
||||||
@ -217,7 +217,7 @@ export default {
|
|||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
||||||
} else if (by === 'referrals') {
|
} else if (by === 'referrals') {
|
||||||
users = await models.$queryRawUnsafe(`
|
users = await models.$queryRawUnsafe(`
|
||||||
SELECT users.*, count(*) as referrals
|
SELECT users.*, count(*)::INTEGER as referrals
|
||||||
FROM users
|
FROM users
|
||||||
JOIN "users" referree on users.id = referree."referrerId"
|
JOIN "users" referree on users.id = referree."referrerId"
|
||||||
WHERE referree.created_at <= $1
|
WHERE referree.created_at <= $1
|
||||||
@ -503,7 +503,7 @@ export default {
|
|||||||
await updateItem(parent, { id: user.bioId, data: { text: bio, title: `@${user.name}'s bio` } }, { me, models })
|
await updateItem(parent, { id: user.bioId, data: { text: bio, title: `@${user.name}'s bio` } }, { me, models })
|
||||||
} else {
|
} else {
|
||||||
const [item] = await serialize(models,
|
const [item] = await serialize(models,
|
||||||
models.$queryRawUnsafe(`${SELECT} FROM create_bio($1, $2, $3) AS "Item"`,
|
models.$queryRawUnsafe(`${SELECT} FROM create_bio($1, $2, $3::INTEGER) AS "Item"`,
|
||||||
`@${user.name}'s bio`, bio, Number(me.id)))
|
`@${user.name}'s bio`, bio, Number(me.id)))
|
||||||
await createMentions(item, models)
|
await createMentions(item, models)
|
||||||
}
|
}
|
||||||
@ -579,7 +579,7 @@ export default {
|
|||||||
return max
|
return max
|
||||||
},
|
},
|
||||||
nitems: async (user, { when }, { models }) => {
|
nitems: async (user, { when }, { models }) => {
|
||||||
if (typeof user.nitems === 'number') {
|
if (typeof user.nitems !== 'undefined') {
|
||||||
return user.nitems
|
return user.nitems
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +593,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
nposts: async (user, { when }, { models }) => {
|
nposts: async (user, { when }, { models }) => {
|
||||||
if (typeof user.nposts === 'number') {
|
if (typeof user.nposts !== 'undefined') {
|
||||||
return user.nposts
|
return user.nposts
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +608,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
ncomments: async (user, { when }, { models }) => {
|
ncomments: async (user, { when }, { models }) => {
|
||||||
if (typeof user.ncomments === 'number') {
|
if (typeof user.ncomments !== 'undefined') {
|
||||||
return user.ncomments
|
return user.ncomments
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +623,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
nbookmarks: async (user, { when }, { models }) => {
|
nbookmarks: async (user, { when }, { models }) => {
|
||||||
if (typeof user.nBookmarks === 'number') {
|
if (typeof user.nBookmarks !== 'undefined') {
|
||||||
return user.nBookmarks
|
return user.nBookmarks
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +637,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
stacked: async (user, { when }, { models }) => {
|
stacked: async (user, { when }, { models }) => {
|
||||||
if (typeof user.stacked === 'number') {
|
if (typeof user.stacked !== 'undefined') {
|
||||||
return user.stacked
|
return user.stacked
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,7 +669,7 @@ export default {
|
|||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
spent: async (user, { when }, { models }) => {
|
spent: async (user, { when }, { models }) => {
|
||||||
if (typeof user.spent === 'number') {
|
if (typeof user.spent !== 'undefined') {
|
||||||
return user.spent
|
return user.spent
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,9 +688,10 @@ export default {
|
|||||||
return (msats && msatsToSats(msats)) || 0
|
return (msats && msatsToSats(msats)) || 0
|
||||||
},
|
},
|
||||||
referrals: async (user, { when }, { models }) => {
|
referrals: async (user, { when }, { models }) => {
|
||||||
if (typeof user.referrals === 'number') {
|
if (typeof user.referrals !== 'undefined') {
|
||||||
return user.referrals
|
return user.referrals
|
||||||
}
|
}
|
||||||
|
|
||||||
return await models.user.count({
|
return await models.user.count({
|
||||||
where: {
|
where: {
|
||||||
referrerId: user.id,
|
referrerId: user.id,
|
||||||
|
@ -211,7 +211,7 @@ export default {
|
|||||||
|
|
||||||
const [inv] = await serialize(models,
|
const [inv] = await serialize(models,
|
||||||
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${invoice.request},
|
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${invoice.request},
|
||||||
${expiresAt}, ${amount * 1000}, ${me.id}, ${description})`)
|
${expiresAt}, ${amount * 1000}, ${me.id}::INTEGER, ${description})`)
|
||||||
|
|
||||||
return inv
|
return inv
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -16,7 +16,7 @@ export default gql`
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TimeData {
|
type TimeData {
|
||||||
time: String!
|
time: Date!
|
||||||
data: [NameValue!]!
|
data: [NameValue!]!
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -15,7 +15,7 @@ import referrals from './referrals'
|
|||||||
import price from './price'
|
import price from './price'
|
||||||
import admin from './admin'
|
import admin from './admin'
|
||||||
|
|
||||||
const link = gql`
|
const common = gql`
|
||||||
type Query {
|
type Query {
|
||||||
_: Boolean
|
_: Boolean
|
||||||
}
|
}
|
||||||
@ -27,7 +27,10 @@ const link = gql`
|
|||||||
type Subscription {
|
type Subscription {
|
||||||
_: Boolean
|
_: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scalar JSONObject
|
||||||
|
scalar Date
|
||||||
`
|
`
|
||||||
|
|
||||||
export default [link, user, item, message, wallet, lnurl, notifications, invite,
|
export default [common, user, item, message, wallet, lnurl, notifications, invite,
|
||||||
sub, upload, growth, rewards, referrals, price, admin]
|
sub, upload, growth, rewards, referrals, price, admin]
|
||||||
|
@ -13,7 +13,7 @@ export default gql`
|
|||||||
|
|
||||||
type Invite {
|
type Invite {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
invitees: [User!]!
|
invitees: [User!]!
|
||||||
gift: Int!
|
gift: Int!
|
||||||
limit: Int
|
limit: Int
|
||||||
|
@ -65,9 +65,9 @@ export default gql`
|
|||||||
|
|
||||||
type Item {
|
type Item {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
updatedAt: String!
|
updatedAt: Date!
|
||||||
deletedAt: String
|
deletedAt: Date
|
||||||
title: String
|
title: String
|
||||||
searchTitle: String
|
searchTitle: String
|
||||||
url: String
|
url: String
|
||||||
@ -87,7 +87,7 @@ export default gql`
|
|||||||
bountyPaidTo: [Int]
|
bountyPaidTo: [Int]
|
||||||
sats: Int!
|
sats: Int!
|
||||||
commentSats: Int!
|
commentSats: Int!
|
||||||
lastCommentAt: String
|
lastCommentAt: Date
|
||||||
upvotes: Int!
|
upvotes: Int!
|
||||||
wvotes: Float!
|
wvotes: Float!
|
||||||
meSats: Int!
|
meSats: Int!
|
||||||
|
@ -13,7 +13,7 @@ export default gql`
|
|||||||
|
|
||||||
type LnAuth {
|
type LnAuth {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
k1: String!
|
k1: String!
|
||||||
pubkey: String
|
pubkey: String
|
||||||
encodedUrl: String!
|
encodedUrl: String!
|
||||||
@ -22,7 +22,7 @@ export default gql`
|
|||||||
|
|
||||||
type LnWith {
|
type LnWith {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
k1: String!
|
k1: String!
|
||||||
user: User!
|
user: User!
|
||||||
withdrawalId: Int
|
withdrawalId: Int
|
||||||
|
@ -14,32 +14,32 @@ export default gql`
|
|||||||
id: ID!
|
id: ID!
|
||||||
earnedSats: Int!
|
earnedSats: Int!
|
||||||
item: Item!
|
item: Item!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reply {
|
type Reply {
|
||||||
id: ID!
|
id: ID!
|
||||||
item: Item!
|
item: Item!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mention {
|
type Mention {
|
||||||
id: ID!
|
id: ID!
|
||||||
mention: Boolean!
|
mention: Boolean!
|
||||||
item: Item!
|
item: Item!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Invitification {
|
type Invitification {
|
||||||
id: ID!
|
id: ID!
|
||||||
invite: Invite!
|
invite: Invite!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type JobChanged {
|
type JobChanged {
|
||||||
id: ID!
|
id: ID!
|
||||||
item: Item!
|
item: Item!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type EarnSources {
|
type EarnSources {
|
||||||
@ -52,14 +52,14 @@ export default gql`
|
|||||||
|
|
||||||
type Streak {
|
type Streak {
|
||||||
id: ID!
|
id: ID!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
days: Int
|
days: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Earn {
|
type Earn {
|
||||||
id: ID!
|
id: ID!
|
||||||
earnedSats: Int!
|
earnedSats: Int!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
sources: EarnSources
|
sources: EarnSources
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,12 +67,12 @@ export default gql`
|
|||||||
id: ID!
|
id: ID!
|
||||||
earnedSats: Int!
|
earnedSats: Int!
|
||||||
invoice: Invoice!
|
invoice: Invoice!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Referral {
|
type Referral {
|
||||||
id: ID!
|
id: ID!
|
||||||
sortTime: String!
|
sortTime: Date!
|
||||||
}
|
}
|
||||||
|
|
||||||
union Notification = Reply | Votification | Mention
|
union Notification = Reply | Votification | Mention
|
||||||
@ -80,7 +80,7 @@ export default gql`
|
|||||||
| Streak
|
| Streak
|
||||||
|
|
||||||
type Notifications {
|
type Notifications {
|
||||||
lastChecked: String
|
lastChecked: Date
|
||||||
cursor: String
|
cursor: String
|
||||||
notifications: [Notification!]!
|
notifications: [Notification!]!
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ export default gql`
|
|||||||
|
|
||||||
type Sub {
|
type Sub {
|
||||||
name: String!
|
name: String!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
updatedAt: String!
|
updatedAt: Date!
|
||||||
postTypes: [String!]!
|
postTypes: [String!]!
|
||||||
rankingType: String!
|
rankingType: String!
|
||||||
baseCost: Int!
|
baseCost: Int!
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { gql } from 'graphql-tag'
|
import { gql } from 'graphql-tag'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
scalar JSONObject
|
|
||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
getSignedPOST(type: String!, size: Int!, width: Int!, height: Int!): SignedPost!
|
getSignedPOST(type: String!, size: Int!, width: Int!, height: Int!): SignedPost!
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ export default gql`
|
|||||||
|
|
||||||
type User {
|
type User {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
name: String
|
name: String
|
||||||
nitems(when: String): Int!
|
nitems(when: String): Int!
|
||||||
nposts(when: String): Int!
|
nposts(when: String): Int!
|
||||||
|
@ -16,17 +16,17 @@ export default gql`
|
|||||||
|
|
||||||
type Invoice {
|
type Invoice {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
bolt11: String!
|
bolt11: String!
|
||||||
expiresAt: String!
|
expiresAt: Date!
|
||||||
cancelled: Boolean!
|
cancelled: Boolean!
|
||||||
confirmedAt: String
|
confirmedAt: Date
|
||||||
satsReceived: Int
|
satsReceived: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Withdrawl {
|
type Withdrawl {
|
||||||
id: ID!
|
id: ID!
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
hash: String!
|
hash: String!
|
||||||
bolt11: String!
|
bolt11: String!
|
||||||
satsPaying: Int!
|
satsPaying: Int!
|
||||||
@ -40,7 +40,7 @@ export default gql`
|
|||||||
id: ID!
|
id: ID!
|
||||||
factId: ID!
|
factId: ID!
|
||||||
bolt11: String
|
bolt11: String
|
||||||
createdAt: String!
|
createdAt: Date!
|
||||||
sats: Float!
|
sats: Float!
|
||||||
satsFee: Float
|
satsFee: Float
|
||||||
status: String
|
status: String
|
||||||
|
@ -34,7 +34,7 @@ const createUserFilter = (tag) => {
|
|||||||
|
|
||||||
const createItemUrl = async ({ id }) => {
|
const createItemUrl = async ({ id }) => {
|
||||||
const [rootItem] = await models.$queryRawUnsafe(
|
const [rootItem] = await models.$queryRawUnsafe(
|
||||||
'SELECT subpath(path, -LEAST(nlevel(path), $1), 1)::text AS id FROM "Item" WHERE id = $2',
|
'SELECT subpath(path, -LEAST(nlevel(path), $1::INTEGER), 1)::text AS id FROM "Item" WHERE id = $2::INTEGER',
|
||||||
COMMENT_DEPTH_LIMIT + 1, Number(id)
|
COMMENT_DEPTH_LIMIT + 1, Number(id)
|
||||||
)
|
)
|
||||||
return `/items/${rootItem.id}` + (rootItem.id !== id ? `?commentId=${id}` : '')
|
return `/items/${rootItem.id}` + (rootItem.id !== id ? `?commentId=${id}` : '')
|
||||||
|
@ -126,10 +126,12 @@ export default function JobForm ({ item, sub }) {
|
|||||||
clear
|
clear
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Checkbox
|
<Col className='d-flex ps-0' xs='auto'>
|
||||||
label={<div className='fw-bold'>remote</div>} name='remote' hiddenLabel
|
<Checkbox
|
||||||
groupClassName={styles.inlineCheckGroup}
|
label={<div className='fw-bold'>remote</div>} name='remote' hiddenLabel
|
||||||
/>
|
groupClassName={styles.inlineCheckGroup}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<MarkdownInput
|
<MarkdownInput
|
||||||
topLevel
|
topLevel
|
||||||
|
@ -28,6 +28,10 @@ export const ITEM_SORTS = ['votes', 'comments', 'sats']
|
|||||||
export const WHENS = ['day', 'week', 'month', 'year', 'forever']
|
export const WHENS = ['day', 'week', 'month', 'year', 'forever']
|
||||||
|
|
||||||
export const ITEM_TYPES = context => {
|
export const ITEM_TYPES = context => {
|
||||||
|
if (context === 'jobs') {
|
||||||
|
return ['posts', 'comments', 'all', 'freebies']
|
||||||
|
}
|
||||||
|
|
||||||
const items = ['all', 'posts', 'comments', 'bounties', 'links', 'discussions', 'polls']
|
const items = ['all', 'posts', 'comments', 'bounties', 'links', 'discussions', 'polls']
|
||||||
if (!context) {
|
if (!context) {
|
||||||
items.push('bios', 'jobs')
|
items.push('bios', 'jobs')
|
||||||
|
@ -21,5 +21,5 @@ export const msatsToSatsDecimal = msats => {
|
|||||||
if (msats === null || msats === undefined) {
|
if (msats === null || msats === undefined) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return fixedDecimal(msats / 1000.0, 3)
|
return fixedDecimal(Number(msats) / 1000.0, 3)
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ export const jobSchema = object({
|
|||||||
v => !v?.match(/\bremote\b/gi))
|
v => !v?.match(/\bremote\b/gi))
|
||||||
.when('remote', {
|
.when('remote', {
|
||||||
is: (value) => !value,
|
is: (value) => !value,
|
||||||
then: string().required('required').trim()
|
then: schema => schema.required('required').trim()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
64
package-lock.json
generated
64
package-lock.json
generated
@ -14,7 +14,7 @@
|
|||||||
"@graphql-tools/schema": "^10.0.0",
|
"@graphql-tools/schema": "^10.0.0",
|
||||||
"@noble/curves": "^1.1.0",
|
"@noble/curves": "^1.1.0",
|
||||||
"@opensearch-project/opensearch": "^2.3.1",
|
"@opensearch-project/opensearch": "^2.3.1",
|
||||||
"@prisma/client": "^3.15.2",
|
"@prisma/client": "^4.16.2",
|
||||||
"@synonymdev/slashtags-auth": "^1.0.0-alpha.5",
|
"@synonymdev/slashtags-auth": "^1.0.0-alpha.5",
|
||||||
"@synonymdev/slashtags-sdk": "^1.0.0-alpha.36",
|
"@synonymdev/slashtags-sdk": "^1.0.0-alpha.36",
|
||||||
"acorn": "^8.10.0",
|
"acorn": "^8.10.0",
|
||||||
@ -53,7 +53,7 @@
|
|||||||
"page-metadata-parser": "^1.1.4",
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pageres": "^7.1.0",
|
"pageres": "^7.1.0",
|
||||||
"pg-boss": "^9.0.3",
|
"pg-boss": "^9.0.3",
|
||||||
"prisma": "^3.15.2",
|
"prisma": "^4.16.2",
|
||||||
"qrcode.react": "^3.1.0",
|
"qrcode.react": "^3.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-avatar-editor": "^13.0.0",
|
"react-avatar-editor": "^13.0.0",
|
||||||
@ -2982,15 +2982,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client": {
|
"node_modules/@prisma/client": {
|
||||||
"version": "3.15.2",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.16.2.tgz",
|
||||||
"integrity": "sha512-ErqtwhX12ubPhU4d++30uFY/rPcyvjk+mdifaZO5SeM21zS3t4jQrscy8+6IyB0GIYshl5ldTq6JSBo1d63i8w==",
|
"integrity": "sha512-qCoEyxv1ZrQ4bKy39GnylE8Zq31IRmm8bNhNbZx7bF2cU5aiCCnSa93J2imF88MBjn7J9eUQneNxUQVJdl/rPQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines-version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
|
"@prisma/engines-version": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.6"
|
"node": ">=14.17"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"prisma": "*"
|
"prisma": "*"
|
||||||
@ -3002,15 +3002,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines": {
|
"node_modules/@prisma/engines": {
|
||||||
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.16.2.tgz",
|
||||||
"integrity": "sha512-NHlojO1DFTsSi3FtEleL9QWXeSF/UjhCW0fgpi7bumnNZ4wj/eQ+BJJ5n2pgoOliTOGv9nX2qXvmHap7rJMNmg==",
|
"integrity": "sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw==",
|
||||||
"hasInstallScript": true
|
"hasInstallScript": true
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines-version": {
|
"node_modules/@prisma/engines-version": {
|
||||||
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
|
"version": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81.tgz",
|
||||||
"integrity": "sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w=="
|
"integrity": "sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg=="
|
||||||
},
|
},
|
||||||
"node_modules/@protobufjs/aspromise": {
|
"node_modules/@protobufjs/aspromise": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -15025,19 +15025,19 @@
|
|||||||
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "3.15.2",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.16.2.tgz",
|
||||||
"integrity": "sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA==",
|
"integrity": "sha512-SYCsBvDf0/7XSJyf2cHTLjLeTLVXYfqp7pG5eEVafFLeT0u/hLFz/9W196nDRGUOo1JfPatAEb+uEnTQImQC1g==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
|
"@prisma/engines": "4.16.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"prisma": "build/index.js",
|
"prisma": "build/index.js",
|
||||||
"prisma2": "build/index.js"
|
"prisma2": "build/index.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.6"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prismjs": {
|
"node_modules/prismjs": {
|
||||||
@ -22131,22 +22131,22 @@
|
|||||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
|
||||||
},
|
},
|
||||||
"@prisma/client": {
|
"@prisma/client": {
|
||||||
"version": "3.15.2",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.16.2.tgz",
|
||||||
"integrity": "sha512-ErqtwhX12ubPhU4d++30uFY/rPcyvjk+mdifaZO5SeM21zS3t4jQrscy8+6IyB0GIYshl5ldTq6JSBo1d63i8w==",
|
"integrity": "sha512-qCoEyxv1ZrQ4bKy39GnylE8Zq31IRmm8bNhNbZx7bF2cU5aiCCnSa93J2imF88MBjn7J9eUQneNxUQVJdl/rPQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@prisma/engines-version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
|
"@prisma/engines-version": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@prisma/engines": {
|
"@prisma/engines": {
|
||||||
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.16.2.tgz",
|
||||||
"integrity": "sha512-NHlojO1DFTsSi3FtEleL9QWXeSF/UjhCW0fgpi7bumnNZ4wj/eQ+BJJ5n2pgoOliTOGv9nX2qXvmHap7rJMNmg=="
|
"integrity": "sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw=="
|
||||||
},
|
},
|
||||||
"@prisma/engines-version": {
|
"@prisma/engines-version": {
|
||||||
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
|
"version": "4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81.tgz",
|
||||||
"integrity": "sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w=="
|
"integrity": "sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg=="
|
||||||
},
|
},
|
||||||
"@protobufjs/aspromise": {
|
"@protobufjs/aspromise": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -30717,11 +30717,11 @@
|
|||||||
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
||||||
},
|
},
|
||||||
"prisma": {
|
"prisma": {
|
||||||
"version": "3.15.2",
|
"version": "4.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.16.2.tgz",
|
||||||
"integrity": "sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA==",
|
"integrity": "sha512-SYCsBvDf0/7XSJyf2cHTLjLeTLVXYfqp7pG5eEVafFLeT0u/hLFz/9W196nDRGUOo1JfPatAEb+uEnTQImQC1g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@prisma/engines": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
|
"@prisma/engines": "4.16.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prismjs": {
|
"prismjs": {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"@graphql-tools/schema": "^10.0.0",
|
"@graphql-tools/schema": "^10.0.0",
|
||||||
"@noble/curves": "^1.1.0",
|
"@noble/curves": "^1.1.0",
|
||||||
"@opensearch-project/opensearch": "^2.3.1",
|
"@opensearch-project/opensearch": "^2.3.1",
|
||||||
"@prisma/client": "^3.15.2",
|
"@prisma/client": "^4.16.2",
|
||||||
"@synonymdev/slashtags-auth": "^1.0.0-alpha.5",
|
"@synonymdev/slashtags-auth": "^1.0.0-alpha.5",
|
||||||
"@synonymdev/slashtags-sdk": "^1.0.0-alpha.36",
|
"@synonymdev/slashtags-sdk": "^1.0.0-alpha.36",
|
||||||
"acorn": "^8.10.0",
|
"acorn": "^8.10.0",
|
||||||
@ -54,7 +54,7 @@
|
|||||||
"page-metadata-parser": "^1.1.4",
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pageres": "^7.1.0",
|
"pageres": "^7.1.0",
|
||||||
"pg-boss": "^9.0.3",
|
"pg-boss": "^9.0.3",
|
||||||
"prisma": "^3.15.2",
|
"prisma": "^4.16.2",
|
||||||
"qrcode.react": "^3.1.0",
|
"qrcode.react": "^3.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-avatar-editor": "^13.0.0",
|
"react-avatar-editor": "^13.0.0",
|
||||||
|
@ -14,7 +14,7 @@ const apolloServer = new ApolloServer({
|
|||||||
plugins: [{
|
plugins: [{
|
||||||
requestDidStart (initialRequestContext) {
|
requestDidStart (initialRequestContext) {
|
||||||
return {
|
return {
|
||||||
executionDidStart (executionRequestContext) {
|
executionDidStart () {
|
||||||
return {
|
return {
|
||||||
willResolveField ({ source, args, context, info }) {
|
willResolveField ({ source, args, context, info }) {
|
||||||
const start = process.hrtime.bigint()
|
const start = process.hrtime.bigint()
|
||||||
@ -28,6 +28,11 @@ const apolloServer = new ApolloServer({
|
|||||||
console.log(`Field ${info.parentType.name}.${info.fieldName} failed with ${error}`)
|
console.log(`Field ${info.parentType.name}.${info.fieldName} failed with ${error}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async executionDidEnd (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error('hey bud', err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export default async ({ query: { username, amount, nostr } }, res) => {
|
|||||||
|
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${invoice.request},
|
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${invoice.request},
|
||||||
${expiresAt}, ${Number(amount)}, ${user.id}, ${noteStr || description})`)
|
${expiresAt}, ${Number(amount)}, ${user.id}::INTEGER, ${noteStr || description})`)
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
pr: invoice.request,
|
pr: invoice.request,
|
||||||
|
@ -33,7 +33,7 @@ export async function getServerSideProps ({ req, res, query: { id, error = null
|
|||||||
// attempt to send gift
|
// attempt to send gift
|
||||||
// catch any errors and just ignore them for now
|
// catch any errors and just ignore them for now
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$queryRawUnsafe('SELECT invite_drain($1, $2)', session.user.id, id))
|
models.$queryRawUnsafe('SELECT invite_drain($1::INTEGER, $2::INTEGER)', session.user.id, id))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
-- multiple create_polls
|
||||||
|
DROP FUNCTION IF EXISTS create_poll(title text, poll_cost integer, boost integer, user_id integer, options text[]);
|
||||||
|
DROP FUNCTION IF EXISTS create_poll(title text, text text, poll_cost integer, boost integer, user_id integer, options text[]);
|
||||||
|
|
||||||
|
-- multiple create_items
|
||||||
|
DROP FUNCTION IF EXISTS create_item(title text, url text, text text, boost integer, parent_id integer, user_id integer);
|
||||||
|
DROP FUNCTION IF EXISTS create_item(title text, url text, text text, boost integer, parent_id integer, user_id integer, fwd_user_id integer, spam_within interval);
|
||||||
|
|
||||||
|
-- multiple earn
|
||||||
|
DROP FUNCTION IF EXISTS earn(user_id integer, earn_msats int);
|
||||||
|
|
||||||
|
-- multiple run_auction
|
||||||
|
DROP FUNCTION IF EXISTS run_auction(item_id integer, bid integer);
|
||||||
|
|
||||||
|
-- multiple update_items
|
||||||
|
DROP FUNCTION IF EXISTS update_item(item_id integer, item_title text, item_url text, item_text text, boost integer, fwd_user_id integer);
|
||||||
|
|
||||||
|
-- multiple update_polls
|
||||||
|
DROP FUNCTION IF EXISTS update_poll(id integer, title text, text text, boost integer, options text[], fwd_user_id integer);
|
||||||
|
|
||||||
|
-- unused vote
|
||||||
|
DROP FUNCTION IF EXISTS vote(item_id integer, username text, vote_sats integer);
|
@ -56,10 +56,6 @@ model User {
|
|||||||
streak Int?
|
streak Int?
|
||||||
subs String[]
|
subs String[]
|
||||||
hideCowboyHat Boolean @default(false)
|
hideCowboyHat Boolean @default(false)
|
||||||
bio Item? @relation(fields: [bioId], references: [id])
|
|
||||||
invite Invite? @relation(fields: [inviteId], references: [id])
|
|
||||||
photo Upload? @relation(fields: [photoId], references: [id])
|
|
||||||
referrer User? @relation("referrals", fields: [referrerId], references: [id])
|
|
||||||
Bookmarks Bookmark[]
|
Bookmarks Bookmark[]
|
||||||
Donation Donation[]
|
Donation Donation[]
|
||||||
Earn Earn[]
|
Earn Earn[]
|
||||||
@ -79,6 +75,10 @@ model User {
|
|||||||
Upload Upload[] @relation("Uploads")
|
Upload Upload[] @relation("Uploads")
|
||||||
nostrRelays UserNostrRelay[]
|
nostrRelays UserNostrRelay[]
|
||||||
withdrawls Withdrawl[]
|
withdrawls Withdrawl[]
|
||||||
|
bio Item? @relation(fields: [bioId], references: [id])
|
||||||
|
invite Invite? @relation(fields: [inviteId], references: [id])
|
||||||
|
photo Upload? @relation(fields: [photoId], references: [id])
|
||||||
|
referrer User? @relation("referrals", fields: [referrerId], references: [id])
|
||||||
referrees User[] @relation("referrals")
|
referrees User[] @relation("referrals")
|
||||||
|
|
||||||
@@index([createdAt], map: "users.created_at_index")
|
@@index([createdAt], map: "users.created_at_index")
|
||||||
@ -200,6 +200,7 @@ model Message {
|
|||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info.
|
||||||
model Item {
|
model Item {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
@ -243,15 +244,15 @@ model Item {
|
|||||||
bountyPaidTo Int[]
|
bountyPaidTo Int[]
|
||||||
upvotes Int @default(0)
|
upvotes Int @default(0)
|
||||||
weightedComments Float @default(0)
|
weightedComments Float @default(0)
|
||||||
|
Bookmark Bookmark[]
|
||||||
fwdUser User? @relation("FwdItem", fields: [fwdUserId], references: [id])
|
fwdUser User? @relation("FwdItem", fields: [fwdUserId], references: [id])
|
||||||
parent Item? @relation("ParentChildren", fields: [parentId], references: [id])
|
parent Item? @relation("ParentChildren", fields: [parentId], references: [id])
|
||||||
|
children Item[] @relation("ParentChildren")
|
||||||
pin Pin? @relation(fields: [pinId], references: [id])
|
pin Pin? @relation(fields: [pinId], references: [id])
|
||||||
root Item? @relation("RootDescendant", fields: [rootId], references: [id])
|
root Item? @relation("RootDescendant", fields: [rootId], references: [id])
|
||||||
|
descendants Item[] @relation("RootDescendant")
|
||||||
sub Sub? @relation(fields: [subName], references: [name])
|
sub Sub? @relation(fields: [subName], references: [name])
|
||||||
user User @relation("UserItems", fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation("UserItems", fields: [userId], references: [id], onDelete: Cascade)
|
||||||
Bookmark Bookmark[]
|
|
||||||
children Item[] @relation("ParentChildren")
|
|
||||||
descendants Item[] @relation("RootDescendant")
|
|
||||||
actions ItemAct[]
|
actions ItemAct[]
|
||||||
mentions Mention[]
|
mentions Mention[]
|
||||||
PollOption PollOption[]
|
PollOption PollOption[]
|
||||||
@ -265,8 +266,8 @@ model Item {
|
|||||||
@@index([freebie], map: "Item.freebie_index")
|
@@index([freebie], map: "Item.freebie_index")
|
||||||
@@index([maxBid], map: "Item.maxBid_index")
|
@@index([maxBid], map: "Item.maxBid_index")
|
||||||
@@index([parentId], map: "Item.parentId_index")
|
@@index([parentId], map: "Item.parentId_index")
|
||||||
@@index([path], map: "Item.path_index")
|
@@index([path], map: "Item.path_index", type: Gist)
|
||||||
@@index([path], map: "Item.path_index0")
|
@@index([path], map: "Item.path_index0", type: Gist)
|
||||||
@@index([pinId], map: "Item.pinId_index")
|
@@index([pinId], map: "Item.pinId_index")
|
||||||
@@index([rootId], map: "Item.rootId_index")
|
@@index([rootId], map: "Item.rootId_index")
|
||||||
@@index([statusUpdatedAt], map: "Item.statusUpdatedAt_index")
|
@@index([statusUpdatedAt], map: "Item.statusUpdatedAt_index")
|
||||||
|
@ -262,7 +262,7 @@ div[contenteditable]:disabled,
|
|||||||
.form-control[readonly] {
|
.form-control[readonly] {
|
||||||
background-color: var(--theme-inputDisabledBg);
|
background-color: var(--theme-inputDisabledBg);
|
||||||
border-color: var(--theme-borderColor);
|
border-color: var(--theme-borderColor);
|
||||||
color: var(--theme-color);
|
color: var(--theme-borderColor);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +489,6 @@ div[contenteditable] {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.dropdown-item.active {
|
.dropdown-item.active {
|
||||||
text-shadow: 0 0 10px var(--bs-primary);
|
text-shadow: 0 0 10px var(--bs-primary);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ function auction ({ models }) {
|
|||||||
// for each item, run serialized auction function
|
// for each item, run serialized auction function
|
||||||
items.forEach(async item => {
|
items.forEach(async item => {
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$executeRaw`SELECT run_auction(${item.id})`)
|
models.$executeRaw`SELECT run_auction(${item.id}::INTEGER)`)
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('done', name)
|
console.log('done', name)
|
||||||
|
@ -21,7 +21,7 @@ function earn ({ models }) {
|
|||||||
SELECT coalesce(sum(sats), 0) as sum
|
SELECT coalesce(sum(sats), 0) as sum
|
||||||
FROM "Donation"
|
FROM "Donation"
|
||||||
WHERE created_at > now_utc() - INTERVAL '1 day'`
|
WHERE created_at > now_utc() - INTERVAL '1 day'`
|
||||||
sum += donatedSum * 1000
|
sum += donatedSum * 1000n
|
||||||
|
|
||||||
/*
|
/*
|
||||||
How earnings (used to) work:
|
How earnings (used to) work:
|
||||||
@ -88,13 +88,13 @@ function earn ({ models }) {
|
|||||||
const now = new Date(new Date().getTime())
|
const now = new Date(new Date().getTime())
|
||||||
|
|
||||||
// this is just a sanity check because it seems like a good idea
|
// this is just a sanity check because it seems like a good idea
|
||||||
let total = 0
|
let total = 0n
|
||||||
|
|
||||||
// for each earner, serialize earnings
|
// for each earner, serialize earnings
|
||||||
// we do this for each earner because we don't need to serialize
|
// we do this for each earner because we don't need to serialize
|
||||||
// all earner updates together
|
// all earner updates together
|
||||||
earners.forEach(async earner => {
|
earners.forEach(async earner => {
|
||||||
const earnings = Math.floor(earner.proportion * sum)
|
const earnings = BigInt(Math.floor(earner.proportion * sum))
|
||||||
total += earnings
|
total += earnings
|
||||||
if (total > sum) {
|
if (total > sum) {
|
||||||
console.log('total exceeds sum', name)
|
console.log('total exceeds sum', name)
|
||||||
@ -103,8 +103,8 @@ function earn ({ models }) {
|
|||||||
|
|
||||||
if (earnings > 0) {
|
if (earnings > 0) {
|
||||||
await serialize(models,
|
await serialize(models,
|
||||||
models.$executeRaw`SELECT earn(${earner.userId}, ${earnings},
|
models.$executeRaw`SELECT earn(${earner.userId}::INTEGER, ${earnings},
|
||||||
${now}, ${earner.type}, ${earner.id}, ${earner.rank})`)
|
${now}::timestamp without time zone, ${earner.type}::"EarnType", ${earner.id}::INTEGER, ${earner.rank}::INTEGER)`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user