diff --git a/README.md b/README.md index cccaa25..8fb070c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Makers.Bolt.Fun +# Lightning Landscape -A lightning apps directory made for and by the bitcoin community. +A directory for lightning startups, projects, and companies. ## Environment Setup @@ -25,48 +25,3 @@ This will spin up a local mocks server with mock data, so you can use the app of This will assume that you have a local api server running on port 8888, and will connect to it. In all cases, the application will be running on http://localhost:3000 - -# Backend API - -We are using serverless functions to serve our GraphQl endpoint to the client app. - -## Running locally - -To run the project locally with your own local DB, you will need to first put a few env variables in an env file that should be created in /envs/server directory, named `local.env` - -The required variables that needs to be put there are: - -``` -NODE_ENV = "development" -DATABASE_PROXY_URL = "YOUR DB CONNECTION STRING" -JWT_SECRET = "SOME RANDOM JWT SECRET" -LNURL_AUTH_HOST = "http://localhost:8888/dev/login" -CLOUDFLARE_IMAGE_ACCOUNT_ID = "FOR UPLOADING IMAGES" -CLOUDFLARE_IMAGE_API_KEY = "FOR UPLOADING IMAGES" -CLOUDFLARE_IMAGE_ACCOUNT_HASH = "FOR UPLOADING IMAGES" -``` - -Then you need to run the migrations against your database. -use the command: - -### `npm run db:migrate-dev` - -Finally, you can start the serverless functions using the command: - -### `npm run server:dev` - -And your functions will be served on http://localhost:8888/dev/graphql - -## Database - -`prisma studio` - -prisma studio runs an UI for the DB - -`prisma migrate dev` - -Create a migration from the schema.prisma file - -`prisma migrate deploy` - -Apply pending migrations to the database diff --git a/api/auth/services/lnurlAuth.service.js b/api/auth/services/lnurlAuth.service.js deleted file mode 100644 index 1dcb91c..0000000 --- a/api/auth/services/lnurlAuth.service.js +++ /dev/null @@ -1,132 +0,0 @@ -const lnurl = require('lnurl') -const crypto = require('crypto') -const { prisma } = require('../../prisma') -const { CONSTS } = require('../../utils') - -async function generateK1() { - let k1 = null - const maxAttempts = 5 - let attempt = 0 - while (k1 === null && attempt < maxAttempts) { - k1 = crypto.randomBytes(32).toString('hex') - const hash = createHash(k1) - const isUsed = await isHashUsed(hash); - if (isUsed) { - k1 = null - } - attempt++ - } - if (!k1) { - const message = 'Too many failed attempts to generate unique k1' - throw new Error(message) - } - return k1 -} - -function isHashUsed(hash) { - return prisma.generatedK1.findFirst({ where: { value: hash } }) -} - -function addHash(hash) { - return prisma.generatedK1.create({ - data: { - value: hash, - } - }) -} - -function removeHash(hash) { - return prisma.generatedK1.delete({ - where: { - value: hash, - } - }) -} - -function removeExpiredHashes() { - const now = new Date(); - const lastHourDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes() - 10); - - return prisma.generatedK1.deleteMany({ - where: { - createdAt: { - lt: lastHourDate - } - } - }) -} - - - -async function generateAuthUrl(options) { - const hostname = CONSTS.LNURL_AUTH_HOST ?? 'https://auth.bolt.fun/.netlify/functions/login'; - const secret = await generateK1(); - const hash = createHash(secret); - await addHash(hash) - let url = `${hostname}?tag=login&k1=${secret}` - if (options.user_token) { - url = url + `&action=link&user_token=${options.user_token}` - } - return { - url, - encoded: lnurl.encode(url).toUpperCase(), - secret, - secretHash: hash, - } -} - -async function getAuthTokenByHash(hash) { - const data = await prisma.generatedK1.findFirst({ - where: { - value: hash, - } - }); - return data.sid; -} - -function associateTokenToHash(hash, token) { - return prisma.generatedK1.update({ - where: { - value: hash - }, - data: { - sid: token - } - }) -} - -async function verifySig(sig, k1, key) { - if (!lnurl.verifyAuthorizationSignature(sig, k1, key)) { - const message = 'Signature verification failed' - throw new Error(message) - } - const hash = createHash(k1) - const hashExist = await isHashUsed(hash); - if (!hashExist) - throw new Error('Provided k1 is not issued by server') - return { key, hash } -} - -function createHash(data) { - if (!(typeof data === 'string' || Buffer.isBuffer(data))) { - throw new Error( - JSON.stringify({ status: 'ERROR', reason: 'Secret must be a string or a Buffer' }) - ) - } - if (typeof data === 'string') { - data = Buffer.from(data, 'hex') - } - return crypto.createHash('sha256').update(data).digest('hex') -} - - - -module.exports = { - generateAuthUrl: generateAuthUrl, - verifySig: verifySig, - removeHash: removeHash, - createHash: createHash, - removeExpiredHashes: removeExpiredHashes, - getAuthTokenByHash: getAuthTokenByHash, - associateTokenToHash: associateTokenToHash -} \ No newline at end of file diff --git a/api/auth/utils/helperFuncs.js b/api/auth/utils/helperFuncs.js deleted file mode 100644 index 54fbf09..0000000 --- a/api/auth/utils/helperFuncs.js +++ /dev/null @@ -1,16 +0,0 @@ - -const { prisma } = require('../../prisma') - -const getUserByPubKey = (pubKey) => { - if (!pubKey) return null; - return prisma.userKey.findUnique({ - where: { - key: pubKey - }, - }).user() -} - - -module.exports = { - getUserByPubKey, -} \ No newline at end of file diff --git a/api/functions/get-login-url/get-login-url.js b/api/functions/get-login-url/get-login-url.js deleted file mode 100644 index 1df402c..0000000 --- a/api/functions/get-login-url/get-login-url.js +++ /dev/null @@ -1,70 +0,0 @@ - -const LnurlAuthService = require('../../auth/services/lnurlAuth.service') -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const jose = require('jose'); -const { JWT_SECRET } = require('../../utils/consts'); -const extractKeyFromCookie = require('../../utils/extractKeyFromCookie'); -const { getUserByPubKey } = require('../../auth/utils/helperFuncs'); - - - - - -const getLoginUrl = async (req, res) => { - - const { action } = req.query; - - try { - - let user_token = null; - if (action === 'link') { - const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie) - const user = await getUserByPubKey(userPubKey); - - if (!user) - return res.status(400).json({ status: 'ERROR', reason: 'Only authenticated user can request a linking URL' }); - - user_token = await new jose.SignJWT({ user_id: user.id }) - .setProtectedHeader({ alg: 'HS256' }) - .setIssuedAt() - .setExpirationTime('5min') - .sign(Buffer.from(JWT_SECRET, 'utf-8')) - } - - const data = await LnurlAuthService.generateAuthUrl({ user_token }); - - const session_token = await new jose.SignJWT({ hash: data.secretHash }) - .setProtectedHeader({ alg: 'HS256' }) - .setIssuedAt() - .setExpirationTime('5min') - .sign(Buffer.from(JWT_SECRET, 'utf-8')) - - return res - .status(200) - .json({ ...data, session_token }); - } catch (error) { - res.status(500).send("Unexpected error happened, please try again") - } - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.get('/get-login-url', getLoginUrl); -} -else { - const router = express.Router(); - router.get('/get-login-url', getLoginUrl) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/graphql/index.js b/api/functions/graphql/index.js deleted file mode 100644 index ca0998e..0000000 --- a/api/functions/graphql/index.js +++ /dev/null @@ -1,40 +0,0 @@ -const { ApolloServer } = require("apollo-server-lambda"); -const schema = require('./schema') -const extractKeyFromCookie = require("../../utils/extractKeyFromCookie"); - - - -const server = new ApolloServer({ - schema, - context: async ({ event }) => { - const userPubKey = await extractKeyFromCookie(event.headers.cookie ?? event.headers.Cookie) - return { userPubKey } - }, -}); - - - -const apolloHandler = server.createHandler({ - expressGetMiddlewareOptions: { - cors: { - origin: ['http://localhost:3000', 'https://studio.apollographql.com'], - credentials: true, - } - } -}); - - -// https://github.com/vendia/serverless-express/issues/427#issuecomment-924580007 -const handler = (event, context, ...args) => { - - return apolloHandler( - { - ...event, - requestContext: context, - }, - context, - ...args - ); -}; - -exports.handler = handler; diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts deleted file mode 100644 index 0ea50ce..0000000 --- a/api/functions/graphql/nexus-typegen.ts +++ /dev/null @@ -1,1439 +0,0 @@ -/** - * This file was generated by Nexus Schema - * Do not make changes to this file directly - */ - - -import type { core } from "nexus" -declare global { - interface NexusGenCustomInputMethods { - /** - * Date custom scalar type - */ - date(fieldName: FieldName, opts?: core.CommonInputFieldConfig): void // "Date"; - } -} -declare global { - interface NexusGenCustomOutputMethods { - /** - * Date custom scalar type - */ - date(fieldName: FieldName, ...opts: core.ScalarOutSpread): void // "Date"; - } -} - - -declare global { - interface NexusGen extends NexusGenTypes {} -} - -export interface NexusGenInputs { - CreateProjectInput: { // input type - capabilities: number[]; // [Int!]! - category_id: number; // Int! - cover_image: NexusGenInputs['ImageInput']; // ImageInput! - description: string; // String! - discord?: string | null; // String - github?: string | null; // String - hashtag: string; // String! - id?: number | null; // Int - launch_status: NexusGenEnums['ProjectLaunchStatusEnum']; // ProjectLaunchStatusEnum! - lightning_address?: string | null; // String - members: NexusGenInputs['TeamMemberInput'][]; // [TeamMemberInput!]! - recruit_roles: number[]; // [Int!]! - screenshots: NexusGenInputs['ImageInput'][]; // [ImageInput!]! - slack?: string | null; // String - tagline: string; // String! - telegram?: string | null; // String - thumbnail_image: NexusGenInputs['ImageInput']; // ImageInput! - title: string; // String! - tournaments: number[]; // [Int!]! - twitter?: string | null; // String - website: string; // String! - } - ImageInput: { // input type - id?: string | null; // String - name?: string | null; // String - url: string; // String! - } - MakerRoleInput: { // input type - id: number; // Int! - level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum! - } - MakerSkillInput: { // input type - id: number; // Int! - } - ProfileDetailsInput: { // input type - avatar?: NexusGenInputs['ImageInput'] | null; // ImageInput - bio?: string | null; // String - discord?: string | null; // String - email?: string | null; // String - github?: string | null; // String - jobTitle?: string | null; // String - lightning_address?: string | null; // String - linkedin?: string | null; // String - location?: string | null; // String - name?: string | null; // String - twitter?: string | null; // String - website?: string | null; // String - } - ProfileRolesInput: { // input type - roles: NexusGenInputs['MakerRoleInput'][]; // [MakerRoleInput!]! - skills: NexusGenInputs['MakerSkillInput'][]; // [MakerSkillInput!]! - } - RegisterInTournamentInput: { // input type - email: string; // String! - hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! - } - StoryInputType: { // input type - body: string; // String! - cover_image?: NexusGenInputs['ImageInput'] | null; // ImageInput - id?: number | null; // Int - is_published?: boolean | null; // Boolean - project_id?: number | null; // Int - tags: string[]; // [String!]! - title: string; // String! - } - TeamMemberInput: { // input type - id: number; // Int! - role: NexusGenEnums['TEAM_MEMBER_ROLE']; // TEAM_MEMBER_ROLE! - } - UpdateProjectInput: { // input type - capabilities: number[]; // [Int!]! - category_id: number; // Int! - cover_image: NexusGenInputs['ImageInput']; // ImageInput! - description: string; // String! - discord?: string | null; // String - github?: string | null; // String - hashtag: string; // String! - id?: number | null; // Int - launch_status: NexusGenEnums['ProjectLaunchStatusEnum']; // ProjectLaunchStatusEnum! - lightning_address?: string | null; // String - members: NexusGenInputs['TeamMemberInput'][]; // [TeamMemberInput!]! - recruit_roles: number[]; // [Int!]! - screenshots: NexusGenInputs['ImageInput'][]; // [ImageInput!]! - slack?: string | null; // String - tagline: string; // String! - telegram?: string | null; // String - thumbnail_image: NexusGenInputs['ImageInput']; // ImageInput! - title: string; // String! - tournaments: number[]; // [Int!]! - twitter?: string | null; // String - website: string; // String! - } - UpdateTournamentRegistrationInput: { // input type - email?: string | null; // String - hacking_status?: NexusGenEnums['TournamentMakerHackingStatusEnum'] | null; // TournamentMakerHackingStatusEnum - } - UserKeyInputType: { // input type - key: string; // String! - name: string; // String! - } -} - -export interface NexusGenEnums { - POST_TYPE: "Bounty" | "Question" | "Story" - ProjectLaunchStatusEnum: "Launched" | "WIP" - ProjectPermissionEnum: "DeleteProject" | "UpdateAdmins" | "UpdateInfo" | "UpdateMembers" - RoleLevelEnum: 3 | 0 | 1 | 2 | 4 - TEAM_MEMBER_ROLE: "Admin" | "Maker" | "Owner" - TournamentEventTypeEnum: 2 | 3 | 0 | 1 - TournamentMakerHackingStatusEnum: 1 | 0 - VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User" -} - -export interface NexusGenScalars { - String: string - Int: number - Float: number - Boolean: boolean - ID: string - Date: any -} - -export interface NexusGenObjects { - Author: { // root type - id: number; // Int! - join_date: NexusGenScalars['Date']; // Date! - lightning_address?: string | null; // String - name: string; // String! - } - Award: { // root type - id: number; // Int! - image: string; // String! - title: string; // String! - url: string; // String! - } - Bounty: { // root type - applicants_count: number; // Int! - applications: NexusGenRootTypes['BountyApplication'][]; // [BountyApplication!]! - body: string; // String! - cover_image?: string | null; // String - createdAt: NexusGenScalars['Date']; // Date! - deadline: string; // String! - excerpt: string; // String! - id: number; // Int! - is_published?: boolean | null; // Boolean - reward_amount: number; // Int! - title: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - BountyApplication: { // root type - author: NexusGenRootTypes['Author']; // Author! - date: string; // String! - id: number; // Int! - workplan: string; // String! - } - Capability: { // root type - icon: string; // String! - id: number; // Int! - title: string; // String! - } - Category: { // root type - icon?: string | null; // String - id: number; // Int! - title: string; // String! - } - CreateProjectResponse: { // root type - project: NexusGenRootTypes['Project']; // Project! - } - Donation: { // root type - amount: number; // Int! - createdAt: NexusGenScalars['Date']; // Date! - id: number; // Int! - paid: boolean; // Boolean! - payment_hash: string; // String! - payment_request: string; // String! - } - DonationsStats: { // root type - applications: string; // String! - donations: string; // String! - prizes: string; // String! - touranments: string; // String! - } - GenericMakerRole: { // root type - icon: string; // String! - id: number; // Int! - title: string; // String! - } - Hackathon: { // root type - description: string; // String! - end_date: NexusGenScalars['Date']; // Date! - id: number; // Int! - location: string; // String! - start_date: NexusGenScalars['Date']; // Date! - title: string; // String! - website: string; // String! - } - LnurlDetails: { // root type - commentAllowed?: number | null; // Int - maxSendable?: number | null; // Int - metadata?: string | null; // String - minSendable?: number | null; // Int - } - MakerRole: { // root type - icon: string; // String! - id: number; // Int! - level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum! - title: string; // String! - } - MakerSkill: { // root type - id: number; // Int! - title: string; // String! - } - Mutation: {}; - MyProfile: { // root type - bio?: string | null; // String - discord?: string | null; // String - email?: string | null; // String - github?: string | null; // String - id: number; // Int! - jobTitle?: string | null; // String - join_date: NexusGenScalars['Date']; // Date! - lightning_address?: string | null; // String - linkedin?: string | null; // String - location?: string | null; // String - name: string; // String! - nostr_prv_key?: string | null; // String - nostr_pub_key?: string | null; // String - role?: string | null; // String - twitter?: string | null; // String - website?: string | null; // String - } - ParticipationInfo: { // root type - createdAt: NexusGenScalars['Date']; // Date! - email: string; // String! - hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! - } - PostComment: { // root type - author: NexusGenRootTypes['Author']; // Author! - body: string; // String! - created_at: NexusGenScalars['Date']; // Date! - id: number; // Int! - parentId?: number | null; // Int - votes_count: number; // Int! - } - Project: { // root type - description: string; // String! - discord?: string | null; // String - github?: string | null; // String - hashtag: string; // String! - id: number; // Int! - launch_status: NexusGenEnums['ProjectLaunchStatusEnum']; // ProjectLaunchStatusEnum! - lightning_address?: string | null; // String - lnurl_callback_url?: string | null; // String - slack?: string | null; // String - tagline: string; // String! - telegram?: string | null; // String - title: string; // String! - twitter?: string | null; // String - votes_count: number; // Int! - website: string; // String! - } - ProjectMember: { // root type - role: NexusGenEnums['TEAM_MEMBER_ROLE']; // TEAM_MEMBER_ROLE! - user: NexusGenRootTypes['User']; // User! - } - Query: {}; - Question: { // root type - body: string; // String! - createdAt: NexusGenScalars['Date']; // Date! - excerpt: string; // String! - id: number; // Int! - is_published?: boolean | null; // Boolean - title: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - Story: { // root type - body: string; // String! - createdAt: NexusGenScalars['Date']; // Date! - excerpt: string; // String! - id: number; // Int! - is_published?: boolean | null; // Boolean - title: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - Tag: { // root type - description?: string | null; // String - icon?: string | null; // String - id: number; // Int! - isOfficial?: boolean | null; // Boolean - title: string; // String! - } - Tournament: { // root type - description: string; // String! - end_date: NexusGenScalars['Date']; // Date! - id: number; // Int! - location: string; // String! - start_date: NexusGenScalars['Date']; // Date! - title: string; // String! - website: string; // String! - } - TournamentEvent: { // root type - description: string; // String! - ends_at: NexusGenScalars['Date']; // Date! - id: number; // Int! - location: string; // String! - starts_at: NexusGenScalars['Date']; // Date! - title: string; // String! - type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! - website: string; // String! - } - TournamentFAQ: { // root type - answer: string; // String! - question: string; // String! - } - TournamentJudge: { // root type - company: string; // String! - name: string; // String! - } - TournamentMakersResponse: { // root type - hasNext?: boolean | null; // Boolean - hasPrev?: boolean | null; // Boolean - makers: NexusGenRootTypes['TournamentParticipant'][]; // [TournamentParticipant!]! - } - TournamentParticipant: { // root type - hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! - is_registered?: boolean | null; // Boolean - user: NexusGenRootTypes['User']; // User! - } - TournamentPrize: { // root type - amount: string; // String! - title: string; // String! - } - TournamentProjectsResponse: { // root type - hasNext?: boolean | null; // Boolean - hasPrev?: boolean | null; // Boolean - projects: NexusGenRootTypes['Project'][]; // [Project!]! - } - User: { // root type - bio?: string | null; // String - discord?: string | null; // String - github?: string | null; // String - id: number; // Int! - jobTitle?: string | null; // String - join_date: NexusGenScalars['Date']; // Date! - lightning_address?: string | null; // String - linkedin?: string | null; // String - location?: string | null; // String - name: string; // String! - role?: string | null; // String - twitter?: string | null; // String - website?: string | null; // String - } - Vote: { // root type - amount_in_sat: number; // Int! - id: number; // Int! - item_id: number; // Int! - item_type: NexusGenEnums['VOTE_ITEM_TYPE']; // VOTE_ITEM_TYPE! - paid: boolean; // Boolean! - payment_hash: string; // String! - payment_request: string; // String! - } - WalletKey: { // root type - createdAt: NexusGenScalars['Date']; // Date! - is_current: boolean; // Boolean! - key: string; // String! - name: string; // String! - } -} - -export interface NexusGenInterfaces { - BaseUser: NexusGenRootTypes['MyProfile'] | NexusGenRootTypes['User']; - PostBase: NexusGenRootTypes['Bounty'] | NexusGenRootTypes['Question'] | NexusGenRootTypes['Story']; -} - -export interface NexusGenUnions { - Post: NexusGenRootTypes['Bounty'] | NexusGenRootTypes['Question'] | NexusGenRootTypes['Story']; -} - -export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions - -export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums - -export interface NexusGenFieldTypes { - Author: { // field return type - avatar: string; // String! - id: number; // Int! - join_date: NexusGenScalars['Date']; // Date! - lightning_address: string | null; // String - name: string; // String! - } - Award: { // field return type - id: number; // Int! - image: string; // String! - project: NexusGenRootTypes['Project']; // Project! - title: string; // String! - url: string; // String! - } - Bounty: { // field return type - applicants_count: number; // Int! - applications: NexusGenRootTypes['BountyApplication'][]; // [BountyApplication!]! - author: NexusGenRootTypes['Author']; // Author! - body: string; // String! - cover_image: string | null; // String - createdAt: NexusGenScalars['Date']; // Date! - deadline: string; // String! - excerpt: string; // String! - id: number; // Int! - is_published: boolean | null; // Boolean - reward_amount: number; // Int! - tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - title: string; // String! - type: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - BountyApplication: { // field return type - author: NexusGenRootTypes['Author']; // Author! - date: string; // String! - id: number; // Int! - workplan: string; // String! - } - Capability: { // field return type - icon: string; // String! - id: number; // Int! - title: string; // String! - } - Category: { // field return type - apps_count: number; // Int! - cover_image: string | null; // String - icon: string | null; // String - id: number; // Int! - project: NexusGenRootTypes['Project'][]; // [Project!]! - title: string; // String! - votes_sum: number; // Int! - } - CreateProjectResponse: { // field return type - project: NexusGenRootTypes['Project']; // Project! - } - Donation: { // field return type - amount: number; // Int! - by: NexusGenRootTypes['User'] | null; // User - createdAt: NexusGenScalars['Date']; // Date! - id: number; // Int! - paid: boolean; // Boolean! - payment_hash: string; // String! - payment_request: string; // String! - } - DonationsStats: { // field return type - applications: string; // String! - donations: string; // String! - prizes: string; // String! - touranments: string; // String! - } - GenericMakerRole: { // field return type - icon: string; // String! - id: number; // Int! - title: string; // String! - } - Hackathon: { // field return type - cover_image: string; // String! - description: string; // String! - end_date: NexusGenScalars['Date']; // Date! - id: number; // Int! - location: string; // String! - start_date: NexusGenScalars['Date']; // Date! - tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - title: string; // String! - website: string; // String! - } - LnurlDetails: { // field return type - commentAllowed: number | null; // Int - maxSendable: number | null; // Int - metadata: string | null; // String - minSendable: number | null; // Int - } - MakerRole: { // field return type - icon: string; // String! - id: number; // Int! - level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum! - title: string; // String! - } - MakerSkill: { // field return type - id: number; // Int! - title: string; // String! - } - Mutation: { // field return type - confirmDonation: NexusGenRootTypes['Donation']; // Donation! - confirmVote: NexusGenRootTypes['Vote']; // Vote! - createProject: NexusGenRootTypes['CreateProjectResponse'] | null; // CreateProjectResponse - createStory: NexusGenRootTypes['Story'] | null; // Story - deleteProject: NexusGenRootTypes['Project'] | null; // Project - deleteStory: NexusGenRootTypes['Story'] | null; // Story - donate: NexusGenRootTypes['Donation']; // Donation! - registerInTournament: NexusGenRootTypes['User'] | null; // User - updateProfileDetails: NexusGenRootTypes['MyProfile'] | null; // MyProfile - updateProfileRoles: NexusGenRootTypes['MyProfile'] | null; // MyProfile - updateProject: NexusGenRootTypes['CreateProjectResponse'] | null; // CreateProjectResponse - updateTournamentRegistration: NexusGenRootTypes['ParticipationInfo'] | null; // ParticipationInfo - updateUserPreferences: NexusGenRootTypes['MyProfile']; // MyProfile! - vote: NexusGenRootTypes['Vote']; // Vote! - } - MyProfile: { // field return type - avatar: string; // String! - bio: string | null; // String - discord: string | null; // String - email: string | null; // String - github: string | null; // String - id: number; // Int! - in_tournament: boolean; // Boolean! - jobTitle: string | null; // String - join_date: NexusGenScalars['Date']; // Date! - lightning_address: string | null; // String - linkedin: string | null; // String - location: string | null; // String - name: string; // String! - nostr_prv_key: string | null; // String - nostr_pub_key: string | null; // String - projects: NexusGenRootTypes['Project'][]; // [Project!]! - role: string | null; // String - roles: NexusGenRootTypes['MakerRole'][]; // [MakerRole!]! - similar_makers: NexusGenRootTypes['User'][]; // [User!]! - skills: NexusGenRootTypes['MakerSkill'][]; // [MakerSkill!]! - stories: NexusGenRootTypes['Story'][]; // [Story!]! - tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! - twitter: string | null; // String - walletsKeys: NexusGenRootTypes['WalletKey'][]; // [WalletKey!]! - website: string | null; // String - } - ParticipationInfo: { // field return type - createdAt: NexusGenScalars['Date']; // Date! - email: string; // String! - hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! - } - PostComment: { // field return type - author: NexusGenRootTypes['Author']; // Author! - body: string; // String! - created_at: NexusGenScalars['Date']; // Date! - id: number; // Int! - parentId: number | null; // Int - votes_count: number; // Int! - } - Project: { // field return type - awards: NexusGenRootTypes['Award'][]; // [Award!]! - capabilities: NexusGenRootTypes['Capability'][]; // [Capability!]! - category: NexusGenRootTypes['Category']; // Category! - cover_image: string; // String! - description: string; // String! - discord: string | null; // String - github: string | null; // String - hashtag: string; // String! - id: number; // Int! - launch_status: NexusGenEnums['ProjectLaunchStatusEnum']; // ProjectLaunchStatusEnum! - lightning_address: string | null; // String - lnurl_callback_url: string | null; // String - members: NexusGenRootTypes['ProjectMember'][]; // [ProjectMember!]! - permissions: NexusGenEnums['ProjectPermissionEnum'][]; // [ProjectPermissionEnum!]! - recruit_roles: NexusGenRootTypes['MakerRole'][]; // [MakerRole!]! - screenshots: string[]; // [String!]! - slack: string | null; // String - stories: NexusGenRootTypes['Story'][]; // [Story!]! - tagline: string; // String! - tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - telegram: string | null; // String - thumbnail_image: string; // String! - title: string; // String! - tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! - twitter: string | null; // String - votes_count: number; // Int! - website: string; // String! - } - ProjectMember: { // field return type - role: NexusGenEnums['TEAM_MEMBER_ROLE']; // TEAM_MEMBER_ROLE! - user: NexusGenRootTypes['User']; // User! - } - Query: { // field return type - allCategories: NexusGenRootTypes['Category'][]; // [Category!]! - allProjects: NexusGenRootTypes['Project'][]; // [Project!]! - checkValidProjectHashtag: boolean; // Boolean! - getAllCapabilities: NexusGenRootTypes['Capability'][]; // [Capability!]! - getAllHackathons: NexusGenRootTypes['Hackathon'][]; // [Hackathon!]! - getAllMakersRoles: NexusGenRootTypes['GenericMakerRole'][]; // [GenericMakerRole!]! - getAllMakersSkills: NexusGenRootTypes['MakerSkill'][]; // [MakerSkill!]! - getCategory: NexusGenRootTypes['Category']; // Category! - getDonationsStats: NexusGenRootTypes['DonationsStats']; // DonationsStats! - getFeed: NexusGenRootTypes['Post'][]; // [Post!]! - getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails! - getMakersInTournament: NexusGenRootTypes['TournamentMakersResponse']; // TournamentMakersResponse! - getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! - getPostById: NexusGenRootTypes['Post']; // Post! - getProject: NexusGenRootTypes['Project']; // Project! - getProjectsInTournament: NexusGenRootTypes['TournamentProjectsResponse']; // TournamentProjectsResponse! - getTournamentById: NexusGenRootTypes['Tournament']; // Tournament! - getTournamentToRegister: NexusGenRootTypes['Tournament'][]; // [Tournament!]! - getTrendingPosts: NexusGenRootTypes['Post'][]; // [Post!]! - hottestProjects: NexusGenRootTypes['Project'][]; // [Project!]! - me: NexusGenRootTypes['MyProfile'] | null; // MyProfile - newProjects: NexusGenRootTypes['Project'][]; // [Project!]! - officialTags: NexusGenRootTypes['Tag'][]; // [Tag!]! - popularTags: NexusGenRootTypes['Tag'][]; // [Tag!]! - profile: NexusGenRootTypes['User'] | null; // User - projectsByCategory: NexusGenRootTypes['Project'][]; // [Project!]! - searchProjects: NexusGenRootTypes['Project'][]; // [Project!]! - searchUsers: NexusGenRootTypes['User'][]; // [User!]! - similarMakers: NexusGenRootTypes['User'][]; // [User!]! - similarProjects: NexusGenRootTypes['Project'][]; // [Project!]! - tournamentParticipationInfo: NexusGenRootTypes['ParticipationInfo'] | null; // ParticipationInfo - } - Question: { // field return type - author: NexusGenRootTypes['Author']; // Author! - body: string; // String! - createdAt: NexusGenScalars['Date']; // Date! - excerpt: string; // String! - id: number; // Int! - is_published: boolean | null; // Boolean - tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - title: string; // String! - type: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - Story: { // field return type - author: NexusGenRootTypes['Author']; // Author! - body: string; // String! - comments: NexusGenRootTypes['PostComment'][]; // [PostComment!]! - comments_count: number; // Int! - cover_image: string | null; // String - createdAt: NexusGenScalars['Date']; // Date! - excerpt: string; // String! - id: number; // Int! - is_published: boolean | null; // Boolean - project: NexusGenRootTypes['Project'] | null; // Project - tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - title: string; // String! - type: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } - Tag: { // field return type - description: string | null; // String - icon: string | null; // String - id: number; // Int! - isOfficial: boolean | null; // Boolean - title: string; // String! - } - Tournament: { // field return type - cover_image: string; // String! - description: string; // String! - end_date: NexusGenScalars['Date']; // Date! - events: NexusGenRootTypes['TournamentEvent'][]; // [TournamentEvent!]! - events_count: number; // Int! - faqs: NexusGenRootTypes['TournamentFAQ'][]; // [TournamentFAQ!]! - id: number; // Int! - judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! - location: string; // String! - makers_count: number; // Int! - prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! - projects_count: number; // Int! - start_date: NexusGenScalars['Date']; // Date! - thumbnail_image: string; // String! - title: string; // String! - website: string; // String! - } - TournamentEvent: { // field return type - description: string; // String! - ends_at: NexusGenScalars['Date']; // Date! - id: number; // Int! - image: string; // String! - links: string[]; // [String!]! - location: string; // String! - starts_at: NexusGenScalars['Date']; // Date! - title: string; // String! - type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum! - website: string; // String! - } - TournamentFAQ: { // field return type - answer: string; // String! - question: string; // String! - } - TournamentJudge: { // field return type - avatar: string; // String! - company: string; // String! - name: string; // String! - } - TournamentMakersResponse: { // field return type - hasNext: boolean | null; // Boolean - hasPrev: boolean | null; // Boolean - makers: NexusGenRootTypes['TournamentParticipant'][]; // [TournamentParticipant!]! - } - TournamentParticipant: { // field return type - hacking_status: NexusGenEnums['TournamentMakerHackingStatusEnum']; // TournamentMakerHackingStatusEnum! - is_registered: boolean | null; // Boolean - user: NexusGenRootTypes['User']; // User! - } - TournamentPrize: { // field return type - amount: string; // String! - image: string; // String! - title: string; // String! - } - TournamentProjectsResponse: { // field return type - hasNext: boolean | null; // Boolean - hasPrev: boolean | null; // Boolean - projects: NexusGenRootTypes['Project'][]; // [Project!]! - } - User: { // field return type - avatar: string; // String! - bio: string | null; // String - discord: string | null; // String - github: string | null; // String - id: number; // Int! - in_tournament: boolean; // Boolean! - jobTitle: string | null; // String - join_date: NexusGenScalars['Date']; // Date! - lightning_address: string | null; // String - linkedin: string | null; // String - location: string | null; // String - name: string; // String! - projects: NexusGenRootTypes['Project'][]; // [Project!]! - role: string | null; // String - roles: NexusGenRootTypes['MakerRole'][]; // [MakerRole!]! - similar_makers: NexusGenRootTypes['User'][]; // [User!]! - skills: NexusGenRootTypes['MakerSkill'][]; // [MakerSkill!]! - stories: NexusGenRootTypes['Story'][]; // [Story!]! - tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! - twitter: string | null; // String - website: string | null; // String - } - Vote: { // field return type - amount_in_sat: number; // Int! - id: number; // Int! - item_id: number; // Int! - item_type: NexusGenEnums['VOTE_ITEM_TYPE']; // VOTE_ITEM_TYPE! - paid: boolean; // Boolean! - payment_hash: string; // String! - payment_request: string; // String! - } - WalletKey: { // field return type - createdAt: NexusGenScalars['Date']; // Date! - is_current: boolean; // Boolean! - key: string; // String! - name: string; // String! - } - BaseUser: { // field return type - avatar: string; // String! - bio: string | null; // String - discord: string | null; // String - github: string | null; // String - id: number; // Int! - in_tournament: boolean; // Boolean! - jobTitle: string | null; // String - join_date: NexusGenScalars['Date']; // Date! - lightning_address: string | null; // String - linkedin: string | null; // String - location: string | null; // String - name: string; // String! - projects: NexusGenRootTypes['Project'][]; // [Project!]! - role: string | null; // String - roles: NexusGenRootTypes['MakerRole'][]; // [MakerRole!]! - similar_makers: NexusGenRootTypes['User'][]; // [User!]! - skills: NexusGenRootTypes['MakerSkill'][]; // [MakerSkill!]! - stories: NexusGenRootTypes['Story'][]; // [Story!]! - tournaments: NexusGenRootTypes['Tournament'][]; // [Tournament!]! - twitter: string | null; // String - website: string | null; // String - } - PostBase: { // field return type - body: string; // String! - createdAt: NexusGenScalars['Date']; // Date! - excerpt: string; // String! - id: number; // Int! - is_published: boolean | null; // Boolean - title: string; // String! - updatedAt: NexusGenScalars['Date']; // Date! - votes_count: number; // Int! - } -} - -export interface NexusGenFieldTypeNames { - Author: { // field return type name - avatar: 'String' - id: 'Int' - join_date: 'Date' - lightning_address: 'String' - name: 'String' - } - Award: { // field return type name - id: 'Int' - image: 'String' - project: 'Project' - title: 'String' - url: 'String' - } - Bounty: { // field return type name - applicants_count: 'Int' - applications: 'BountyApplication' - author: 'Author' - body: 'String' - cover_image: 'String' - createdAt: 'Date' - deadline: 'String' - excerpt: 'String' - id: 'Int' - is_published: 'Boolean' - reward_amount: 'Int' - tags: 'Tag' - title: 'String' - type: 'String' - updatedAt: 'Date' - votes_count: 'Int' - } - BountyApplication: { // field return type name - author: 'Author' - date: 'String' - id: 'Int' - workplan: 'String' - } - Capability: { // field return type name - icon: 'String' - id: 'Int' - title: 'String' - } - Category: { // field return type name - apps_count: 'Int' - cover_image: 'String' - icon: 'String' - id: 'Int' - project: 'Project' - title: 'String' - votes_sum: 'Int' - } - CreateProjectResponse: { // field return type name - project: 'Project' - } - Donation: { // field return type name - amount: 'Int' - by: 'User' - createdAt: 'Date' - id: 'Int' - paid: 'Boolean' - payment_hash: 'String' - payment_request: 'String' - } - DonationsStats: { // field return type name - applications: 'String' - donations: 'String' - prizes: 'String' - touranments: 'String' - } - GenericMakerRole: { // field return type name - icon: 'String' - id: 'Int' - title: 'String' - } - Hackathon: { // field return type name - cover_image: 'String' - description: 'String' - end_date: 'Date' - id: 'Int' - location: 'String' - start_date: 'Date' - tags: 'Tag' - title: 'String' - website: 'String' - } - LnurlDetails: { // field return type name - commentAllowed: 'Int' - maxSendable: 'Int' - metadata: 'String' - minSendable: 'Int' - } - MakerRole: { // field return type name - icon: 'String' - id: 'Int' - level: 'RoleLevelEnum' - title: 'String' - } - MakerSkill: { // field return type name - id: 'Int' - title: 'String' - } - Mutation: { // field return type name - confirmDonation: 'Donation' - confirmVote: 'Vote' - createProject: 'CreateProjectResponse' - createStory: 'Story' - deleteProject: 'Project' - deleteStory: 'Story' - donate: 'Donation' - registerInTournament: 'User' - updateProfileDetails: 'MyProfile' - updateProfileRoles: 'MyProfile' - updateProject: 'CreateProjectResponse' - updateTournamentRegistration: 'ParticipationInfo' - updateUserPreferences: 'MyProfile' - vote: 'Vote' - } - MyProfile: { // field return type name - avatar: 'String' - bio: 'String' - discord: 'String' - email: 'String' - github: 'String' - id: 'Int' - in_tournament: 'Boolean' - jobTitle: 'String' - join_date: 'Date' - lightning_address: 'String' - linkedin: 'String' - location: 'String' - name: 'String' - nostr_prv_key: 'String' - nostr_pub_key: 'String' - projects: 'Project' - role: 'String' - roles: 'MakerRole' - similar_makers: 'User' - skills: 'MakerSkill' - stories: 'Story' - tournaments: 'Tournament' - twitter: 'String' - walletsKeys: 'WalletKey' - website: 'String' - } - ParticipationInfo: { // field return type name - createdAt: 'Date' - email: 'String' - hacking_status: 'TournamentMakerHackingStatusEnum' - } - PostComment: { // field return type name - author: 'Author' - body: 'String' - created_at: 'Date' - id: 'Int' - parentId: 'Int' - votes_count: 'Int' - } - Project: { // field return type name - awards: 'Award' - capabilities: 'Capability' - category: 'Category' - cover_image: 'String' - description: 'String' - discord: 'String' - github: 'String' - hashtag: 'String' - id: 'Int' - launch_status: 'ProjectLaunchStatusEnum' - lightning_address: 'String' - lnurl_callback_url: 'String' - members: 'ProjectMember' - permissions: 'ProjectPermissionEnum' - recruit_roles: 'MakerRole' - screenshots: 'String' - slack: 'String' - stories: 'Story' - tagline: 'String' - tags: 'Tag' - telegram: 'String' - thumbnail_image: 'String' - title: 'String' - tournaments: 'Tournament' - twitter: 'String' - votes_count: 'Int' - website: 'String' - } - ProjectMember: { // field return type name - role: 'TEAM_MEMBER_ROLE' - user: 'User' - } - Query: { // field return type name - allCategories: 'Category' - allProjects: 'Project' - checkValidProjectHashtag: 'Boolean' - getAllCapabilities: 'Capability' - getAllHackathons: 'Hackathon' - getAllMakersRoles: 'GenericMakerRole' - getAllMakersSkills: 'MakerSkill' - getCategory: 'Category' - getDonationsStats: 'DonationsStats' - getFeed: 'Post' - getLnurlDetailsForProject: 'LnurlDetails' - getMakersInTournament: 'TournamentMakersResponse' - getMyDrafts: 'Post' - getPostById: 'Post' - getProject: 'Project' - getProjectsInTournament: 'TournamentProjectsResponse' - getTournamentById: 'Tournament' - getTournamentToRegister: 'Tournament' - getTrendingPosts: 'Post' - hottestProjects: 'Project' - me: 'MyProfile' - newProjects: 'Project' - officialTags: 'Tag' - popularTags: 'Tag' - profile: 'User' - projectsByCategory: 'Project' - searchProjects: 'Project' - searchUsers: 'User' - similarMakers: 'User' - similarProjects: 'Project' - tournamentParticipationInfo: 'ParticipationInfo' - } - Question: { // field return type name - author: 'Author' - body: 'String' - createdAt: 'Date' - excerpt: 'String' - id: 'Int' - is_published: 'Boolean' - tags: 'Tag' - title: 'String' - type: 'String' - updatedAt: 'Date' - votes_count: 'Int' - } - Story: { // field return type name - author: 'Author' - body: 'String' - comments: 'PostComment' - comments_count: 'Int' - cover_image: 'String' - createdAt: 'Date' - excerpt: 'String' - id: 'Int' - is_published: 'Boolean' - project: 'Project' - tags: 'Tag' - title: 'String' - type: 'String' - updatedAt: 'Date' - votes_count: 'Int' - } - Tag: { // field return type name - description: 'String' - icon: 'String' - id: 'Int' - isOfficial: 'Boolean' - title: 'String' - } - Tournament: { // field return type name - cover_image: 'String' - description: 'String' - end_date: 'Date' - events: 'TournamentEvent' - events_count: 'Int' - faqs: 'TournamentFAQ' - id: 'Int' - judges: 'TournamentJudge' - location: 'String' - makers_count: 'Int' - prizes: 'TournamentPrize' - projects_count: 'Int' - start_date: 'Date' - thumbnail_image: 'String' - title: 'String' - website: 'String' - } - TournamentEvent: { // field return type name - description: 'String' - ends_at: 'Date' - id: 'Int' - image: 'String' - links: 'String' - location: 'String' - starts_at: 'Date' - title: 'String' - type: 'TournamentEventTypeEnum' - website: 'String' - } - TournamentFAQ: { // field return type name - answer: 'String' - question: 'String' - } - TournamentJudge: { // field return type name - avatar: 'String' - company: 'String' - name: 'String' - } - TournamentMakersResponse: { // field return type name - hasNext: 'Boolean' - hasPrev: 'Boolean' - makers: 'TournamentParticipant' - } - TournamentParticipant: { // field return type name - hacking_status: 'TournamentMakerHackingStatusEnum' - is_registered: 'Boolean' - user: 'User' - } - TournamentPrize: { // field return type name - amount: 'String' - image: 'String' - title: 'String' - } - TournamentProjectsResponse: { // field return type name - hasNext: 'Boolean' - hasPrev: 'Boolean' - projects: 'Project' - } - User: { // field return type name - avatar: 'String' - bio: 'String' - discord: 'String' - github: 'String' - id: 'Int' - in_tournament: 'Boolean' - jobTitle: 'String' - join_date: 'Date' - lightning_address: 'String' - linkedin: 'String' - location: 'String' - name: 'String' - projects: 'Project' - role: 'String' - roles: 'MakerRole' - similar_makers: 'User' - skills: 'MakerSkill' - stories: 'Story' - tournaments: 'Tournament' - twitter: 'String' - website: 'String' - } - Vote: { // field return type name - amount_in_sat: 'Int' - id: 'Int' - item_id: 'Int' - item_type: 'VOTE_ITEM_TYPE' - paid: 'Boolean' - payment_hash: 'String' - payment_request: 'String' - } - WalletKey: { // field return type name - createdAt: 'Date' - is_current: 'Boolean' - key: 'String' - name: 'String' - } - BaseUser: { // field return type name - avatar: 'String' - bio: 'String' - discord: 'String' - github: 'String' - id: 'Int' - in_tournament: 'Boolean' - jobTitle: 'String' - join_date: 'Date' - lightning_address: 'String' - linkedin: 'String' - location: 'String' - name: 'String' - projects: 'Project' - role: 'String' - roles: 'MakerRole' - similar_makers: 'User' - skills: 'MakerSkill' - stories: 'Story' - tournaments: 'Tournament' - twitter: 'String' - website: 'String' - } - PostBase: { // field return type name - body: 'String' - createdAt: 'Date' - excerpt: 'String' - id: 'Int' - is_published: 'Boolean' - title: 'String' - updatedAt: 'Date' - votes_count: 'Int' - } -} - -export interface NexusGenArgTypes { - Mutation: { - confirmDonation: { // args - payment_request: string; // String! - preimage: string; // String! - } - confirmVote: { // args - payment_request: string; // String! - preimage: string; // String! - } - createProject: { // args - input?: NexusGenInputs['CreateProjectInput'] | null; // CreateProjectInput - } - createStory: { // args - data?: NexusGenInputs['StoryInputType'] | null; // StoryInputType - } - deleteProject: { // args - id: number; // Int! - } - deleteStory: { // args - id: number; // Int! - } - donate: { // args - amount_in_sat: number; // Int! - } - registerInTournament: { // args - data?: NexusGenInputs['RegisterInTournamentInput'] | null; // RegisterInTournamentInput - tournament_id: number; // Int! - } - updateProfileDetails: { // args - data?: NexusGenInputs['ProfileDetailsInput'] | null; // ProfileDetailsInput - } - updateProfileRoles: { // args - data?: NexusGenInputs['ProfileRolesInput'] | null; // ProfileRolesInput - } - updateProject: { // args - input?: NexusGenInputs['UpdateProjectInput'] | null; // UpdateProjectInput - } - updateTournamentRegistration: { // args - data?: NexusGenInputs['UpdateTournamentRegistrationInput'] | null; // UpdateTournamentRegistrationInput - tournament_id: number; // Int! - } - updateUserPreferences: { // args - userKeys?: NexusGenInputs['UserKeyInputType'][] | null; // [UserKeyInputType!] - } - vote: { // args - amount_in_sat: number; // Int! - item_id: number; // Int! - item_type: NexusGenEnums['VOTE_ITEM_TYPE']; // VOTE_ITEM_TYPE! - } - } - MyProfile: { - in_tournament: { // args - id: number; // Int! - } - } - Query: { - allProjects: { // args - skip?: number | null; // Int - take: number | null; // Int - } - checkValidProjectHashtag: { // args - hashtag: string; // String! - projectId?: number | null; // Int - } - getAllHackathons: { // args - sortBy?: string | null; // String - tag?: number | null; // Int - } - getCategory: { // args - id: number; // Int! - } - getFeed: { // args - skip?: number | null; // Int - sortBy?: string | null; // String - tag?: number | null; // Int - take: number | null; // Int - } - getLnurlDetailsForProject: { // args - project_id: number; // Int! - } - getMakersInTournament: { // args - openToConnect?: boolean | null; // Boolean - roleId?: number | null; // Int - search?: string | null; // String - skip?: number | null; // Int - take: number | null; // Int - tournamentId: number; // Int! - } - getMyDrafts: { // args - type: NexusGenEnums['POST_TYPE']; // POST_TYPE! - } - getPostById: { // args - id: number; // Int! - type: NexusGenEnums['POST_TYPE']; // POST_TYPE! - } - getProject: { // args - id?: number | null; // Int - tag?: string | null; // String - } - getProjectsInTournament: { // args - roleId?: number | null; // Int - search?: string | null; // String - skip?: number | null; // Int - take: number | null; // Int - tournamentId: number; // Int! - } - getTournamentById: { // args - id: number; // Int! - } - hottestProjects: { // args - skip?: number | null; // Int - take: number | null; // Int - } - newProjects: { // args - skip?: number | null; // Int - take: number | null; // Int - } - profile: { // args - id: number; // Int! - } - projectsByCategory: { // args - category_id: number; // Int! - skip?: number | null; // Int - take: number | null; // Int - } - searchProjects: { // args - search: string; // String! - skip?: number | null; // Int - take: number | null; // Int - } - searchUsers: { // args - value: string; // String! - } - similarMakers: { // args - id: number; // Int! - } - similarProjects: { // args - id: number; // Int! - } - tournamentParticipationInfo: { // args - tournamentId: number; // Int! - } - } - User: { - in_tournament: { // args - id: number; // Int! - } - } - BaseUser: { - in_tournament: { // args - id: number; // Int! - } - } -} - -export interface NexusGenAbstractTypeMembers { - Post: "Bounty" | "Question" | "Story" - BaseUser: "MyProfile" | "User" - PostBase: "Bounty" | "Question" | "Story" -} - -export interface NexusGenTypeInterfaces { - Bounty: "PostBase" - MyProfile: "BaseUser" - Question: "PostBase" - Story: "PostBase" - User: "BaseUser" -} - -export type NexusGenObjectNames = keyof NexusGenObjects; - -export type NexusGenInputNames = keyof NexusGenInputs; - -export type NexusGenEnumNames = keyof NexusGenEnums; - -export type NexusGenInterfaceNames = keyof NexusGenInterfaces; - -export type NexusGenScalarNames = keyof NexusGenScalars; - -export type NexusGenUnionNames = keyof NexusGenUnions; - -export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never; - -export type NexusGenAbstractsUsingStrategyResolveType = "BaseUser" | "Post" | "PostBase"; - -export type NexusGenFeaturesConfig = { - abstractTypeStrategies: { - isTypeOf: false - resolveType: true - __typename: false - } -} - -export interface NexusGenTypes { - context: any; - inputTypes: NexusGenInputs; - rootTypes: NexusGenRootTypes; - inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars; - argTypes: NexusGenArgTypes; - fieldTypes: NexusGenFieldTypes; - fieldTypeNames: NexusGenFieldTypeNames; - allTypes: NexusGenAllTypes; - typeInterfaces: NexusGenTypeInterfaces; - objectNames: NexusGenObjectNames; - inputNames: NexusGenInputNames; - enumNames: NexusGenEnumNames; - interfaceNames: NexusGenInterfaceNames; - scalarNames: NexusGenScalarNames; - unionNames: NexusGenUnionNames; - allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames']; - allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames']; - allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes'] - abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames']; - abstractTypeMembers: NexusGenAbstractTypeMembers; - objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf; - abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType; - features: NexusGenFeaturesConfig; -} - - -declare global { - interface NexusGenPluginTypeConfig { - } - interface NexusGenPluginInputTypeConfig { - } - interface NexusGenPluginFieldConfig { - } - interface NexusGenPluginInputFieldConfig { - } - interface NexusGenPluginSchemaConfig { - } - interface NexusGenPluginArgConfig { - } -} \ No newline at end of file diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql deleted file mode 100644 index 60ac7cc..0000000 --- a/api/functions/graphql/schema.graphql +++ /dev/null @@ -1,602 +0,0 @@ -### This file was generated by Nexus Schema -### Do not make changes to this file directly - - -type Author { - avatar: String! - id: Int! - join_date: Date! - lightning_address: String - name: String! -} - -type Award { - id: Int! - image: String! - project: Project! - title: String! - url: String! -} - -interface BaseUser { - avatar: String! - bio: String - discord: String - github: String - id: Int! - in_tournament(id: Int!): Boolean! - jobTitle: String - join_date: Date! - lightning_address: String - linkedin: String - location: String - name: String! - projects: [Project!]! - role: String - roles: [MakerRole!]! - similar_makers: [User!]! - skills: [MakerSkill!]! - stories: [Story!]! - tournaments: [Tournament!]! - twitter: String - website: String -} - -type Bounty implements PostBase { - applicants_count: Int! - applications: [BountyApplication!]! - author: Author! - body: String! - cover_image: String - createdAt: Date! - deadline: String! - excerpt: String! - id: Int! - is_published: Boolean - reward_amount: Int! - tags: [Tag!]! - title: String! - type: String! - updatedAt: Date! - votes_count: Int! -} - -type BountyApplication { - author: Author! - date: String! - id: Int! - workplan: String! -} - -type Capability { - icon: String! - id: Int! - title: String! -} - -type Category { - apps_count: Int! - cover_image: String - icon: String - id: Int! - project: [Project!]! - title: String! - votes_sum: Int! -} - -input CreateProjectInput { - capabilities: [Int!]! - category_id: Int! - cover_image: ImageInput! - description: String! - discord: String - github: String - hashtag: String! - id: Int - launch_status: ProjectLaunchStatusEnum! - lightning_address: String - members: [TeamMemberInput!]! - recruit_roles: [Int!]! - screenshots: [ImageInput!]! - slack: String - tagline: String! - telegram: String - thumbnail_image: ImageInput! - title: String! - tournaments: [Int!]! - twitter: String - website: String! -} - -type CreateProjectResponse { - project: Project! -} - -"""Date custom scalar type""" -scalar Date - -type Donation { - amount: Int! - by: User - createdAt: Date! - id: Int! - paid: Boolean! - payment_hash: String! - payment_request: String! -} - -type DonationsStats { - applications: String! - donations: String! - prizes: String! - touranments: String! -} - -type GenericMakerRole { - icon: String! - id: Int! - title: String! -} - -type Hackathon { - cover_image: String! - description: String! - end_date: Date! - id: Int! - location: String! - start_date: Date! - tags: [Tag!]! - title: String! - website: String! -} - -input ImageInput { - id: String - name: String - url: String! -} - -type LnurlDetails { - commentAllowed: Int - maxSendable: Int - metadata: String - minSendable: Int -} - -type MakerRole { - icon: String! - id: Int! - level: RoleLevelEnum! - title: String! -} - -input MakerRoleInput { - id: Int! - level: RoleLevelEnum! -} - -type MakerSkill { - id: Int! - title: String! -} - -input MakerSkillInput { - id: Int! -} - -type Mutation { - confirmDonation(payment_request: String!, preimage: String!): Donation! - confirmVote(payment_request: String!, preimage: String!): Vote! - createProject(input: CreateProjectInput): CreateProjectResponse - createStory(data: StoryInputType): Story - deleteProject(id: Int!): Project - deleteStory(id: Int!): Story - donate(amount_in_sat: Int!): Donation! - registerInTournament(data: RegisterInTournamentInput, tournament_id: Int!): User - updateProfileDetails(data: ProfileDetailsInput): MyProfile - updateProfileRoles(data: ProfileRolesInput): MyProfile - updateProject(input: UpdateProjectInput): CreateProjectResponse - updateTournamentRegistration(data: UpdateTournamentRegistrationInput, tournament_id: Int!): ParticipationInfo - updateUserPreferences(userKeys: [UserKeyInputType!]): MyProfile! - vote(amount_in_sat: Int!, item_id: Int!, item_type: VOTE_ITEM_TYPE!): Vote! -} - -type MyProfile implements BaseUser { - avatar: String! - bio: String - discord: String - email: String - github: String - id: Int! - in_tournament(id: Int!): Boolean! - jobTitle: String - join_date: Date! - lightning_address: String - linkedin: String - location: String - name: String! - nostr_prv_key: String - nostr_pub_key: String - projects: [Project!]! - role: String - roles: [MakerRole!]! - similar_makers: [User!]! - skills: [MakerSkill!]! - stories: [Story!]! - tournaments: [Tournament!]! - twitter: String - walletsKeys: [WalletKey!]! - website: String -} - -enum POST_TYPE { - Bounty - Question - Story -} - -type ParticipationInfo { - createdAt: Date! - email: String! - hacking_status: TournamentMakerHackingStatusEnum! -} - -union Post = Bounty | Question | Story - -interface PostBase { - body: String! - createdAt: Date! - excerpt: String! - id: Int! - is_published: Boolean - title: String! - updatedAt: Date! - votes_count: Int! -} - -type PostComment { - author: Author! - body: String! - created_at: Date! - id: Int! - parentId: Int - votes_count: Int! -} - -input ProfileDetailsInput { - avatar: ImageInput - bio: String - discord: String - email: String - github: String - jobTitle: String - lightning_address: String - linkedin: String - location: String - name: String - twitter: String - website: String -} - -input ProfileRolesInput { - roles: [MakerRoleInput!]! - skills: [MakerSkillInput!]! -} - -type Project { - awards: [Award!]! - capabilities: [Capability!]! - category: Category! - cover_image: String! - description: String! - discord: String - github: String - hashtag: String! - id: Int! - launch_status: ProjectLaunchStatusEnum! - lightning_address: String - lnurl_callback_url: String - members: [ProjectMember!]! - permissions: [ProjectPermissionEnum!]! - recruit_roles: [MakerRole!]! - screenshots: [String!]! - slack: String - stories: [Story!]! - tagline: String! - tags: [Tag!]! - telegram: String - thumbnail_image: String! - title: String! - tournaments: [Tournament!]! - twitter: String - votes_count: Int! - website: String! -} - -enum ProjectLaunchStatusEnum { - Launched - WIP -} - -type ProjectMember { - role: TEAM_MEMBER_ROLE! - user: User! -} - -enum ProjectPermissionEnum { - DeleteProject - UpdateAdmins - UpdateInfo - UpdateMembers -} - -type Query { - allCategories: [Category!]! - allProjects(skip: Int = 0, take: Int = 50): [Project!]! - checkValidProjectHashtag(hashtag: String!, projectId: Int): Boolean! - getAllCapabilities: [Capability!]! - getAllHackathons(sortBy: String, tag: Int): [Hackathon!]! - getAllMakersRoles: [GenericMakerRole!]! - getAllMakersSkills: [MakerSkill!]! - getCategory(id: Int!): Category! - getDonationsStats: DonationsStats! - getFeed(skip: Int = 0, sortBy: String, tag: Int = 0, take: Int = 10): [Post!]! - getLnurlDetailsForProject(project_id: Int!): LnurlDetails! - getMakersInTournament(openToConnect: Boolean, roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentMakersResponse! - getMyDrafts(type: POST_TYPE!): [Post!]! - getPostById(id: Int!, type: POST_TYPE!): Post! - getProject(id: Int, tag: String): Project! - getProjectsInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentProjectsResponse! - getTournamentById(id: Int!): Tournament! - getTournamentToRegister: [Tournament!]! - getTrendingPosts: [Post!]! - hottestProjects(skip: Int = 0, take: Int = 50): [Project!]! - me: MyProfile - newProjects(skip: Int = 0, take: Int = 50): [Project!]! - officialTags: [Tag!]! - popularTags: [Tag!]! - profile(id: Int!): User - projectsByCategory(category_id: Int!, skip: Int = 0, take: Int = 10): [Project!]! - searchProjects(search: String!, skip: Int = 0, take: Int = 50): [Project!]! - searchUsers(value: String!): [User!]! - similarMakers(id: Int!): [User!]! - similarProjects(id: Int!): [Project!]! - tournamentParticipationInfo(tournamentId: Int!): ParticipationInfo -} - -type Question implements PostBase { - author: Author! - body: String! - createdAt: Date! - excerpt: String! - id: Int! - is_published: Boolean - tags: [Tag!]! - title: String! - type: String! - updatedAt: Date! - votes_count: Int! -} - -input RegisterInTournamentInput { - email: String! - hacking_status: TournamentMakerHackingStatusEnum! -} - -enum RoleLevelEnum { - Advanced - Beginner - Hobbyist - Intermediate - Pro -} - -type Story implements PostBase { - author: Author! - body: String! - comments: [PostComment!]! - comments_count: Int! - cover_image: String - createdAt: Date! - excerpt: String! - id: Int! - is_published: Boolean - project: Project - tags: [Tag!]! - title: String! - type: String! - updatedAt: Date! - votes_count: Int! -} - -input StoryInputType { - body: String! - cover_image: ImageInput - id: Int - is_published: Boolean - project_id: Int - tags: [String!]! - title: String! -} - -enum TEAM_MEMBER_ROLE { - Admin - Maker - Owner -} - -type Tag { - description: String - icon: String - id: Int! - isOfficial: Boolean - title: String! -} - -input TeamMemberInput { - id: Int! - role: TEAM_MEMBER_ROLE! -} - -type Tournament { - cover_image: String! - description: String! - end_date: Date! - events: [TournamentEvent!]! - events_count: Int! - faqs: [TournamentFAQ!]! - id: Int! - judges: [TournamentJudge!]! - location: String! - makers_count: Int! - prizes: [TournamentPrize!]! - projects_count: Int! - start_date: Date! - thumbnail_image: String! - title: String! - website: String! -} - -type TournamentEvent { - description: String! - ends_at: Date! - id: Int! - image: String! - links: [String!]! - location: String! - starts_at: Date! - title: String! - type: TournamentEventTypeEnum! - website: String! -} - -enum TournamentEventTypeEnum { - IRLMeetup - OnlineMeetup - TwitterSpace - Workshop -} - -type TournamentFAQ { - answer: String! - question: String! -} - -type TournamentJudge { - avatar: String! - company: String! - name: String! -} - -enum TournamentMakerHackingStatusEnum { - OpenToConnect - Solo -} - -type TournamentMakersResponse { - hasNext: Boolean - hasPrev: Boolean - makers: [TournamentParticipant!]! -} - -type TournamentParticipant { - hacking_status: TournamentMakerHackingStatusEnum! - is_registered: Boolean - user: User! -} - -type TournamentPrize { - amount: String! - image: String! - title: String! -} - -type TournamentProjectsResponse { - hasNext: Boolean - hasPrev: Boolean - projects: [Project!]! -} - -input UpdateProjectInput { - capabilities: [Int!]! - category_id: Int! - cover_image: ImageInput! - description: String! - discord: String - github: String - hashtag: String! - id: Int - launch_status: ProjectLaunchStatusEnum! - lightning_address: String - members: [TeamMemberInput!]! - recruit_roles: [Int!]! - screenshots: [ImageInput!]! - slack: String - tagline: String! - telegram: String - thumbnail_image: ImageInput! - title: String! - tournaments: [Int!]! - twitter: String - website: String! -} - -input UpdateTournamentRegistrationInput { - email: String - hacking_status: TournamentMakerHackingStatusEnum -} - -type User implements BaseUser { - avatar: String! - bio: String - discord: String - github: String - id: Int! - in_tournament(id: Int!): Boolean! - jobTitle: String - join_date: Date! - lightning_address: String - linkedin: String - location: String - name: String! - projects: [Project!]! - role: String - roles: [MakerRole!]! - similar_makers: [User!]! - skills: [MakerSkill!]! - stories: [Story!]! - tournaments: [Tournament!]! - twitter: String - website: String -} - -input UserKeyInputType { - key: String! - name: String! -} - -enum VOTE_ITEM_TYPE { - Bounty - PostComment - Project - Question - Story - User -} - -type Vote { - amount_in_sat: Int! - id: Int! - item_id: Int! - item_type: VOTE_ITEM_TYPE! - paid: Boolean! - payment_hash: String! - payment_request: String! -} - -type WalletKey { - createdAt: Date! - is_current: Boolean! - key: String! - name: String! -} \ No newline at end of file diff --git a/api/functions/graphql/schema/index.js b/api/functions/graphql/schema/index.js deleted file mode 100644 index 4b81296..0000000 --- a/api/functions/graphql/schema/index.js +++ /dev/null @@ -1,35 +0,0 @@ -const { makeSchema } = require('nexus'); -const { join } = require('path'); -const types = require('../types') - - -const schema = makeSchema({ - types: types, - outputs: { - typegen: join(__dirname, '..', 'nexus-typegen.ts'), - schema: join(__dirname, '..', 'schema.graphql'), - }, -}) - -module.exports = schema; - -// const { gql } = require("apollo-server-lambda"); -// const projectSchema = require('./project') -// const categorySchema = require('./category') -// const voteSchema = require('./vote') - -// const linkSchema = gql` -// type Query { -// _: Boolean -// } - -// type Mutation { -// _: Boolean -// } - -// type Subscription { -// _: Boolean -// } -// `; - -// module.exports = [linkSchema, categorySchema, projectSchema, voteSchema]; \ No newline at end of file diff --git a/api/functions/graphql/types/_scalars.js b/api/functions/graphql/types/_scalars.js deleted file mode 100644 index ec7c171..0000000 --- a/api/functions/graphql/types/_scalars.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Kind } = require("graphql") -const { scalarType } = require("nexus") - -const DateScalar = scalarType({ - name: 'Date', - asNexusMethod: 'date', - description: 'Date custom scalar type', - parseValue(value) { - return new Date(value) - }, - serialize(value) { - return value.toISOString() - }, - parseLiteral(ast) { - if (ast.kind === Kind.INT) { - return new Date(ast.value) - } - return null - }, -}) - -module.exports = { - DateScalar -} \ No newline at end of file diff --git a/api/functions/graphql/types/category.js b/api/functions/graphql/types/category.js deleted file mode 100644 index 4f3f5b8..0000000 --- a/api/functions/graphql/types/category.js +++ /dev/null @@ -1,95 +0,0 @@ -const { - intArg, - objectType, - extendType, - nonNull, -} = require('nexus'); -const { prisma } = require('../../../prisma'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); - - -const Category = objectType({ - name: 'Category', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.string('cover_image', { - async resolve(parent) { - return prisma.category.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl) - } - }); - t.string('icon'); - - - t.nonNull.int('votes_sum', { - async resolve(parent) { - const projects = await prisma.category.findUnique({ where: { id: parent.id } }).project() - return projects.reduce((total, project) => total + project.votes_count, 0); - } - }); - t.nonNull.int('apps_count', { - async resolve(parent) { - const projects = await prisma.category.findUnique({ where: { id: parent.id } }).project(); - return projects.length; - - } - }); - - t.nonNull.list.nonNull.field('project', { - type: "Project", - resolve: (parent) => { - return parent.project ?? prisma.category.findUnique({ - where: { id: parent.id } - }).project() - } - }) - } -}) - -const allCategoriesQuery = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('allCategories', { - type: "Category", - resolve: async () => { - const categories = await prisma.category.findMany({ - include: { - _count: { - select: { - project: true - } - } - } - }) - categories.sort((c1, c2) => c2._count.project - c1._count.project) - return categories; - } - }) - } -}) - -const getCategory = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getCategory', { - type: "Category", - args: { - id: nonNull(intArg()) - }, - resolve(parent, { id }) { - return prisma.category.findUnique({ - where: { id } - }) - } - }) - } -}) - -module.exports = { - // Types - Category, - - // Queries - allCategoriesQuery, - getCategory -} \ No newline at end of file diff --git a/api/functions/graphql/types/donation.js b/api/functions/graphql/types/donation.js deleted file mode 100644 index 4cc8171..0000000 --- a/api/functions/graphql/types/donation.js +++ /dev/null @@ -1,154 +0,0 @@ -const { createHash } = require('crypto'); -const { parsePaymentRequest } = require('invoices'); -const { - intArg, - objectType, - stringArg, - extendType, - nonNull, -} = require('nexus'); -const { prisma } = require('../../../prisma'); -const { CONSTS } = require('../../../utils'); -const { getPaymetRequestForItem, hexToUint8Array } = require('./helpers'); - - - -const Donation = objectType({ - name: 'Donation', - definition(t) { - t.nonNull.int('id'); - t.nonNull.int('amount'); - t.nonNull.date('createdAt'); - t.nonNull.string('payment_request'); - t.nonNull.string('payment_hash'); - t.nonNull.boolean('paid'); - - t.field('by', { - type: 'User', - resolve: (parent) => { - return prisma.donation.findUnique({ where: { id: parent.id } }).donor(); - } - }); - } -}) - - - -const donateMutation = extendType({ - type: "Mutation", - definition(t) { - t.nonNull.field('donate', { - type: "Donation", - args: { - amount_in_sat: nonNull(intArg()) - }, - resolve: async (_, args) => { - - const { amount_in_sat } = args; - const lightning_address = CONSTS.BOLT_FUN_LIGHTNING_ADDRESS; - const pr = await getPaymetRequestForItem(lightning_address, args.amount_in_sat); - const invoice = parsePaymentRequest({ request: pr }); - - return prisma.donation.create({ - data: { - amount: amount_in_sat, - payment_request: pr, - payment_hash: invoice.id, - } - }); - } - }) - } -}) - -const confirmDonateMutation = extendType({ - type: "Mutation", - definition(t) { - t.nonNull.field('confirmDonation', { - type: "Donation", - args: { - payment_request: nonNull(stringArg()), - preimage: nonNull(stringArg()) - }, - resolve: async (_, args) => { - const paymentHash = createHash("sha256") - .update(hexToUint8Array(args.preimage)) - .digest("hex"); - // look for a vote for the payment request and the calculated payment hash - const donation = await prisma.donation.findFirst({ - where: { - payment_request: args.payment_request, - payment_hash: paymentHash, - }, - }); - - // if we find a donation it means the preimage is correct and we update the donation and mark it as paid - // can we write this nicer? - if (donation) { - - // return the current donation - return prisma.donation.update({ - where: { id: donation.id }, - data: { - paid: true, - preimage: args.preimage, - } - }); - } else { - throw new Error("Invalid preimage"); - } - } - }) - } -}) - - -const DonationsStats = objectType({ - name: 'DonationsStats', - definition(t) { - t.nonNull.string("prizes"); - t.nonNull.string("touranments"); - t.nonNull.string("donations"); - t.nonNull.string("applications"); - }, -}) - -const getDonationsStats = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getDonationsStats', { - type: "DonationsStats", - async resolve() { - const [donations, applications] = await Promise.all([ - prisma.donation.aggregate({ - _sum: { - amount: true - }, - where: { - paid: true - } - }).then(d => d._sum.amount ?? 0), - prisma.project.count()]); - // #TODO add a measurement unit for prizes & donations (eg. $ or sats or BTC) - return { - prizes: '$5.2k', - touranments: 2, - donations, - applications - } - } - }) - } -}) - - - -module.exports = { - // Types - Donation, - DonationsStats, - // Queries - donateMutation, - confirmDonateMutation, - getDonationsStats, -} \ No newline at end of file diff --git a/api/functions/graphql/types/hackathon.js b/api/functions/graphql/types/hackathon.js deleted file mode 100644 index 6212b92..0000000 --- a/api/functions/graphql/types/hackathon.js +++ /dev/null @@ -1,89 +0,0 @@ -const { - intArg, - objectType, - stringArg, - extendType, - nonNull, -} = require('nexus'); -const { prisma } = require('../../../prisma'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); - - - -const Hackathon = objectType({ - name: 'Hackathon', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('description'); - t.nonNull.string('cover_image', { - async resolve(parent) { - return prisma.hackathon.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.date('start_date'); - t.nonNull.date('end_date'); - t.nonNull.string('location'); - t.nonNull.string('website'); - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => { - return prisma.hackathon.findUnique({ where: { id: parent.id } }).tags(); - } - }); - } -}) - -const getAllHackathons = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getAllHackathons', { - type: "Hackathon", - args: { - sortBy: stringArg(), - tag: intArg(), - }, - resolve(_, args) { - const { sortBy, tag } = args; - return prisma.hackathon.findMany({ - where: { - ...(sortBy === 'Upcoming' && { - start_date: { - gte: new Date(), - } - }), - ...(sortBy === 'Live' && { - start_date: { lte: new Date() }, - end_date: { gte: new Date() } - }), - ...(sortBy === 'Finished' && { - end_date: { - lt: new Date() - } - }), - - - - ...(tag && { - tags: { - some: { - id: tag - } - } - }) - }, - orderBy: { - start_date: "desc" - } - }) - } - }) - } -}) - -module.exports = { - // Types - Hackathon, - // Queries - getAllHackathons, -} \ No newline at end of file diff --git a/api/functions/graphql/types/helpers.js b/api/functions/graphql/types/helpers.js deleted file mode 100644 index 17c7f8c..0000000 --- a/api/functions/graphql/types/helpers.js +++ /dev/null @@ -1,86 +0,0 @@ -const { intArg } = require("nexus"); -const axios = require("axios"); - - -function hexToUint8Array(hexString) { - const match = hexString.match(/.{1,2}/g); - if (match) { - return new Uint8Array(match.map((byte) => parseInt(byte, 16))); - } -} - -// TODO: generaly validate LNURL responses -// get lnurl params -function getLnurlDetails(lnurl) { - return axios.get(lnurl); -} - -// parse lightning address and return a url that can be -// used in a request -function lightningAddressToLnurl(lightning_address) { - const [name, domain] = lightning_address.split("@"); - return `https://${domain}/.well-known/lnurlp/${name}`; -} - -// when pressing tip or selecting an amount. -// this is used for caching so the frontend doesnt -// have to make an additional http request to get -// the callback url for future visits -async function getLnurlCallbackUrl(lightning_address) { - return getLnurlDetails(lightningAddressToLnurl(lightning_address)).then( - (response) => { - return response.data.callback; - } - ); -} - - -async function getPaymetRequestForItem(lightning_address, amount_in_sat) { - // # NOTE: CACHING LNURL CALLBACK URLS + PARAMETERS - // LNURL flows have a lot of back and forth and can impact - // the load time for your application users. - // You may consider caching the callback url, or resolved - // parameters but be mindful of this. - // The LNURL service provider can change the callback url - // details or the paramters that is returned we must be - // careful when trying to optimise the amount of - // requests so be mindful of this when you are storing - // these items. - - const amount = amount_in_sat * 1000; // msats - let lnurlCallbackUrl = await getLnurlCallbackUrl(lightning_address); - return axios - .get(lnurlCallbackUrl, { params: { amount } }) - .then((prResponse) => { - return prResponse.data.pr; - }); -} - - - -const paginationArgs = (args) => { - const { take = 10, skip = 0 } = args ?? {} - return { - take: intArg({ default: take }), - skip: intArg({ default: skip }) - } -} - -const removeNulls = (obj) => { - let res = {}; - for (const key in obj) { - if (obj[key] != null) { - res[key] = obj[key]; - } - } - return res -} - -module.exports = { - getPaymetRequestForItem, - hexToUint8Array, - lightningAddressToLnurl, - getLnurlDetails, - paginationArgs, - removeNulls -} diff --git a/api/functions/graphql/types/index.js b/api/functions/graphql/types/index.js deleted file mode 100644 index 2c7ad75..0000000 --- a/api/functions/graphql/types/index.js +++ /dev/null @@ -1,25 +0,0 @@ -const scalars = require('./_scalars') -const misc = require('./misc') -const category = require('./category') -const project = require('./project') -const vote = require('./vote') -const post = require('./post') -const users = require('./users') -const hackathon = require('./hackathon') -const tournament = require('./tournament') -const donation = require('./donation') -const tag = require('./tag') - -module.exports = { - ...misc, - ...tag, - ...scalars, - ...category, - ...project, - ...vote, - ...post, - ...users, - ...hackathon, - ...tournament, - ...donation, -} \ No newline at end of file diff --git a/api/functions/graphql/types/misc.js b/api/functions/graphql/types/misc.js deleted file mode 100644 index 2fde16f..0000000 --- a/api/functions/graphql/types/misc.js +++ /dev/null @@ -1,19 +0,0 @@ -const { objectType, extendType, inputObjectType } = require("nexus"); -const { prisma } = require('../../../prisma'); - -const ImageInput = inputObjectType({ - name: 'ImageInput', - definition(t) { - t.string('id'); - t.string('name'); - t.nonNull.string('url'); - } -}); - - -module.exports = { - // Types - ImageInput, - - // Queries -} \ No newline at end of file diff --git a/api/functions/graphql/types/post.js b/api/functions/graphql/types/post.js deleted file mode 100644 index 62ac65a..0000000 --- a/api/functions/graphql/types/post.js +++ /dev/null @@ -1,698 +0,0 @@ -const { - intArg, - objectType, - extendType, - nonNull, - interfaceType, - unionType, - stringArg, - enumType, - arg, - inputObjectType, -} = require('nexus'); -const { paginationArgs } = require('./helpers'); -const { prisma } = require('../../../prisma'); -const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); -const { ApolloError } = require('apollo-server-lambda'); -const { marked } = require('marked'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); -const { ImageInput } = require('./misc'); -const { deleteImage } = require('../../../services/imageUpload.service'); -const { logError } = require('../../../utils/logger'); - - -const POST_TYPE = enumType({ - name: 'POST_TYPE', - members: ['Story', 'Bounty', 'Question'], -}); - -const asType = type => (obj) => { - if (Array.isArray(obj)) return obj.map(o => ({ ...o, type })) - return { ...obj, type } -} - -const asStoryType = asType('Story') -const asQuestionType = asType('Question') -const asBountyType = asType('Bounty') - - -const Author = objectType({ - name: 'Author', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('name'); - t.nonNull.string('avatar', { - async resolve(parent) { - return prisma.user.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.date('join_date'); - - t.string('lightning_address'); - } -}) - - - - -const PostBase = interfaceType({ - name: 'PostBase', - resolveType(item) { - return item.type - }, - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.date('createdAt'); - t.nonNull.date('updatedAt'); - t.nonNull.string('body'); - t.nonNull.string('excerpt'); - t.nonNull.int('votes_count'); - t.boolean('is_published'); - }, -}) - -const Story = objectType({ - name: 'Story', - definition(t) { - t.implements('PostBase'); - t.nonNull.string('type', { - resolve: () => t.typeName - }); - t.string('cover_image', { - async resolve(parent) { - return prisma.story.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.list.nonNull.field('comments', { - type: "PostComment", - resolve: (parent) => [] - }); - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => prisma.story.findUnique({ where: { id: parent.id } }).tags() - }); - t.nonNull.int('comments_count', { - resolve: async (parent) => { - const post = await prisma.story.findUnique({ - where: { id: parent.id }, - include: { - _count: { - select: { - comments: true - } - } - } - }) - return post._count.comments; - } - }); - t.nonNull.field('author', { - type: "Author", - resolve: (parent) => - prisma.story.findUnique({ where: { id: parent.id } }).user() - - }); - - t.field('project', { - type: "Project", - resolve(parent) { - return prisma.story.findUnique({ where: { id: parent.id } }).project(); - } - }) - - }, -}) - -const StoryInputType = inputObjectType({ - name: 'StoryInputType', - definition(t) { - t.int('id'); - t.nonNull.string('title'); - t.nonNull.string('body'); - t.field('cover_image', { - type: ImageInput - }) - t.nonNull.list.nonNull.string('tags'); - t.boolean('is_published') - t.int('project_id') - } -}) - - -const BountyApplication = objectType({ - name: 'BountyApplication', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('date'); - t.nonNull.string('workplan'); - t.nonNull.field('author', { - type: "Author" - }); - } -}) - -const Bounty = objectType({ - name: 'Bounty', - definition(t) { - t.implements('PostBase'); - t.nonNull.string('type', { - resolve: () => 'Bounty' - }); - t.string('cover_image'); - t.nonNull.string('deadline'); - t.nonNull.int('reward_amount'); - t.nonNull.int('applicants_count'); - t.nonNull.list.nonNull.field('applications', { - type: "BountyApplication" - }); - t.nonNull.field('author', { - type: "Author", - resolve: (parent) => { - return prisma.bounty.findUnique({ where: { id: parent.id } }).user(); - } - }); - - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => [] - }); - }, -}) - -const Question = objectType({ - name: 'Question', - definition(t) { - t.implements('PostBase'); - t.nonNull.string('type', { - resolve: () => 'Question', - - }); - - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => prisma.question.findUnique({ where: { id: parent.id } }).tags() - }); - - // t.nonNull.int('answers_count'); - // t.nonNull.list.nonNull.field('comments', { - // type: "PostComment", - // resolve: (parent) => { - // return prisma.question.findUnique({ where: { id: parent.id } }).comments(); - // } - // }); - - t.nonNull.field('author', { - type: "Author", - resolve: (parent) => { - return prisma.question.findUnique({ where: { id: parent.id } }).user(); - } - }); - }, -}) - -const PostComment = objectType({ - name: 'PostComment', - definition(t) { - t.nonNull.int('id'); - t.nonNull.date('created_at'); - t.nonNull.string('body'); - t.nonNull.field('author', { - type: "Author" - }); - t.int('parentId'); - t.nonNull.int('votes_count'); - } -}) - -const Post = unionType({ - name: 'Post', - definition(t) { - t.members('Story', 'Bounty', 'Question') - }, - resolveType: (item) => { - return item.type - }, -}) - - -const getFeed = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getFeed', { - type: "Post", - args: { - ...paginationArgs({ take: 10 }), - sortBy: stringArg(), // all, popular, trending, newest - tag: intArg({ - default: 0 - }) - }, - resolve(_, { take, skip, tag, sortBy, }) { - - - let orderBy = { createdAt: "desc" }; - - if (sortBy === 'popular') - orderBy = { votes_count: 'desc' }; - else if (sortBy === 'newest') - orderBy = { createdAt: "desc" }; - - return prisma.story.findMany({ - orderBy: orderBy, - where: { - ...(tag && { - tags: { - some: { - id: tag - } - }, - }), - is_published: true, - }, - skip, - take, - }).then(asStoryType) - } - }) - } -}) - - -const getTrendingPosts = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getTrendingPosts', { - type: "Post", - args: { - }, - resolve() { - const now = new Date(); - const lastWeekDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7) - return prisma.story.findMany({ - where: { - createdAt: { - gte: lastWeekDate - }, - is_published: true, - }, - orderBy: { votes_count: 'desc' }, - take: 5, - }).then(asStoryType) - } - }) - } -}) - - - -const getMyDrafts = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getMyDrafts', { - type: "Post", - args: { - type: arg({ - type: nonNull('POST_TYPE') - }) - }, - async resolve(parent, { type }, ctx) { - const user = await getUserByPubKey(ctx.userPubKey); - // Do some validation - if (!user) - throw new ApolloError("Not Authenticated"); - - if (type === 'Story') - return prisma.story.findMany({ - where: { - is_published: false, - user_id: user.id - }, - orderBy: { createdAt: 'desc' }, - }).then(asStoryType) - return [] - } - }) - } -}) - - -const getPostById = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getPostById', { - type: "Post", - args: { - id: nonNull(intArg()), - type: arg({ - type: nonNull('POST_TYPE') - }) - }, - resolve(_, { id, type }) { - if (type === 'Story') - return prisma.story.findUnique({ - where: { id } - }).then(asStoryType) - - if (type === 'Question') - return prisma.question.findUnique({ - where: { id } - }).then(asQuestionType) - return null - } - }) - } -}) - -const addCoverImage = async (providerImageId) => { - const newCoverImage = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: providerImageId - } - }) - - if (!newCoverImage) throw new ApolloError("New cover image not found") - - await prisma.hostedImage.update({ - where: { - id: newCoverImage.id - }, - data: { - is_used: true - } - }) - - return newCoverImage -} - -const getHostedImageIdsFromBody = async (body, oldBodyImagesIds = null) => { - let bodyImageIds = [] - - const regex = /(?:!\[(.*?)\]\((.*?)\))/g - let match; - while ((match = regex.exec(body))) { - const [, , value] = match - - // Useful for old external images in case of duplicates. We need to be sure we are targeting an image from the good story. - const where = oldBodyImagesIds ? { - AND: [ - { url: value }, - { id: { in: oldBodyImagesIds } } - ] - } : - { - url: value, - } - - const hostedImage = await prisma.hostedImage.findFirst({ - where - }) - if (hostedImage) { - bodyImageIds.push(hostedImage.id) - await prisma.hostedImage.update({ - where: { - id: hostedImage.id - }, - data: { - is_used: true - } - }) - } - } - return bodyImageIds -} - -const createStory = extendType({ - type: 'Mutation', - definition(t) { - t.field('createStory', { - type: 'Story', - args: { data: StoryInputType }, - async resolve(_root, args, ctx) { - const { id, title, body, project_id, cover_image, tags, is_published } = args.data; - const user = await getUserByPubKey(ctx.userPubKey); - - // Do some validation - if (!user) - throw new ApolloError("Not Authenticated"); - - let was_published = false; - - - // TODO: validate post data - - let coverImage = null - let bodyImageIds = [] - - - try { - if (id) { - const oldPost = await prisma.story.findFirst({ - where: { id }, - select: { - user_id: true, - is_published: true, - cover_image_id: true, - body_image_ids: true - } - }) - was_published = oldPost.is_published; - if (user.id !== oldPost.user_id) throw new ApolloError("Not post author") - - // Body images - bodyImageIds = await getHostedImageIdsFromBody(body, oldPost.body_image_ids) - - // Old cover image is found - if (oldPost.cover_image_id) { - const oldCoverImage = await prisma.hostedImage.findFirst({ - where: { - id: oldPost.cover_image_id - } - }) - - // New cover image - if (cover_image?.id && cover_image.id !== oldCoverImage?.provider_image_id) { - await deleteImage(oldCoverImage.id) - coverImage = await addCoverImage(cover_image.id) - } else { - coverImage = oldCoverImage - } - } else { - // No old image found and new cover image - if (cover_image?.id) { - coverImage = await addCoverImage(cover_image.id) - } - } - - // Remove unused body images - const unusedImagesIds = oldPost.body_image_ids.filter(x => !bodyImageIds.includes(x)); - unusedImagesIds.map(async i => await deleteImage(i)) - - } else { - // Body images - bodyImageIds = await getHostedImageIdsFromBody(body) - - // New story and new cover image - if (cover_image?.id) { - coverImage = await addCoverImage(cover_image.id) - } - } - - // Preprocess & insert - const htmlBody = marked.parse(body); - const excerpt = htmlBody - .replace(/<[^>]+>/g, '') - .slice(0, 120) - .replace(/&/g, "&") - .replace(/'/g, "'") - .replace(/"/g, '"') - ; - - - const coverImageRel = coverImage ? { - cover_image_rel: { - connect: - { - id: coverImage ? coverImage.id : null - } - } - } : {} - - if (id) { - await prisma.story.update({ - where: { id }, - data: { - tags: { - set: [] - }, - } - }); - - return prisma.story.update({ - where: { id }, - data: { - title, - body, - cover_image: '', - excerpt, - is_published: was_published || is_published, - project: project_id ? { - connect: { - id: project_id, - }, - } : { - disconnect: true - }, - tags: { - connectOrCreate: - tags.map(tag => { - tag = tag.toLowerCase().trim(); - return { - where: { - title: tag, - }, - create: { - title: tag - } - } - }) - }, - body_image_ids: bodyImageIds, - ...coverImageRel - } - }) - .catch(error => { - logError(error) - throw new ApolloError("Unexpected error happened...") - }) - } - - return prisma.story.create({ - data: { - title, - body, - cover_image: '', - excerpt, - is_published, - tags: { - connectOrCreate: - tags.map(tag => { - tag = tag.toLowerCase().trim(); - return { - where: { - title: tag, - }, - create: { - title: tag - } - } - }) - }, - project: { - connect: { - id: project_id, - } - }, - user: { - connect: { - id: user.id, - } - }, - body_image_ids: bodyImageIds, - ...coverImageRel - } - }).catch(error => { - logError(error) - throw new ApolloError("Unexpected error happened...") - }) - - - } catch (error) { - logError(error) - throw new ApolloError("Unexpected error happened...") - } - } - }) - }, -}) - -const deleteStory = extendType({ - type: 'Mutation', - definition(t) { - t.field('deleteStory', { - type: 'Story', - args: { id: nonNull(intArg()) }, - async resolve(_root, args, ctx) { - const { id } = args; - const user = await getUserByPubKey(ctx.userPubKey); - // Do some validation - if (!user) - throw new ApolloError("Not Authenticated"); - - - const oldPost = await prisma.story.findFirst({ - where: { id }, - select: { - user_id: true, - body_image_ids: true, - cover_image_id: true - } - }) - if (user.id !== oldPost.user_id) - throw new ApolloError("Not post author") - - const deletedPost = await prisma.story.delete({ - where: { - id - } - }) - - const coverImage = await prisma.hostedImage.findMany({ - where: { - OR: [ - { id: oldPost.cover_image_id }, - { - id: { - in: oldPost.body_image_ids - } - } - ] - }, - select: { - id: true, - provider_image_id: true - } - }) - coverImage.map(async i => await deleteImage(i.id)) - - return deletedPost - } - }) - }, -}) - - - - -module.exports = { - // Types - POST_TYPE, - Author, - PostBase, - BountyApplication, - Bounty, - Story, - StoryInputType, - Question, - PostComment, - Post, - // Queries - getFeed, - getPostById, - getTrendingPosts, - getMyDrafts, - - // Mutations - createStory, - deleteStory, -} \ No newline at end of file diff --git a/api/functions/graphql/types/project.js b/api/functions/graphql/types/project.js deleted file mode 100644 index 121540b..0000000 --- a/api/functions/graphql/types/project.js +++ /dev/null @@ -1,1136 +0,0 @@ -const { ApolloError } = require('apollo-server-lambda'); -const { - intArg, - objectType, - stringArg, - extendType, - nonNull, - enumType, - inputObjectType, -} = require('nexus'); -const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); -const { prisma } = require('../../../prisma'); -const { deleteImage } = require('../../../services/imageUpload.service'); -const { logError } = require('../../../utils/logger'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); -const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers'); -const { ImageInput } = require('./misc'); -const { Story } = require('./post'); -const { MakerRole } = require('./users'); - - - -const Project = objectType({ - name: 'Project', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('tagline'); - t.nonNull.string('website'); - t.nonNull.string('description'); - t.nonNull.string('hashtag'); - t.nonNull.string('cover_image', { - async resolve(parent) { - return prisma.project.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.string('thumbnail_image', { - async resolve(parent) { - return prisma.project.findUnique({ where: { id: parent.id } }).thumbnail_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.field('launch_status', { - type: ProjectLaunchStatusEnum - }); - t.string('twitter'); - t.string('discord'); - t.string('github'); - t.string('slack'); - t.string('telegram'); - t.nonNull.list.nonNull.string('screenshots', { - async resolve(parent) { - if (!parent.screenshots_ids) return null - const imgObject = await prisma.hostedImage.findMany({ - where: { - id: { in: parent.screenshots_ids } - } - }); - - return imgObject.map(img => { - return resolveImgObjectToUrl(img); - }); - } - }); - t.string('lightning_address'); - t.string('lnurl_callback_url'); - t.nonNull.int('votes_count'); - - t.nonNull.field('category', { - type: "Category", - resolve: (parent) => { - return prisma.project.findUnique({ where: { id: parent.id } }).category(); - } - }); - - t.nonNull.list.nonNull.field('awards', { - type: "Award", - resolve: (parent) => { - return prisma.project.findUnique({ where: { id: parent.id } }).awards(); - } - }); - - t.nonNull.list.nonNull.field('tags', { - type: "Tag", - resolve: (parent) => { - return prisma.project.findUnique({ where: { id: parent.id } }).tags(); - } - }) - - t.nonNull.list.nonNull.field('members', { - type: ProjectMember, - resolve: (parent) => { - return prisma.projectMember.findMany({ - where: { - projectId: parent.id - }, - include: { - user: true - } - }) - } - }) - - - t.nonNull.list.nonNull.field('tournaments', { - type: "Tournament", - resolve: (parent) => { - return prisma.tournamentProject.findMany({ - where: { project_id: parent.id }, - include: { - tournament: true - } - }).then(res => res.map(item => item.tournament)) - } - }) - - t.nonNull.list.nonNull.field('stories', { - type: Story, - resolve: (parent) => { - return prisma.story.findMany({ - where: { - project_id: parent.id, - }, - orderBy: { - createdAt: "desc" - }, - }) - } - }) - - t.nonNull.list.nonNull.field('capabilities', { - type: Capability, - resolve: async (parent) => { - return prisma.project.findUnique({ where: { id: parent.id } }).capabilities() - } - }) - - t.nonNull.list.nonNull.field('recruit_roles', { - type: MakerRole, - resolve: async (parent) => { - const data = await prisma.project.findUnique({ - where: { - id: parent.id - }, - select: { - recruit_roles: { - select: { - role: true, - level: true - } - }, - } - }) - return data.recruit_roles.map(data => { - return ({ ...data.role, level: data.level }) - }) - } - }) - - t.nonNull.list.nonNull.field('permissions', { - type: ProjectPermissionEnum, - resolve: async (parent, _, ctx) => { - const user = await getUserByPubKey(ctx.userPubKey) - if (!user) return []; - - const role = (await prisma.projectMember.findUnique({ where: { projectId_userId: { projectId: parent.id, userId: user.id } } }))?.role; - - if (!role) return []; - - if (role === ROLE_ADMIN) return [PROJECT_PERMISSIONS.UpdateMembers, PROJECT_PERMISSIONS.UpdateInfo]; - - if (role === ROLE_OWNER) return Object.values(PROJECT_PERMISSIONS); - - return [] - } - }) - } -}) - -const ROLE_OWNER = 'Owner' -const ROLE_ADMIN = 'Admin' -const ROLE_MAKER = 'Maker' - -const TEAM_MEMBER_ROLE = enumType({ - name: 'TEAM_MEMBER_ROLE', - members: [ROLE_OWNER, ROLE_ADMIN, ROLE_MAKER], -}); - -const PROJECT_PERMISSIONS = { - UpdateInfo: "UpdateInfo", - DeleteProject: "DeleteProject", - UpdateAdmins: "UpdateAdmins", - UpdateMembers: "UpdateMembers", -} - -const ProjectPermissionEnum = enumType({ - name: 'ProjectPermissionEnum', - members: PROJECT_PERMISSIONS, -}); - -const ProjectMember = objectType({ - name: "ProjectMember", - definition(t) { - t.nonNull.field('user', { - type: "User" - }) - t.nonNull.field("role", { - type: TEAM_MEMBER_ROLE - }) - } -}) - - -const Award = objectType({ - name: 'Award', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('image'); - t.nonNull.string('url'); - t.nonNull.field('project', { - type: "Project", - resolve: (parent) => { - return prisma.award.findUnique({ where: { id: parent.id } }).project(); - } - }) - } -}) - - -const Capability = objectType({ - name: 'Capability', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('icon'); - } -}) - -const checkValidProjectHashtag = extendType({ - type: "Query", - definition(t) { - t.nonNull.boolean('checkValidProjectHashtag', { - args: { - hashtag: nonNull(stringArg()), - projectId: intArg(), - }, - async resolve(parent, args, context) { - if (args.projectId) { - return !(await prisma.project.findFirst({ - where: { - id: { - not: args.projectId, - }, - hashtag: { - equals: args.hashtag - } - } - })) - } - return !(await prisma.project.findFirst({ - where: { - hashtag: { - equals: args.hashtag - } - } - })) - } - }) - } -}) - -const getAllCapabilities = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getAllCapabilities', { - type: Capability, - async resolve(parent, args, context) { - return prisma.capability.findMany(); - } - }) - } -}) - - -const getProject = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getProject', { - type: "Project", - args: { - id: intArg(), - tag: stringArg(), - }, - resolve(_, { id, tag }) { - if (tag) return prisma.project.findFirst({ where: { hashtag: tag } }) - return prisma.project.findUnique({ - where: { id } - }) - } - }) - } -}) - -const allProjects = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('allProjects', { - type: "Project", - args: paginationArgs({ take: 50 }), - resolve(_, { take, skip }) { - return prisma.project.findMany({ - orderBy: { votes_count: "desc" }, - skip, - take, - }); - } - }) - } -}) - -const newProjects = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('newProjects', { - type: "Project", - args: paginationArgs({ take: 50 }), - resolve(_, args) { - const take = args.take || 50; - const skip = args.skip || 0; - return prisma.project.findMany({ - orderBy: { createdAt: "desc" }, - skip, - take, - }); - } - }) - } -}) - - -const hottestProjects = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('hottestProjects', { - type: "Project", - args: paginationArgs({ take: 50 }), - async resolve(_, { take, skip }) { - return prisma.project.findMany({ - orderBy: { votes_count: "desc" }, - skip, - take, - }); - } - }) - } -}) - - -const searchProjects = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('searchProjects', { - type: "Project", - args: { - ...paginationArgs({ take: 50 }), - search: nonNull(stringArg()) - }, - async resolve(_, { take, skip, search }) { - return prisma.project.findMany({ - where: { - OR: [{ - title: { - contains: search, - mode: 'insensitive' - }, - }, { - description: { - contains: search, - mode: 'insensitive' - }, - }] - }, - skip, - take, - }); - } - }) - } -}) - - -const projectsByCategory = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('projectsByCategory', { - type: "Project", - args: { - ...paginationArgs(), - category_id: nonNull(intArg()) - }, - async resolve(_, { take, skip, category_id }) { - return prisma.project.findMany({ - where: { category_id }, - orderBy: { votes_count: "desc" }, - skip, - take, - }); - } - }) - } -}) - - -const getLnurlDetailsForProject = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getLnurlDetailsForProject', { - type: "LnurlDetails", - args: { project_id: nonNull(intArg()) }, - async resolve(_, args) { - const project = await prisma.project.findUnique({ - where: { - id: args.project_id, - }, - }); - const lnurlDetails = await getLnurlDetails( - lightningAddressToLnurl(project.lightning_address) - ); - if ( - !lnurlDetails.data || - lnurlDetails.data.status.toLowerCase() !== "ok" - ) { - console.error(lnurlDetails.data); - throw new Error("Recipient not available"); - } - - // cache the callback URL - await prisma.project.update({ - where: { id: project.id }, - data: { - lnurl_callback_url: lnurlDetails.data.callback, - }, - }); - // # SENDING MESSAGES TO THE PROJECT OWNER USING LNURL-PAY COMMENTS - // comments in lnurl pay can be used to send a private message or - // post on the projcet owners site. could even be used for advertising - // or tip messages. or can even be a pay to respond / paid advise - return { - minSendable: parseInt(lnurlDetails.data.minSendable) / 1000, - maxSendable: parseInt(lnurlDetails.data.maxSendable) / 1000, - metadata: lnurlDetails.data.metadata, - commentAllowed: lnurlDetails.data.commentAllowed, - }; - } - }) - } -}) - -const similarProjects = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('similarProjects', { - type: "Project", - args: { - id: nonNull(intArg()) - }, - async resolve(parent, { id }, ctx) { - const currentProject = await prisma.project.findUnique({ where: { id }, select: { category_id: true } }) - - return prisma.project.findMany({ - where: { - AND: { - id: { - not: id - }, - category_id: { - equals: currentProject.category_id - } - } - }, - take: 5, - }) - } - }) - } -}) - -const TeamMemberInput = inputObjectType({ - name: 'TeamMemberInput', - definition(t) { - t.nonNull.int('id') - t.nonNull.field("role", { - type: TEAM_MEMBER_ROLE - }) - } -}) - -const ProjectLaunchStatusEnum = enumType({ - name: 'ProjectLaunchStatusEnum', - members: ['WIP', 'Launched'], -}); - -const CreateProjectInput = inputObjectType({ - name: 'CreateProjectInput', - definition(t) { - t.int('id') // exists in update - t.nonNull.string('title'); - t.nonNull.string('hashtag'); - t.nonNull.string('website'); - t.nonNull.string('tagline'); - t.nonNull.string('description'); - t.nonNull.field('thumbnail_image', { - type: ImageInput - }) - t.nonNull.field('cover_image', { - type: ImageInput - }) - t.string('twitter'); - t.string('discord'); - t.string('github'); - t.string('slack'); - t.string('telegram'); - t.string('lightning_address'); - t.nonNull.int('category_id'); - t.nonNull.list.nonNull.int('capabilities'); // ids - t.nonNull.list.nonNull.field('screenshots', { - type: ImageInput - }); - t.nonNull.list.nonNull.field('members', { - type: TeamMemberInput - }); - t.nonNull.list.nonNull.int('recruit_roles'); // ids - t.nonNull.field('launch_status', { - type: ProjectLaunchStatusEnum - }); - t.nonNull.list.nonNull.int('tournaments'); // ids - } -}) - -const CreateProjectResponse = objectType({ - name: 'CreateProjectResponse', - definition(t) { - t.nonNull.field('project', { type: Project }) - } -}) - - - -const createProject = extendType({ - type: 'Mutation', - definition(t) { - t.field('createProject', { - type: CreateProjectResponse, - args: { input: CreateProjectInput }, - async resolve(_root, args, ctx) { - let { - title, - tagline, - hashtag, - description, - lightning_address, - capabilities, - category_id, - cover_image, - discord, - github, - slack, - telegram, - twitter, - website, - launch_status, - members, - recruit_roles, - screenshots, - thumbnail_image, - tournaments, - } = args.input - - const user = await getUserByPubKey(ctx.userPubKey) - - // Do some validation - if (!user) throw new ApolloError('Not Authenticated') - - // Many Owners found. Throw an error - if (members.filter((m) => m.role === ROLE_OWNER).length > 1) { - throw new ApolloError('Only 1 owner can be defined.') - } - - // No owner found. Set the current user as Owner - if (!members.find((m) => m.role === ROLE_OWNER)) { - const currentUser = members.find((m) => m.id === user.id) - if (currentUser) { - currentUser.role = ROLE_OWNER - } else { - members = [{ id: user.id, role: ROLE_OWNER }, ...members] - } - } - - const coverImage = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: cover_image.id, - }, - }) - - const coverImageRel = coverImage - ? { - cover_image_rel: { - connect: { - id: coverImage ? coverImage.id : null, - }, - }, - } - : {} - - const thumbnailImage = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: thumbnail_image.id, - }, - }) - - const thumbnailImageRel = thumbnailImage - ? { - thumbnail_image_rel: { - connect: { - id: thumbnailImage ? thumbnailImage.id : null, - }, - }, - } - : {} - - const screenshots_ids = await prisma.hostedImage.findMany({ - where: { - provider_image_id: { - in: screenshots.map((s) => s.id), - }, - }, - select: { - id: true, - }, - }) - - const project = await prisma.project.create({ - data: { - title, - description, - lightning_address, - tagline, - hashtag, - website, - discord, - github, - twitter, - slack, - telegram, - launch_status, - - ...coverImageRel, - ...thumbnailImageRel, - screenshots_ids: screenshots_ids.map((s) => s.id), - - category: { - connect: { - id: category_id, - }, - }, - members: { - create: members.map((member) => { - return { - role: member.role, - user: { - connect: { - id: member.id, - }, - }, - } - }), - }, - recruit_roles: { - create: recruit_roles.map((role) => { - return { - level: 0, - role: { - connect: { - id: role, - }, - }, - } - }), - }, - tournaments: { - create: tournaments.map((tournament) => { - return { - tournament: { - connect: { - id: tournament, - }, - }, - } - }), - }, - capabilities: { - connect: capabilities.map((c) => { - return { - id: c, - } - }), - }, - }, - }) - - await prisma.hostedImage - .updateMany({ - where: { - id: { - in: [coverImage.id, thumbnailImage.id, ...screenshots_ids.map((s) => s.id)], - }, - }, - data: { - is_used: true, - }, - }) - .catch((error) => { - logError(error) - throw new ApolloError('Unexpected error happened...') - }) - - return { project } - }, - }) - }, -}) - -const UpdateProjectInput = inputObjectType({ - name: 'UpdateProjectInput', - definition(t) { - t.int('id') - t.nonNull.string('title') - t.nonNull.string('hashtag') - t.nonNull.string('website') - t.nonNull.string('tagline') - t.nonNull.string('description') - t.nonNull.field('thumbnail_image', { - type: ImageInput, - }) - t.nonNull.field('cover_image', { - type: ImageInput, - }) - t.string('twitter') - t.string('discord') - t.string('github') - t.string('slack') - t.string('telegram') - t.string('lightning_address'); - t.nonNull.int('category_id') - t.nonNull.list.nonNull.int('capabilities') - t.nonNull.list.nonNull.field('screenshots', { - type: ImageInput, - }) - t.nonNull.list.nonNull.field('members', { - type: TeamMemberInput, - }) - t.nonNull.list.nonNull.int('recruit_roles') // ids - t.nonNull.field('launch_status', { - type: ProjectLaunchStatusEnum, - }) - t.nonNull.list.nonNull.int('tournaments') // ids - }, -}) - -const updateProject = extendType({ - type: 'Mutation', - definition(t) { - t.field('updateProject', { - type: CreateProjectResponse, - args: { input: UpdateProjectInput }, - async resolve(_root, args, ctx) { - const { - id, - title, - tagline, - hashtag, - description, - lightning_address, - capabilities, - category_id, - cover_image, - discord, - github, - slack, - telegram, - twitter, - website, - launch_status, - members, - recruit_roles, - screenshots, - thumbnail_image, - tournaments, - } = args.input - - const user = await getUserByPubKey(ctx.userPubKey) - - // Do some validation - if (!user) throw new ApolloError('Not Authenticated') - - const project = await prisma.project.findFirst({ - where: { - id, - }, - include: { - members: true, - }, - }) - - // Verifying current user is a member - if (!project.members.some((m) => m.userId === user.id)) { - throw new ApolloError("You don't have permission to update this project") - } - - // Maker can't change project info - if (project.members.find((m) => m.userId === user.id)?.role === ROLE_MAKER) { - throw new ApolloError("Makers can't change project info") - } - - let newMembers = [] - - // Admin can only change makers - if (project.members.find((m) => m.userId === user.id)?.role === ROLE_ADMIN) { - // Changing Makers - const newMakers = members.filter((m) => m.role === ROLE_MAKER) - - // Set old Admins and Owner using current project.memebers because Admin can't change these Roles - const currentAdminsOwner = project.members - .filter((m) => m.role === ROLE_ADMIN || m.role === ROLE_OWNER) - .map((m) => ({ id: m.userId, role: m.role })) - - newMembers = [...newMakers, ...currentAdminsOwner] - } else { - // Curent user is Owner. Can change all users roles - newMembers = members - } - - let imagesToDelete = [] - let imagesToAdd = [] - - let coverImageRel = {} - if (cover_image.id) { - const coverImage = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: cover_image.id, - }, - }) - - coverImageRel = coverImage - ? { - cover_image_rel: { - connect: { - id: coverImage ? coverImage.id : null, - }, - }, - } - : {} - - if (coverImage) { - imagesToAdd.push(coverImage.id) - } - - imagesToDelete.push(project.cover_image_id) - } - - let thumbnailImageRel = {} - if (thumbnail_image.id) { - const thumbnailImage = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: thumbnail_image.id, - }, - }) - - thumbnailImageRel = thumbnailImage - ? { - thumbnail_image_rel: { - connect: { - id: thumbnailImage ? thumbnailImage.id : null, - }, - }, - } - : {} - - if (thumbnailImage) { - imagesToAdd.push(thumbnailImage.id) - } - - imagesToDelete.push(project.thumbnail_image_id) - } - - let screenshots_ids = [] - for (const screenshot of screenshots) { - if (screenshot.id) { - const newScreenshot = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: screenshot.id, - }, - select: { - id: true, - }, - }) - if (newScreenshot) { - screenshots_ids.push(newScreenshot.id) - imagesToAdd.push(newScreenshot.id) - } - } else { - const newScreenshot = await prisma.hostedImage.findFirst({ - where: { - url: screenshot.url, - }, - select: { - id: true, - }, - }) - if (newScreenshot) { - screenshots_ids.push(newScreenshot.id) - } - } - } - const screenshotsIdsToDelete = project.screenshots_ids.filter((x) => !screenshots_ids.includes(x)) - imagesToDelete = [...imagesToDelete, ...screenshotsIdsToDelete] - - const updatedProject = await prisma.project - .update({ - where: { - id, - }, - data: { - title, - description, - lightning_address, - tagline, - hashtag, - website, - discord, - github, - twitter, - slack, - telegram, - launch_status, - - ...coverImageRel, - ...thumbnailImageRel, - screenshots_ids, - - category: { - connect: { - id: category_id, - }, - }, - members: { - deleteMany: {}, - create: newMembers.map((member) => { - return { - role: member.role, - user: { - connect: { - id: member.id, - }, - }, - } - }), - }, - recruit_roles: { - deleteMany: {}, - create: recruit_roles.map((role) => { - return { - level: 0, - role: { - connect: { - id: role, - }, - }, - } - }), - }, - tournaments: { - deleteMany: {}, - create: tournaments.map((tournament) => { - return { - tournament: { - connect: { - id: tournament, - }, - }, - } - }), - }, - capabilities: { - set: capabilities.map((c) => { - return { - id: c, - } - }), - }, - }, - }) - .catch((error) => { - logError(error) - throw new ApolloError('Unexpected error happened...') - }) - - if (imagesToAdd.length > 0) { - await prisma.hostedImage - .updateMany({ - where: { - id: { - in: imagesToAdd, - }, - }, - data: { - is_used: true, - }, - }) - .catch((error) => { - logError(error) - throw new ApolloError('Unexpected error happened...') - }) - } - - imagesToDelete.map(async (i) => await deleteImage(i)) - - return { project: updatedProject } - }, - }) - }, -}) - -const deleteProject = extendType({ - type: 'Mutation', - definition(t) { - t.field('deleteProject', { - type: 'Project', - args: { id: nonNull(intArg()) }, - async resolve(_root, args, ctx) { - const { id } = args - const user = await getUserByPubKey(ctx.userPubKey) - - // Do some validation - if (!user) throw new ApolloError('Not Authenticated') - - const project = await prisma.project.findFirst({ - where: { id }, - include: { - members: true, - }, - }) - - if (!project) throw new ApolloError('Project not found') - - if (project.members.find((m) => m.userId === user.id)?.role !== ROLE_OWNER) - throw new ApolloError("You don't have the right to delete this project") - - // Award is not implemented yet - // await prisma.award.deleteMany({ - // where: { - // projectId: project.id - // } - // }) - - await prisma.projectRecruitRoles.deleteMany({ - where: { - projectId: project.id, - }, - }) - - await prisma.projectMember.deleteMany({ - where: { - projectId: project.id, - }, - }) - - await prisma.tournamentProject.deleteMany({ - where: { - project_id: project.id, - }, - }) - - const deletedProject = await prisma.project.delete({ - where: { - id, - }, - }) - - const imagesToDelete = await prisma.hostedImage.findMany({ - where: { - OR: [ - { id: project.cover_image_id }, - { id: project.thumbnail_image_id }, - { - id: { - in: project.screenshots_ids, - }, - }, - ], - }, - select: { - id: true, - }, - }) - imagesToDelete.map(async (i) => await deleteImage(i.id)) - - return deletedProject - }, - }) - }, -}) - - -module.exports = { - // Types - Project, - Award, - TEAM_MEMBER_ROLE, - // Queries - getProject, - allProjects, - newProjects, - hottestProjects, - searchProjects, - projectsByCategory, - getLnurlDetailsForProject, - getAllCapabilities, - checkValidProjectHashtag, - similarProjects, - - // Mutations - createProject, - updateProject, - deleteProject, -} \ No newline at end of file diff --git a/api/functions/graphql/types/tag.js b/api/functions/graphql/types/tag.js deleted file mode 100644 index 6b48f43..0000000 --- a/api/functions/graphql/types/tag.js +++ /dev/null @@ -1,63 +0,0 @@ -const { objectType, extendType } = require("nexus"); -const { prisma } = require('../../../prisma'); - -const Tag = objectType({ - name: 'Tag', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.string('icon'); - t.string('description'); - t.boolean('isOfficial'); - } -}); - -const officialTags = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('officialTags', { - type: "Tag", - resolve: () => { - return prisma.tag.findMany({ - orderBy: { - title: 'asc' - }, - where: { - isOfficial: true - } - }); - } - }) - } -}) - -const popularTags = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('popularTags', { - type: "Tag", - resolve: () => { - return prisma.tag.findMany({ - where: { - isOfficial: true - }, - take: 8, - orderBy: { - stories: { - _count: 'desc' - } - }, - }); - } - }) - } -}) - -module.exports = { - // Types - Tag, - - // Queries - popularTags, - officialTags, -} \ No newline at end of file diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js deleted file mode 100644 index 196f376..0000000 --- a/api/functions/graphql/types/tournament.js +++ /dev/null @@ -1,566 +0,0 @@ -const { - intArg, - objectType, - stringArg, - extendType, - nonNull, - enumType, - inputObjectType, - booleanArg, -} = require('nexus'); -const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); -const { prisma } = require('../../../prisma'); -const { paginationArgs, removeNulls } = require('./helpers'); - - - -const TournamentPrize = objectType({ - name: 'TournamentPrize', - definition(t) { - t.nonNull.string('title'); - t.nonNull.string('amount'); - t.nonNull.string('image', { - async resolve(parent) { - return prisma.tournamentPrize.findUnique({ where: { id: parent.id } }).image_rel().then(resolveImgObjectToUrl) - } - }); - } -}) - -const TournamentJudge = objectType({ - name: 'TournamentJudge', - definition(t) { - t.nonNull.string('name'); - t.nonNull.string('company'); - t.nonNull.string('avatar', { - async resolve(parent) { - return prisma.tournamentJudge.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl) - } - }); - } -}) - -const TournamentFAQ = objectType({ - name: 'TournamentFAQ', - definition(t) { - t.nonNull.string('question'); - t.nonNull.string('answer'); - } -}) - -const TournamentParticipant = objectType({ - name: "TournamentParticipant", - definition(t) { - t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }); - t.boolean('is_registered') - t.nonNull.field('user', { type: "User" }) - } -}) - -const TournamentEventTypeEnum = enumType({ - name: 'TournamentEventTypeEnum', - members: { - TwitterSpace: 0, - Workshop: 1, - IRLMeetup: 2, - OnlineMeetup: 3, - }, -}); - -const TournamentMakerHackingStatusEnum = enumType({ - name: 'TournamentMakerHackingStatusEnum', - members: { - Solo: 0, - OpenToConnect: 1, - }, -}); - -const TournamentEvent = objectType({ - name: 'TournamentEvent', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('image', { - async resolve(parent) { - return prisma.tournamentEvent.findUnique({ where: { id: parent.id } }).image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.string('description'); - t.nonNull.date('starts_at'); - t.nonNull.date('ends_at'); - t.nonNull.string('location'); - t.nonNull.string('website'); - t.nonNull.field('type', { type: TournamentEventTypeEnum }) - t.nonNull.list.nonNull.string('links', { resolve() { return [] } }); - } -}) - -const Tournament = objectType({ - name: 'Tournament', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('description'); - t.nonNull.string('thumbnail_image', { - async resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).thumbnail_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.string('cover_image', { - async resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.date('start_date'); - t.nonNull.date('end_date'); - t.nonNull.string('location'); - t.nonNull.string('website'); - - t.nonNull.int('events_count', { - resolve(parent) { - return prisma.tournamentEvent.count({ - where: { - tournament_id: parent.id - } - }) - } - }); - t.nonNull.int('makers_count', { - resolve(parent) { - return prisma.tournamentParticipant.count({ - where: { - tournament_id: parent.id - } - }) - } - }); - t.nonNull.int('projects_count', { - resolve(parent) { - return prisma.tournamentProject.count({ - where: { - tournament_id: parent.id - } - }) - } - }); - - t.nonNull.list.nonNull.field('prizes', { - type: TournamentPrize, - resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).prizes() - } - }); - t.nonNull.list.nonNull.field('judges', { - type: TournamentJudge, - resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).judges() - } - }); - t.nonNull.list.nonNull.field('faqs', { - type: TournamentFAQ, - resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).faqs() - } - }); - t.nonNull.list.nonNull.field('events', { - type: TournamentEvent, - resolve(parent) { - return prisma.tournament.findUnique({ where: { id: parent.id } }).events() - } - }); - } -}) - - -const TournamentMakersResponse = objectType({ - name: 'TournamentMakersResponse', - definition(t) { - t.boolean('hasNext'); - t.boolean('hasPrev'); - - t.nonNull.list.nonNull.field('makers', { type: TournamentParticipant }) - } -} -) - -const TournamentProjectsResponse = objectType({ - name: 'TournamentProjectsResponse', - definition(t) { - t.boolean('hasNext'); - t.boolean('hasPrev'); - - t.nonNull.list.nonNull.field('projects', { type: "Project" }) - } -} -) - -const getTournamentById = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getTournamentById', { - type: Tournament, - args: { - id: nonNull(intArg()), - }, - resolve(_, { id }) { - return prisma.tournament.findUnique({ - where: { id } - }) - } - }) - } -}) - - -const getTournamentToRegister = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getTournamentToRegister', { - type: Tournament, - args: { - }, - resolve() { - - return prisma.tournament.findMany({ - where: { - end_date: { - gt: new Date() - }, - } - }) - } - }) - } -}) - -const ParticipationInfo = objectType({ - name: "ParticipationInfo", - definition(t) { - t.nonNull.date('createdAt') - t.nonNull.string('email') - t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }); - - } -}) - -const tournamentParticipationInfo = extendType({ - type: "Query", - definition(t) { - t.field('tournamentParticipationInfo', { - type: ParticipationInfo, - args: { - tournamentId: nonNull(intArg()), - }, - async resolve(_, args, ctx) { - - const user = await getUserByPubKey(ctx.userPubKey); - if (!user) - return null - - - return prisma.tournamentParticipant.findFirst({ - where: { - user_id: user.id, - tournament_id: args.tournamentId - } - }) - } - }) - } -}) - -const getMakersInTournament = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getMakersInTournament', { - type: TournamentMakersResponse, - args: { - tournamentId: nonNull(intArg()), - ...paginationArgs({ take: 10 }), - search: stringArg(), - roleId: intArg(), - openToConnect: booleanArg() - }, - async resolve(_, args, ctx) { - - const user = await getUserByPubKey(ctx.userPubKey); - - - let filters = []; - - if (args.search) filters.push({ - OR: [ - { - name: { - contains: args.search, - mode: 'insensitive' - } - }, - { - jobTitle: { - contains: args.search, - mode: 'insensitive' - } - } - ] - }) - - - if (args.roleId) filters.push({ - roles: { - some: { - roleId: args.roleId - } - } - }) - - if (args.openToConnect) filters.push({ - OR: [ - { - github: { - not: '' - } - }, - { - twitter: { - not: '' - } - }, - { - linkedin: { - not: '' - } - }, - ] - }) - - if (user?.id) filters.push({ - id: { - not: user.id - } - }) - - - - const makers = (await prisma.tournamentParticipant.findMany({ - where: { - tournament_id: args.tournamentId, - ...(filters.length > 0 && { - user: { - AND: filters - } - }), - ...(args.openToConnect && { - hacking_status: TournamentMakerHackingStatusEnum.value.members.OpenToConnect - }) - }, - orderBy: { - createdAt: 'desc' - }, - include: { - user: true, - }, - skip: args.skip, - take: args.take + 1, - })) - .map(item => ({ - hacking_status: item.hacking_status, - user: item.user - })) - - - - return { - hasNext: makers.length === args.take + 1, - hasPrev: args.skip !== 0, - makers: makers.slice(0, args.take) - } - } - }) - } -}) - -const getProjectsInTournament = extendType({ - type: "Query", - definition(t) { - t.nonNull.field('getProjectsInTournament', { - type: TournamentProjectsResponse, - args: { - tournamentId: nonNull(intArg()), - ...paginationArgs({ take: 10 }), - search: stringArg(), - roleId: intArg(), - }, - async resolve(_, args) { - - - let filters = []; - - if (args.search) filters.push({ - OR: [ - { - title: { - contains: args.search, - mode: 'insensitive' - } - }, - { - description: { - contains: args.search, - mode: 'insensitive' - } - } - ] - }) - - - // if (args.roleId) filters.push({ - // recruit_roles: { - // some: { - // roleId: args.roleId - // } - // } - // }) - - - - const projects = (await prisma.tournamentProject.findMany({ - where: { - tournament_id: args.tournamentId, - ...(filters.length > 0 && { - project: { - AND: filters - } - }) - }, - include: { - project: true, - }, - skip: args.skip, - take: args.take + 1, - })).map(item => item.project) - - console.log(); - - - return { - hasNext: projects.length === args.take + 1, - hasPrev: args.skip !== 0, - projects: projects.slice(0, args.take) - } - } - }) - } -}) - - - -const RegisterInTournamentInput = inputObjectType({ - name: 'RegisterInTournamentInput', - definition(t) { - t.nonNull.string('email') - t.nonNull.field('hacking_status', { type: TournamentMakerHackingStatusEnum }) - } -}) - - -const registerInTournament = extendType({ - type: 'Mutation', - definition(t) { - t.field('registerInTournament', { - type: 'User', - args: { - data: RegisterInTournamentInput, - tournament_id: nonNull(intArg()) - }, - async resolve(_root, { tournament_id, data: { email, hacking_status } }, ctx) { - const user = await getUserByPubKey(ctx.userPubKey); - - // Do some validation - if (!user) - throw new Error("You have to login"); - - - // Email verification here: - // .... - // .... - - return (await prisma.tournamentParticipant.create({ - data: { - tournament_id, - user_id: user.id, - email, - hacking_status - }, - include: { - user: true - } - })).user; - } - }) - }, -}) - -const UpdateTournamentRegistrationInput = inputObjectType({ - name: 'UpdateTournamentRegistrationInput', - definition(t) { - t.string('email') - t.field('hacking_status', { type: TournamentMakerHackingStatusEnum }) - } -}) - -const updateTournamentRegistration = extendType({ - type: 'Mutation', - definition(t) { - t.field('updateTournamentRegistration', { - type: ParticipationInfo, - args: { - data: UpdateTournamentRegistrationInput, - tournament_id: nonNull(intArg()) - }, - async resolve(_root, { tournament_id, data: { email, hacking_status } }, ctx) { - const user = await getUserByPubKey(ctx.userPubKey); - - // Do some validation - // if (!user) - // throw new Error("You have to login"); - - - // Email verification here: - // .... - // .... - - return prisma.tournamentParticipant.update({ - where: { - tournament_id_user_id: { tournament_id, user_id: user.id } - }, - data: removeNulls({ - email, - hacking_status - }), - }); - } - }) - }, -}) - - -module.exports = { - // Types - Tournament, - - // Enums - TournamentEventTypeEnum, - - // Queries - getTournamentById, - getMakersInTournament, - getProjectsInTournament, - tournamentParticipationInfo, - getTournamentToRegister, - - // Mutations - registerInTournament, - updateTournamentRegistration, -} diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js deleted file mode 100644 index 3ec0a8a..0000000 --- a/api/functions/graphql/types/users.js +++ /dev/null @@ -1,577 +0,0 @@ - -const { prisma } = require('../../../prisma'); -const { objectType, extendType, intArg, nonNull, inputObjectType, stringArg, interfaceType, list, enumType } = require("nexus"); -const { getUserByPubKey } = require("../../../auth/utils/helperFuncs"); -const { removeNulls } = require("./helpers"); -const { ImageInput } = require('./misc'); -const { Tournament } = require('./tournament'); -const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl'); -const { deleteImage } = require('../../../services/imageUpload.service'); - - - - -const BaseUser = interfaceType({ - name: 'BaseUser', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('name'); - t.nonNull.string('avatar', { - async resolve(parent) { - return prisma.user.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl) - } - }); - t.nonNull.date('join_date'); - t.string('role'); - t.string('jobTitle') - t.string('lightning_address') - t.string('website') - t.string('twitter') - t.string('discord') - t.string('github') - t.string('linkedin') - t.string('bio') - t.string('location') - t.nonNull.list.nonNull.field('roles', { - type: MakerRole, - resolve: async (parent) => { - const data = await prisma.user.findUnique({ - where: { - id: parent.id - }, - select: { - roles: { - select: { - role: true, - level: true - } - }, - } - }) - return data.roles.map(data => { - return ({ ...data.role, level: data.level }) - }) - } - }) - t.nonNull.list.nonNull.field('skills', { - type: MakerSkill, - resolve: (parent) => { - return prisma.user.findUnique({ where: { id: parent.id } }).skills(); - } - }) - t.nonNull.list.nonNull.field('tournaments', { - type: Tournament, - resolve: async (parent) => { - return prisma.tournamentParticipant.findMany({ - where: { - user_id: parent.id - }, - include: { - tournament: true - } - }).then(d => d.map(item => item.tournament)) - } - }) - t.nonNull.list.nonNull.field('projects', { - type: "Project", - resolve: async (parent) => { - return prisma.projectMember.findMany({ - where: { - userId: parent.id - }, - include: { - project: true - } - }).then(d => d.map(item => item.project)) - } - }) - t.nonNull.list.nonNull.field('similar_makers', { - type: "User", - resolve(parent,) { - return prisma.user.findMany({ - where: { - AND: { - id: { - not: parent.id - } - } - }, - take: 3, - }) - } - }) - - - t.nonNull.list.nonNull.field('stories', { - type: "Story", - resolve: (parent) => { - return prisma.story.findMany({ where: { user_id: parent.id, is_published: true }, orderBy: { createdAt: "desc" } }); - } - }); - - t.nonNull.boolean('in_tournament', { - args: { - id: nonNull(intArg()) - }, - resolve(parent, args) { - return prisma.tournamentParticipant.findFirst({ where: { tournament_id: args.id, user_id: parent.id } }).then(res => !!res) - } - }) - - - }, - resolveType() { - return null - }, -}) - - - -const RoleLevelEnum = enumType({ - name: 'RoleLevelEnum', - members: { - Beginner: 0, - Hobbyist: 1, - Intermediate: 2, - Advanced: 3, - Pro: 4, - }, -}); - -const GenericMakerRole = objectType({ - name: 'GenericMakerRole', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('icon'); - } -}) - -const MakerRole = objectType({ - name: 'MakerRole', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - t.nonNull.string('icon'); - t.nonNull.field('level', { type: RoleLevelEnum }) - } -}) - -const getAllMakersRoles = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getAllMakersRoles', { - type: GenericMakerRole, - async resolve(parent, args, context) { - return prisma.workRole.findMany(); - } - }) - } -}) - - -const MakerSkill = objectType({ - name: 'MakerSkill', - definition(t) { - t.nonNull.int('id'); - t.nonNull.string('title'); - } -}) - -const getAllMakersSkills = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('getAllMakersSkills', { - type: MakerSkill, - async resolve(parent, args, context) { - return prisma.skill.findMany(); - } - }) - } -}) - - -const User = objectType({ - name: 'User', - definition(t) { - t.implements('BaseUser') - } -}) - -const MyProfile = objectType({ - name: 'MyProfile', - definition(t) { - t.implements('BaseUser') - - t.string('email') - t.string('nostr_prv_key') - t.string('nostr_pub_key') - - t.nonNull.list.nonNull.field('walletsKeys', { - type: "WalletKey", - resolve: (parent, _, context) => { - return prisma.userKey.findMany({ - where: { - user_id: parent.id, - }, - orderBy: { - createdAt: "asc" - } - }) - .then(keys => keys.map(k => ({ ...k, is_current: k.key === context.userPubKey }))) - } - }); - } -}) - - -const me = extendType({ - type: "Query", - definition(t) { - t.field('me', { - type: "MyProfile", - async resolve(parent, args, context) { - const user = await getUserByPubKey(context.userPubKey) - return user - } - }) - } -}) - -const profile = extendType({ - type: "Query", - definition(t) { - t.field('profile', { - type: "User", - args: { - id: nonNull(intArg()) - }, - async resolve(parent, { id }, ctx) { - - const user = await getUserByPubKey(ctx.userPubKey) - let isMy = false; - if (user?.id === id) isMy = true; - - return prisma.user.findUnique({ where: { id } }) - } - }) - } -}) - -const searchUsers = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('searchUsers', { - type: "User", - args: { - value: nonNull(stringArg()) - }, - async resolve(_, { value }) { - return prisma.user.findMany({ - where: { - name: { - contains: value, - mode: "insensitive" - } - }, - }) - } - }) - } -}) - - -const similarMakers = extendType({ - type: "Query", - definition(t) { - t.nonNull.list.nonNull.field('similarMakers', { - type: "User", - args: { - id: nonNull(intArg()) - }, - async resolve(parent, { id }, ctx) { - return prisma.user.findMany({ - where: { - AND: { - id: { - not: id - } - } - }, - take: 3, - }) - } - }) - } -}) - -const ProfileDetailsInput = inputObjectType({ - name: 'ProfileDetailsInput', - definition(t) { - t.string('name'); - t.field('avatar', { - type: ImageInput - }) - t.string('email') - t.string('jobTitle') - t.string('lightning_address') - t.string('website') - t.string('twitter') - t.string('discord') - t.string('github') - t.string('linkedin') - t.string('bio') - t.string('location') - } -}) - -const updateProfileDetails = extendType({ - type: 'Mutation', - definition(t) { - t.field('updateProfileDetails', { - type: 'MyProfile', - args: { data: ProfileDetailsInput }, - async resolve(_root, args, ctx) { - const user = await getUserByPubKey(ctx.userPubKey); - - // Do some validation - if (!user) - throw new Error("You have to login"); - // TODO: validate new data - - // ---------------- - // Check if the user uploaded a new image, and if so, - // remove the old one from the hosting service, then replace it with this one - // ---------------- - let avatarId = user.avatar_id; - if (args.data.avatar.id) { - const newAvatarProviderId = args.data.avatar.id; - const newAvatar = await prisma.hostedImage.findFirst({ - where: { - provider_image_id: newAvatarProviderId - } - }) - - if (newAvatar && newAvatar.id !== user.avatar_id) { - avatarId = newAvatar.id; - - await prisma.hostedImage.update({ - where: { - id: newAvatar.id - }, - data: { - is_used: true - } - }); - - await deleteImage(user.avatar_id) - } - } - - // Preprocess & insert - return prisma.user.update({ - where: { - id: user.id, - }, - data: removeNulls({ - ...args.data, - avatar_id: avatarId, - - //hack to remove avatar from args.data - // can be removed later with a schema data validator - avatar: '', - }) - }) - } - }) - }, -}) - - -const WalletKey = objectType({ - name: 'WalletKey', - definition(t) { - t.nonNull.string('key'); - t.nonNull.string('name'); - t.nonNull.date('createdAt'); - t.nonNull.boolean('is_current') - } -}) - - - -const UserKeyInputType = inputObjectType({ - name: 'UserKeyInputType', - definition(t) { - t.nonNull.string('key'); - t.nonNull.string('name'); - } -}) - - - -const updateUserPreferences = extendType({ - type: 'Mutation', - definition(t) { - t.nonNull.field('updateUserPreferences', { - type: 'MyProfile', - args: { userKeys: list(nonNull(UserKeyInputType)) }, - async resolve(_root, args, ctx) { - - const user = await getUserByPubKey(ctx.userPubKey); - if (!user) - throw new Error("You have to login"); - - - //Update the userkeys - //-------------------- - - // Check if all the sent keys belong to the user - const userKeys = (await prisma.userKey.findMany({ - where: { - AND: { - user_id: { - equals: user.id, - }, - key: { - in: args.userKeys.map(i => i.key) - } - }, - }, - select: { - key: true - } - })).map(i => i.key); - - const newKeys = []; - for (let i = 0; i < args.userKeys.length; i++) { - const item = args.userKeys[i]; - if (userKeys.includes(item.key)) - newKeys.push(item); - } - - - if (newKeys.length === 0) - throw new Error("You can't delete all your wallets keys") - - await prisma.userKey.deleteMany({ - where: { - user_id: user.id - } - }) - - await prisma.userKey.createMany({ - data: newKeys.map(i => ({ - user_id: user.id, - key: i.key, - name: i.name, - })) - }) - - return prisma.user.findUnique({ where: { id: user.id } }); - } - }) - } -}) - - - -const MakerRoleInput = inputObjectType({ - name: "MakerRoleInput", - definition(t) { - t.nonNull.int('id'); - t.nonNull.field('level', { type: RoleLevelEnum }) - } -}) - -const MakerSkillInput = inputObjectType({ - name: "MakerSkillInput", - definition(t) { - t.nonNull.int('id'); - } -}) - - -const ProfileRolesInput = inputObjectType({ - name: 'ProfileRolesInput', - definition(t) { - t.nonNull.list.nonNull.field('roles', { - type: MakerRoleInput, - }) - t.nonNull.list.nonNull.field('skills', { - type: MakerSkillInput, - }) - } -}) - -const updateProfileRoles = extendType({ - type: 'Mutation', - definition(t) { - t.field('updateProfileRoles', { - type: 'MyProfile', - args: { data: ProfileRolesInput }, - async resolve(_root, args, ctx) { - const user = await getUserByPubKey(ctx.userPubKey); - - // Do some validation - if (!user) - throw new Error("You have to login"); - - await prisma.user.update({ - where: { - id: user.id, - }, - data: { - skills: { - set: [], - }, - roles: { - deleteMany: {} - }, - }, - } - ) - - - return prisma.user.update({ - where: { - id: user.id, - }, - data: { - skills: { - connect: args.data.skills, - }, - roles: { - create: args.data.roles.map(r => ({ roleId: r.id, level: r.level })) - } - } - }) - } - }) - }, -}) - - - - - -module.exports = { - // Types - - BaseUser, - User, - MyProfile, - WalletKey, - MakerRole, - // Queries - me, - profile, - searchUsers, - similarMakers, - getAllMakersRoles, - getAllMakersSkills, - // Mutations - updateProfileDetails, - updateUserPreferences, - updateProfileRoles, -} diff --git a/api/functions/graphql/types/vote.js b/api/functions/graphql/types/vote.js deleted file mode 100644 index 086f299..0000000 --- a/api/functions/graphql/types/vote.js +++ /dev/null @@ -1,219 +0,0 @@ -const { - intArg, - objectType, - extendType, - nonNull, - stringArg, - arg, - enumType, -} = require('nexus') -const { parsePaymentRequest } = require('invoices'); -const { getPaymetRequestForItem, hexToUint8Array } = require('./helpers'); -const { createHash } = require('crypto'); -const { prisma } = require('../../../prisma'); -const { CONSTS } = require('../../../utils'); - - - -// the types of items we can vote to -const VOTE_ITEM_TYPE = enumType({ - name: 'VOTE_ITEM_TYPE', - members: ['Story', 'Bounty', 'Question', 'Project', 'User', 'PostComment'], -}) - - -const Vote = objectType({ - name: 'Vote', - definition(t) { - t.nonNull.int('id'); - t.nonNull.int('amount_in_sat'); - t.nonNull.string('payment_request'); - t.nonNull.string('payment_hash'); - t.nonNull.boolean('paid'); - - t.nonNull.field('item_type', { - type: "VOTE_ITEM_TYPE" - }) - t.nonNull.int('item_id'); - - } -}) - - -const LnurlDetails = objectType({ - name: 'LnurlDetails', - definition(t) { - t.int('minSendable'); - t.int('maxSendable'); - t.string('metadata'); - t.int('commentAllowed'); - } -}) - - - - -const getModalOfType = (type) => { - switch (type) { - case "Story": - return prisma.story; - case "Question": - return prisma.question; - case "Project": - return prisma.project; - case "PostComment": - return prisma.postComment; - default: - return null; - } -} - -const getLightningAddress = async (item_id, item_type) => { - switch (item_type) { - case "Story": - return prisma.story.findUnique({ - where: { id: item_id }, include: { - user: { - select: { - lightning_address: true - } - } - } - }).then(data => data.user.lightning_address); - case "Question": - return prisma.question.findUnique({ - where: { id: item_id }, include: { - user: { - select: { - lightning_address: true - } - } - } - }).then(data => data.user.lightning_address); - case "Project": - return prisma.project.findUnique({ - where: { id: item_id }, - select: { - lightning_address: true - } - }).then(data => data.lightning_address); - case "Comment": - return prisma.postComment.findUnique({ - where: { id: item_id }, include: { - user: { - select: { - lightning_address: true - } - } - } - }).then(data => data.user.lightning_address); - default: - return null; - } -} - -// type => modal -// type => lightning address (pr) - - -// This is the new voting mutation, it can vote for any type of item that we define in the VOTE_ITEM_TYPE enum -const voteMutation = extendType({ - type: "Mutation", - definition(t) { - t.nonNull.field('vote', { - type: "Vote", - args: { - item_type: arg({ - type: nonNull("VOTE_ITEM_TYPE") - }), - item_id: nonNull(intArg()), - amount_in_sat: nonNull(intArg()) - }, - resolve: async (_, args) => { - - const { item_id, item_type, amount_in_sat } = args; - const lightning_address = (await getLightningAddress(item_id, item_type)) ?? CONSTS.BOLT_FUN_LIGHTNING_ADDRESS; - const pr = await getPaymetRequestForItem(lightning_address, args.amount_in_sat); - const invoice = parsePaymentRequest({ request: pr }); - - // #TODO remove votes rows that get added but not confirmed after some time - // maybe using a scheduler, timeout, or whatever mean available - - return prisma.vote.create({ - data: { - item_type: item_type, - item_id: item_id, - amount_in_sat: amount_in_sat, - payment_request: pr, - payment_hash: invoice.id, - } - }); - } - }) - } -}) - - -const confirmVoteMutation = extendType({ - type: "Mutation", - definition(t) { - t.nonNull.field('confirmVote', { - type: "Vote", - args: { - payment_request: nonNull(stringArg()), - preimage: nonNull(stringArg()) - }, - resolve: async (_, args) => { - const paymentHash = createHash("sha256") - .update(hexToUint8Array(args.preimage)) - .digest("hex"); - // look for a vote for the payment request and the calculated payment hash - const vote = await prisma.vote.findFirst({ - where: { - payment_request: args.payment_request, - payment_hash: paymentHash, - }, - }); - - // if we find a vote it means the preimage is correct and we update the vote and mark it as paid - // can we write this nicer? - if (vote) { - const modal = getModalOfType(vote.item_type); - const item = await modal.findUnique({ - where: { id: vote.item_id }, - }); - // count up votes cache - await modal.update({ - where: { id: item.id }, - data: { - votes_count: item.votes_count + vote.amount_in_sat, - }, - }); - // return the current vote - return prisma.vote.update({ - where: { id: vote.id }, - data: { - paid: true, - preimage: args.preimage, - } - }); - } else { - throw new Error("Invalid preimage"); - } - } - }) - } -}) - -module.exports = { - // Enums - VOTE_ITEM_TYPE, - - // Types - Vote, - LnurlDetails, - - // Mutations - voteMutation, - confirmVoteMutation -} \ No newline at end of file diff --git a/api/functions/is-logged-in/is-logged-in.js b/api/functions/is-logged-in/is-logged-in.js deleted file mode 100644 index 3eeb574..0000000 --- a/api/functions/is-logged-in/is-logged-in.js +++ /dev/null @@ -1,72 +0,0 @@ - -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const jose = require('jose'); -const { JWT_SECRET } = require('../../utils/consts'); -const lnurlAuthService = require('../../auth/services/lnurlAuth.service'); - - -const isLoggedInHandler = async (req, res) => { - try { - const login_session = req.headers.session_token; - if (login_session) { - const { payload } = await jose.jwtVerify(login_session, Buffer.from(JWT_SECRET), { - algorithms: ['HS256'], - }); - const hash = payload.hash; - const authToken = await lnurlAuthService.getAuthTokenByHash(hash); - if (!authToken) - throw new Error("Not logged in yet") - - lnurlAuthService.removeHash(hash).catch(); - lnurlAuthService.removeExpiredHashes().catch(); - - res - .status(200) - .clearCookie('login_session', { - secure: true, - httpOnly: true, - sameSite: "none", - }) - .cookie('Authorization', authToken, { - maxAge: 3600000 * 24 * 30, - secure: true, - httpOnly: true, - sameSite: "none", - }) - .json({ - logged_in: true - }); - } else { - res.json({ - logged_in: false - }); - } - } catch (error) { - res.json({ - logged_in: false - }) - } - - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.get('/is-logged-in', isLoggedInHandler); -} -else { - const router = express.Router(); - router.get('/is-logged-in', (isLoggedInHandler)) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/login/login.js b/api/functions/login/login.js deleted file mode 100644 index 9dbf7e8..0000000 --- a/api/functions/login/login.js +++ /dev/null @@ -1,170 +0,0 @@ - -const { prisma } = require('../../prisma'); -const LnurlAuthService = require('../../auth/services/lnurlAuth.service') -const serverless = require('serverless-http'); -const { createHash, associateTokenToHash } = require('../../auth/services/lnurlAuth.service'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const jose = require('jose'); -const { JWT_SECRET } = require('../../utils/consts'); -const { generatePrivateKey, getPublicKey } = require('../../utils/nostr-tools'); -const { getUserByPubKey } = require('../../auth/utils/helperFuncs'); -const { logError } = require('../../utils/logger'); - - - -const loginHandler = async (req, res) => { - - const { tag, k1, sig, key, action, user_token } = req.query; - - if (tag !== 'login') - return res.status(400).json({ status: 'ERROR', reason: 'Invalid Tag Provided' }) - // Verify login params - try { - await LnurlAuthService.verifySig(sig, k1, key) - } catch (error) { - return res.status(400).json({ status: 'ERROR', reason: 'Invalid Signature' }) - - } - - if (action === 'link' && user_token) { - try { - - let user_id; - - try { - const { payload } = await jose.jwtVerify(user_token, Buffer.from(JWT_SECRET), { - algorithms: ['HS256'], - }) - user_id = payload.user_id; - } catch (error) { - return res.status(400).json({ status: 'ERROR', reason: "Invalid user_token" }) - } - - const existingKeys = await prisma.userKey.findMany({ where: { user_id }, select: { key: true } }); - - if (existingKeys.length >= 3) - return res.status(400).json({ status: 'ERROR', reason: "Can only link up to 3 wallets" }) - - // Remove old linking for this key if existing - await prisma.userKey.deleteMany({ - where: { key } - }) - - await prisma.userKey.create({ - data: { - key, - user_id, - } - }); - - - return res - .status(200) - .json({ status: "OK" }) - - } catch (error) { - logError(error) - return res.status(500).json({ status: 'ERROR', reason: 'Unexpected error happened' }) - } - } - - - try { - //Create user if not already existing - const user = await getUserByPubKey(key) - if (user === null) { - - // Check if user had a previous account using this wallet - const oldAccount = await prisma.user.findFirst({ - where: { - pubKey: key - } - }); - - if (oldAccount) { - await prisma.userKey.create({ - data: { - key, - name: "My original wallet key", - user_id: oldAccount.id, - } - }); - } else { - const nostr_prv_key = generatePrivateKey(); - const nostr_pub_key = getPublicKey(nostr_prv_key); - - const avatar = await prisma.hostedImage.create({ - data: { - filename: 'avatar.svg', - provider: 'external', - is_used: true, - url: `https://avatars.dicebear.com/api/bottts/${key}.svg`, - provider_image_id: '' - } - }) - - const createdUser = await prisma.user.create({ - data: { - pubKey: key, - name: key, - avatar_id: avatar.id, - nostr_prv_key, - nostr_pub_key, - }, - }) - await prisma.userKey.create({ - data: { - key, - name: "My original wallet key", - user_id: createdUser.id, - } - }); - } - - } - - // calc the hash of k1 - const hash = createHash(k1); - - // generate the auth jwt token - const hour = 3600000 - const maxAge = 30 * 24 * hour; - - const authToken = await new jose.SignJWT({ pubKey: key }) - .setProtectedHeader({ alg: 'HS256' }) - .setIssuedAt() - .setExpirationTime(maxAge) - //TODO: Set audience, issuer - .sign(Buffer.from(JWT_SECRET, 'utf-8')) - - // associate the auth token with the hash in the db - await associateTokenToHash(hash, authToken); - - - return res.status(200).json({ status: "OK" }) - - } catch (error) { - logError(error) - return res.status(500).json({ status: 'ERROR', reason: 'Unexpected error happened, please try again' }) - } -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.get('/login', loginHandler); -} -else { - const router = express.Router(); - router.get('/login', loginHandler) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/logout/logout.js b/api/functions/logout/logout.js deleted file mode 100644 index dea478c..0000000 --- a/api/functions/logout/logout.js +++ /dev/null @@ -1,34 +0,0 @@ -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); - -const logoutHandler = (req, res, next) => { - - res - .clearCookie('Authorization', { - secure: true, - httpOnly: true, - sameSite: "none", - }) - .redirect("/") - .end() - -}; - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.get('/logout', logoutHandler); -} -else { - const router = express.Router(); - router.get('/logout', logoutHandler) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/nostr-confirm-event/nostr-confirm-event.js b/api/functions/nostr-confirm-event/nostr-confirm-event.js deleted file mode 100644 index bd522af..0000000 --- a/api/functions/nostr-confirm-event/nostr-confirm-event.js +++ /dev/null @@ -1,97 +0,0 @@ - -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const extractKeyFromCookie = require('../../utils/extractKeyFromCookie'); -const { getUserByPubKey } = require('../../auth/utils/helperFuncs'); -const { verifySignature, validateEvent } = require('../../utils/nostr-tools'); -const { prisma } = require('../../prisma'); - - -const signEvent = async (req, res) => { - try { - const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie) - const user = await getUserByPubKey(userPubKey); - - if (!user) - return res.status(401).json({ status: 'ERROR', reason: 'Not Authenticated' }); - - const pubkey = user.nostr_pub_key; - - const event = req.body.event - - if (!validateEvent(event)) - return res.status(400).send("Event not valid"); - - if (event.pubkey !== pubkey || !(await verifySignature(event))) - return res.status(400).send("Signature not valid") - - - - // Extract type & id - const rTag = event.tags.find(tag => tag[0] === 'r'); - const [host, type, refId] = rTag[1].split(' '); - - if (host !== 'boltfun') return res.status(400).send("This event wasn't signed by bolt.fun"); - - - if (type === 'Story_comment') { - - // Extract replyTo id - const eTag = event.tags.find(tag => tag[0] === 'e'); - let parent_comment_id; - if (eTag) { - const [parent_nostr_comment_id] = eTag[1].split(' '); - if (parent_nostr_comment_id) - parent_comment_id = (await prisma.postComment.findFirst({ - where: { - nostr_id: parent_nostr_comment_id - } - }))?.id; - } - - - // Insert comment in database - await prisma.postComment.create({ - data: { - nostr_id: event.id, - body: event.content, - story_id: Number(refId), - user_id: user.id, - parent_comment_id - }, - - }) - - - } - - - return res - .status(200) - .end() - } catch (error) { - console.log(error); - res.status(500).send("Unexpected error happened, please try again") - } - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.post('/nostr-confirm-event', signEvent); -} -else { - const router = express.Router(); - router.post('/nostr-confirm-event', signEvent) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/nostr-events-extra-data/nostr-events-extra-data.js b/api/functions/nostr-events-extra-data/nostr-events-extra-data.js deleted file mode 100644 index b1d00f5..0000000 --- a/api/functions/nostr-events-extra-data/nostr-events-extra-data.js +++ /dev/null @@ -1,66 +0,0 @@ - -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const { prisma } = require('../../prisma'); - - -const getEventsExtraData = async (req, res) => { - try { - const ids = req.body.ids ?? [] - - const comments = await prisma.postComment.findMany({ - where: { - nostr_id: { - in: ids - } - }, - select: { - id: true, - nostr_id: true, - votes_count: true, - user: { - select: { - id: true, - avatar: true, - avatar_rel: { - select: { - url: true, - } - }, - name: true, - } - } - } - }); - - comments.map(c => c.user.avatar = c.user.avatar_rel?.url ?? c.user.avatar) - - return res - .status(200) - .json(comments) - } catch (error) { - console.log(error); - res.status(500).send("Unexpected error happened, please try again") - } - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.post('/nostr-events-extra-data', getEventsExtraData); -} -else { - const router = express.Router(); - router.post('/nostr-events-extra-data', getEventsExtraData) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/nostr-sign-event/nostr-sign-event.js b/api/functions/nostr-sign-event/nostr-sign-event.js deleted file mode 100644 index 8b195ca..0000000 --- a/api/functions/nostr-sign-event/nostr-sign-event.js +++ /dev/null @@ -1,74 +0,0 @@ - -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const extractKeyFromCookie = require('../../utils/extractKeyFromCookie'); -const { getUserByPubKey } = require('../../auth/utils/helperFuncs'); -const { generatePrivateKey, getPublicKey, signEvent: signNostrEvent } = require('../../utils/nostr-tools'); -const { prisma } = require('../../prisma'); - - -const signEvent = async (req, res) => { - try { - const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie) - const user = await getUserByPubKey(userPubKey); - - if (!user) - return res.status(401).json({ status: 'ERROR', reason: 'Not Authenticated' }); - - let prvkey = user.nostr_prv_key, pubkey = user.nostr_pub_key; - - if (!prvkey) { - prvkey = generatePrivateKey(); - pubkey = getPublicKey(prvkey); - - await prisma.user.update({ - where: { - id: user.id, - }, - data: { - nostr_prv_key: prvkey, - nostr_pub_key: pubkey - } - }) - } - - const { content, tags, kind = 1 } = req.body.event - const event = { - kind, - pubkey, - content, - tags, - created_at: Math.round(Date.now() / 1000), - } - - event.sig = await signNostrEvent(event, prvkey); - - return res - .status(200) - .json({ event }); - } catch (error) { - console.log(error); - res.status(500).send("Unexpected error happened, please try again") - } - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.post('/nostr-sign-event', signEvent); -} -else { - const router = express.Router(); - router.post('/nostr-sign-event', signEvent) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/pubkeys-to-users/pubkeys-to-users.js b/api/functions/pubkeys-to-users/pubkeys-to-users.js deleted file mode 100644 index f8bb7f7..0000000 --- a/api/functions/pubkeys-to-users/pubkeys-to-users.js +++ /dev/null @@ -1,62 +0,0 @@ - -const serverless = require('serverless-http'); -const { createExpressApp } = require('../../modules'); -const express = require('express'); -const extractKeyFromCookie = require('../../utils/extractKeyFromCookie'); -const { getUserByPubKey } = require('../../auth/utils/helperFuncs'); -const { prisma } = require('../../prisma'); - - -const mapPubkeysToUsers = async (req, res) => { - try { - - const pubkeys = req.body.pubkeys ?? []; - - const usersArr = await prisma.user.findMany({ - where: { - nostr_pub_key: { - in: pubkeys - } - }, - select: { - id: true, - name: true, - avatar: true, - nostr_pub_key: true, - lightning_address: true - } - }) - - let pubkeysToUsers = {} - usersArr.forEach(user => { - pubkeysToUsers[user.nostr_pub_key] = user; - }); - - return res - .status(200) - .json({ pubkeysToUsers }); - } catch (error) { - console.log(error); - res.status(500).send("Unexpected error happened, please try again") - } - -} - - -let app; - -if (process.env.LOCAL) { - app = createExpressApp() - app.post('/pubkeys-to-users', mapPubkeysToUsers); -} -else { - const router = express.Router(); - router.post('/pubkeys-to-users', mapPubkeysToUsers) - app = createExpressApp(router) -} - - -const handler = serverless(app); -exports.handler = async (event, context) => { - return await handler(event, context); -}; diff --git a/api/functions/upload-image-url/upload-image-url.js b/api/functions/upload-image-url/upload-image-url.js deleted file mode 100644 index 91f0eb7..0000000 --- a/api/functions/upload-image-url/upload-image-url.js +++ /dev/null @@ -1,53 +0,0 @@ -const serverless = require('serverless-http') -const { createExpressApp } = require('../../modules') -const express = require('express') -const extractKeyFromCookie = require('../../utils/extractKeyFromCookie') -const { getUserByPubKey } = require('../../auth/utils/helperFuncs') -const { getDirectUploadUrl } = require('../../services/imageUpload.service') -const { prisma } = require('../../prisma') -const { getUrlFromProvider } = require('../../utils/resolveImageUrl') - -const postUploadImageUrl = async (req, res) => { - - const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie) - const user = await getUserByPubKey(userPubKey) - - if (!user) return res.status(401).json({ status: 'ERROR', reason: 'Not Authenticated' }) - - const { filename } = req.body - - if (!filename) return res.status(422).json({ status: 'ERROR', reason: "The field 'filename' is required`" }) - - try { - const uploadUrl = await getDirectUploadUrl() - - const hostedImage = await prisma.hostedImage.create({ - data: { - filename, - url: getUrlFromProvider(uploadUrl.provider, uploadUrl.id), - provider_image_id: uploadUrl.id, - provider: uploadUrl.provider - }, - }) - - return res.status(200).json({ id: hostedImage.id, uploadURL: uploadUrl.uploadURL }) - } catch (error) { - res.status(500).send('Unexpected error happened, please try again') - } -} - -let app - -if (process.env.LOCAL) { - app = createExpressApp() - app.post('/upload-image-url', postUploadImageUrl) -} else { - const router = express.Router() - router.post('/upload-image-url', postUploadImageUrl) - app = createExpressApp(router) -} - -const handler = serverless(app) -exports.handler = async (event, context) => { - return await handler(event, context) -} diff --git a/api/modules/express-app.js b/api/modules/express-app.js deleted file mode 100644 index f541e49..0000000 --- a/api/modules/express-app.js +++ /dev/null @@ -1,32 +0,0 @@ - -const express = require('express'); -const cors = require('cors'); -const cookieParser = require('cookie-parser'); -const bodyParser = require('body-parser') - - -const createExpressApp = (router) => { - - const app = express(); - const routerBasePath = process.env.LOCAL ? `/dev` : `/.netlify/functions` - - // parse application/x-www-form-urlencoded - app.use(bodyParser.urlencoded({ extended: false })) - - // parse application/json - app.use(bodyParser.json()) - - app.use(cookieParser()); - app.use(cors({ - origin: ['http://localhost:3000', 'https://studio.apollographql.com'], - credentials: true, - })) - - if (router) - app.use(routerBasePath, router); - - return app; -} - - -module.exports = createExpressApp; \ No newline at end of file diff --git a/api/modules/index.js b/api/modules/index.js deleted file mode 100644 index 068c677..0000000 --- a/api/modules/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const createExpressApp = require("./express-app"); - - -module.exports = { - createExpressApp, -} \ No newline at end of file diff --git a/api/prisma/index.d.ts b/api/prisma/index.d.ts deleted file mode 100644 index ed0aebd..0000000 --- a/api/prisma/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PrismaClient } from '@prisma/client' - -export const prisma: PrismaClient; diff --git a/api/prisma/index.js b/api/prisma/index.js deleted file mode 100644 index a63f077..0000000 --- a/api/prisma/index.js +++ /dev/null @@ -1,19 +0,0 @@ -const { PrismaClient } = process.env.PRISMA_GENERATE_DATAPROXY ? require('@prisma/client/edge') : require('@prisma/client'); -const createGlobalModule = require('../utils/createGlobalModule'); - - -const createPrismaClient = () => { - console.log("New Prisma Client"); - try { - return new PrismaClient(); - } catch (error) { - console.log(error); - } -} - -const prisma = createGlobalModule('prisma', createPrismaClient) - - -module.exports = { - prisma -} \ No newline at end of file diff --git a/api/services/imageUpload.service.js b/api/services/imageUpload.service.js deleted file mode 100644 index ef63701..0000000 --- a/api/services/imageUpload.service.js +++ /dev/null @@ -1,98 +0,0 @@ -const { CONSTS } = require('../utils') -const axios = require('axios') -const FormData = require('form-data') -const { prisma } = require('../prisma') - -const BASE_URL = 'https://api.cloudflare.com/client/v4' - -const operationUrls = { - 'image.uploadUrl': `${BASE_URL}/accounts/${CONSTS.CLOUDFLARE_IMAGE_ACCOUNT_ID}/images/v2/direct_upload`, - 'image.delete': `${BASE_URL}/accounts/${CONSTS.CLOUDFLARE_IMAGE_ACCOUNT_ID}/images/v1/`, -} - -function getAxiosConfig() { - return { - headers: { - Authorization: `Bearer ${CONSTS.CLOUDFLARE_IMAGE_API_KEY}`, - }, - } -} - -async function getDirectUploadUrl() { - const url = operationUrls['image.uploadUrl'] - - const formData = new FormData() - formData.append('requireSignedURLs', 'false') - - const config = { - headers: { - Authorization: `Bearer ${CONSTS.CLOUDFLARE_IMAGE_API_KEY}`, - ...formData.getHeaders(), - }, - } - - const result = await axios.post(url, formData, config) - - if (!result.data.success) { - throw new Error(result.data, { cause: result.data.errors }) - } - - const data = result.data.result - - return { id: data.id, uploadURL: data.uploadURL, provider: 'cloudflare' } -} - -async function deleteImageFromProvider(providerImageId) { - try { - const url = operationUrls['image.delete'] + providerImageId - const result = await axios.delete(url, getAxiosConfig()) - - if (!result.data.success) { - throw new Error(result.data, { cause: result.data.errors }) - } - } catch (error) { - throw error - } -} - -async function deleteImage(hostedImageId) { - if (!hostedImageId) throw new Error("argument 'hostedImageId' must be provider") - - const hostedImage = await prisma.hostedImage.findFirst({ - where: { - id: hostedImageId, - }, - }) - - if (!hostedImage) throw new Error(`No HostedImage row found for HostedImage.id=${hostedImageId}`) - if (hostedImage.provider_image_id && hostedImage.provider_image_id === '') - throw new Error(`Field 'provider_image_id' for HostedImage.id=${hostedImageId} must not be empty. Current value '${hostedImage.provider_image_id}'`) - - // Set is_used to false in case of deletion fail from the hosting image provider. The scheduled job will try to delete the HostedImage row - await prisma.hostedImage.update({ - where: { - id: hostedImage.id, - }, - data: { - is_used: false, - }, - }) - - if (hostedImage.provider_image_id && hostedImage.provider_image_id !== '') { - deleteImageFromProvider(hostedImage.provider_image_id) - .then(async () => { - await prisma.hostedImage.delete({ - where: { - id: hostedImageId, - }, - }) - }) - .catch((error) => console.error(error)) - } -} - -module.exports = { - getDirectUploadUrl, - deleteImage, - deleteImageFromProvider, -} diff --git a/api/utils/consts.js b/api/utils/consts.js deleted file mode 100644 index bc62418..0000000 --- a/api/utils/consts.js +++ /dev/null @@ -1,17 +0,0 @@ -const BOLT_FUN_LIGHTNING_ADDRESS = 'johns@getalby.com' // #TODO, replace it by bolt-fun lightning address if there exist one -const JWT_SECRET = process.env.JWT_SECRET -const LNURL_AUTH_HOST = process.env.LNURL_AUTH_HOST -const CLOUDFLARE_IMAGE_ACCOUNT_ID = process.env.CLOUDFLARE_IMAGE_ACCOUNT_ID -const CLOUDFLARE_IMAGE_API_KEY = process.env.CLOUDFLARE_IMAGE_API_KEY -const CLOUDFLARE_IMAGE_ACCOUNT_HASH = process.env.CLOUDFLARE_IMAGE_ACCOUNT_HASH - -const CONSTS = { - JWT_SECRET, - BOLT_FUN_LIGHTNING_ADDRESS, - LNURL_AUTH_HOST, - CLOUDFLARE_IMAGE_ACCOUNT_ID, - CLOUDFLARE_IMAGE_API_KEY, - CLOUDFLARE_IMAGE_ACCOUNT_HASH -} - -module.exports = CONSTS diff --git a/api/utils/createGlobalModule.js b/api/utils/createGlobalModule.js deleted file mode 100644 index c1a0234..0000000 --- a/api/utils/createGlobalModule.js +++ /dev/null @@ -1,9 +0,0 @@ -const createGlobalModule = (name, factoryFn) => { - if (!global[name]) { - global[name] = factoryFn(); - } - return global[name]; -} - -module.exports = createGlobalModule - diff --git a/api/utils/extractKeyFromCookie.js b/api/utils/extractKeyFromCookie.js deleted file mode 100644 index 6be9c6a..0000000 --- a/api/utils/extractKeyFromCookie.js +++ /dev/null @@ -1,22 +0,0 @@ - -const cookie = require('cookie') -const jose = require('jose'); -const { JWT_SECRET } = require("./consts"); - -const extractKeyFromCookie = async (cookieHeader) => { - const cookies = cookie.parse(cookieHeader ?? ''); - const token = cookies.Authorization; - if (token) { - try { - const { payload } = await jose.jwtVerify(token, Buffer.from(JWT_SECRET), { - algorithms: ['HS256'], - }) - return payload.pubKey - } catch (error) { - return null - } - } - return null; -} - -module.exports = extractKeyFromCookie; \ No newline at end of file diff --git a/api/utils/generateId.js b/api/utils/generateId.js deleted file mode 100644 index ecb03f3..0000000 --- a/api/utils/generateId.js +++ /dev/null @@ -1,6 +0,0 @@ - -const crypto = require('crypto'); - -const generateId = () => crypto.randomUUID({}); - -module.exports = generateId; \ No newline at end of file diff --git a/api/utils/index.js b/api/utils/index.js deleted file mode 100644 index 29afb78..0000000 --- a/api/utils/index.js +++ /dev/null @@ -1,5 +0,0 @@ - -module.exports = { - CONSTS: require('./consts'), - nostr_tools: require('./nostr-tools') -} \ No newline at end of file diff --git a/api/utils/logger.js b/api/utils/logger.js deleted file mode 100644 index 5bc72ab..0000000 --- a/api/utils/logger.js +++ /dev/null @@ -1,9 +0,0 @@ - -function logError(error) { - console.log("Unexpected Error: "); - console.log(error); -} - -module.exports = { - logError -} \ No newline at end of file diff --git a/api/utils/nostr-tools.js b/api/utils/nostr-tools.js deleted file mode 100644 index 2577efe..0000000 --- a/api/utils/nostr-tools.js +++ /dev/null @@ -1,69 +0,0 @@ -// import * as secp256k1 from '@noble/secp256k1' -// import { Buffer } from 'buffer' -const secp256k1 = require('@noble/secp256k1'); -const crypto = require('crypto') - -function generatePrivateKey() { - return Buffer.from(secp256k1.utils.randomPrivateKey()).toString('hex') -} - -function getPublicKey(privateKey) { - return Buffer.from(secp256k1.schnorr.getPublicKey(privateKey)).toString('hex') -} - - -function serializeEvent(evt) { - return JSON.stringify([ - 0, - evt.pubkey, - evt.created_at, - evt.kind, - evt.tags, - evt.content - ]) -} - - -function getEventHash(event) { - let eventHash = crypto.createHash('sha256') - .update(Buffer.from(serializeEvent(event))) - .digest() - return Buffer.from(eventHash).toString('hex') -} - - -async function signEvent(event, key) { - return Buffer.from( - await secp256k1.schnorr.sign(getEventHash(event), key) - ).toString('hex') -} - -function validateEvent(event) { - if (event.id !== getEventHash(event)) return false - if (typeof event.content !== 'string') return false - if (typeof event.created_at !== 'number') return false - - if (!Array.isArray(event.tags)) return false - for (let i = 0; i < event.tags.length; i++) { - let tag = event.tags[i] - if (!Array.isArray(tag)) return false - for (let j = 0; j < tag.length; j++) { - if (typeof tag[j] === 'object') return false - } - } - - return true -} - -function verifySignature(event) { - return secp256k1.schnorr.verify(event.sig, event.id, event.pubkey) -} - - -module.exports = { - generatePrivateKey, - getPublicKey, - signEvent, - validateEvent, - verifySignature, -} \ No newline at end of file diff --git a/api/utils/resolveImageUrl.js b/api/utils/resolveImageUrl.js deleted file mode 100644 index 40931ed..0000000 --- a/api/utils/resolveImageUrl.js +++ /dev/null @@ -1,45 +0,0 @@ -const { CLOUDFLARE_IMAGE_ACCOUNT_HASH } = require('./consts') - -const PROVIDERS = [ - { - name: 'cloudflare', - prefixUrl: `https://imagedelivery.net/${CLOUDFLARE_IMAGE_ACCOUNT_HASH}/`, - variants: [ - { - default: true, - name: 'public', - }, - ], - }, -] - -/** - * resolveImgObjectToUrl - * @param {object} imgObject - * @param {string} variant - List to be defined. DEFAULT TO 'public' - * @returns {string} image url - */ -function resolveImgObjectToUrl(imgObject, variant = null) { - if (!imgObject) return null; - - if (imgObject.provider === 'external') { - return imgObject.url - } - - return getUrlFromProvider(imgObject.provider, imgObject.provider_image_id, variant) -} - -function getUrlFromProvider(provider, providerImageId, variant = null) { - const p = PROVIDERS.find((p) => p.name === provider) - - if (p) { - if (p && p.name === 'cloudflare') { - const variantName = variant ?? p.variants.find((v) => v.default).name - return p.prefixUrl + providerImageId + '/' + variantName - } - } - - throw new Error('Hosting images provider not supported') -} - -module.exports = { resolveImgObjectToUrl, getUrlFromProvider } diff --git a/netlify.toml b/netlify.toml index e8e832f..83ef30c 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,11 +1,7 @@ - -[build] - functions = "api/functions" # netlify-lambda builds to this folder AND Netlify reads functions from here - + [dev] framework = "#static" - functions = "api/functions" # netlify-lambda builds to this folder AND Netlify reads functions from here publish = "build" # create-react-app builds to this folder, Netlify should serve all these files statically \ No newline at end of file diff --git a/package.json b/package.json index 8bdb1f2..c13d38a 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "makers-bolt-fun", + "name": "lightning-landscape", "version": "0.1.0", "private": true, "dependencies": { @@ -99,31 +99,14 @@ }, "scripts": { "client:dev-server": "env-cmd -f ./envs/client/dev-server.env react-scripts start", - "server:dev": "env-cmd -f ./envs/server/local.env serverless offline", "client:preview-server": "env-cmd -f ./envs/client/preview-server.env react-scripts start", - "server:preview": "env-cmd -f ./envs/server/preview.env serverless offline", - "client:prod-server": "env-cmd -f ./envs/client/prod-server.env react-scripts start", - "server:prod": "env-cmd -f ./envs/server/prod.env serverless offline", - "client:mocks": "env-cmd -f ./envs/client/mock-server.env react-scripts start", "generate-graphql": "graphql-codegen", - "storybook": "env-cmd -f ./envs/client/preview-server.env start-storybook -p 6006 -s public", - "storybook:mocks": "env-cmd -f ./envs/client/mock-server.env start-storybook -p 6006 -s public", "build": "react-scripts build", "build:mocks": "env-cmd -f ./envs/client/mock-server.env react-scripts build", - "build-storybook": "env-cmd -f ./envs/client/preview-server.env build-storybook -s public", - "build-storybook:mocks": "env-cmd -f ./envs/client/mock-server.env build-storybook -s public", "test": "react-scripts test", "eject": "react-scripts eject", - "db:migrate-dev": "prisma migrate dev", - "db:migrate-deploy": "prisma migrate deploy", - "db:reset": "prisma migrate reset", - "db:seed": "prisma db seed", - "db:gui": "prisma studio", "netlify:start": "set NETLIFY=true&& netlify dev" }, - "prisma": { - "seed": "node prisma/seed/index.js" - }, "eslintConfig": { "extends": [ "react-app", diff --git a/prisma/migrations/20211128173513_init/migration.sql b/prisma/migrations/20211128173513_init/migration.sql deleted file mode 100644 index 9812f94..0000000 --- a/prisma/migrations/20211128173513_init/migration.sql +++ /dev/null @@ -1,41 +0,0 @@ --- CreateTable -CREATE TABLE "Category" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - - CONSTRAINT "Category_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Project" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "description" TEXT NOT NULL, - "website" TEXT NOT NULL, - "thumbnail_image" TEXT, - "cover_image" TEXT, - "category_id" INTEGER NOT NULL, - "votes_count" INTEGER NOT NULL DEFAULT 0, - "lightning_address" TEXT, - - CONSTRAINT "Project_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Vote" ( - "id" SERIAL NOT NULL, - "project_id" INTEGER NOT NULL, - "amount_in_sat" INTEGER NOT NULL, - "payment_request" TEXT, - "payment_hash" TEXT, - "preimage" TEXT, - "paid" BOOLEAN NOT NULL DEFAULT false, - - CONSTRAINT "Vote_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "Category"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Vote" ADD CONSTRAINT "Vote_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20211128213034_add_created_at_to_project/migration.sql b/prisma/migrations/20211128213034_add_created_at_to_project/migration.sql deleted file mode 100644 index 6a2df84..0000000 --- a/prisma/migrations/20211128213034_add_created_at_to_project/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ADD COLUMN "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/migrations/20211129045548_add_lnurl_callback_url_to_project/migration.sql b/prisma/migrations/20211129045548_add_lnurl_callback_url_to_project/migration.sql deleted file mode 100644 index 8045323..0000000 --- a/prisma/migrations/20211129045548_add_lnurl_callback_url_to_project/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ADD COLUMN "lnurl_callback_url" TEXT; diff --git a/prisma/migrations/20220320102659_add_category_fields_and_project_screenshots/migration.sql b/prisma/migrations/20220320102659_add_category_fields_and_project_screenshots/migration.sql deleted file mode 100644 index fdc23a8..0000000 --- a/prisma/migrations/20220320102659_add_category_fields_and_project_screenshots/migration.sql +++ /dev/null @@ -1,20 +0,0 @@ --- AlterTable -ALTER TABLE "Category" ADD COLUMN "cover_image" TEXT, -ADD COLUMN "icon" TEXT; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "screenshots" TEXT[]; - --- CreateTable -CREATE TABLE "Award" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "cover_image" TEXT NOT NULL, - "icon" TEXT NOT NULL, - "project_id" INTEGER NOT NULL, - - CONSTRAINT "Award_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Award" ADD CONSTRAINT "Award_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20220320103516_change_awards/migration.sql b/prisma/migrations/20220320103516_change_awards/migration.sql deleted file mode 100644 index 3c571ce..0000000 --- a/prisma/migrations/20220320103516_change_awards/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `cover_image` on the `Award` table. All the data in the column will be lost. - - You are about to drop the column `icon` on the `Award` table. All the data in the column will be lost. - - Added the required column `image` to the `Award` table without a default value. This is not possible if the table is not empty. - - Added the required column `url` to the `Award` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Award" DROP COLUMN "cover_image", -DROP COLUMN "icon", -ADD COLUMN "image" TEXT NOT NULL, -ADD COLUMN "url" TEXT NOT NULL; diff --git a/prisma/migrations/20220320103733_add_tags/migration.sql b/prisma/migrations/20220320103733_add_tags/migration.sql deleted file mode 100644 index 6f41b5e..0000000 --- a/prisma/migrations/20220320103733_add_tags/migration.sql +++ /dev/null @@ -1,25 +0,0 @@ --- CreateTable -CREATE TABLE "Tag" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - - CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_ProjectToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_ProjectToTag_AB_unique" ON "_ProjectToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_ProjectToTag_B_index" ON "_ProjectToTag"("B"); - --- AddForeignKey -ALTER TABLE "_ProjectToTag" ADD FOREIGN KEY ("A") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_ProjectToTag" ADD FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20220320153147_unique_tags/migration.sql b/prisma/migrations/20220320153147_unique_tags/migration.sql deleted file mode 100644 index c76ea63..0000000 --- a/prisma/migrations/20220320153147_unique_tags/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[title]` on the table `Tag` will be added. If there are existing duplicate values, this will fail. - -*/ --- CreateIndex -CREATE UNIQUE INDEX "Tag_title_key" ON "Tag"("title"); diff --git a/prisma/migrations/20220519165912_add_stories_questions_users/migration.sql b/prisma/migrations/20220519165912_add_stories_questions_users/migration.sql deleted file mode 100644 index 1120c4c..0000000 --- a/prisma/migrations/20220519165912_add_stories_questions_users/migration.sql +++ /dev/null @@ -1,159 +0,0 @@ --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "username" TEXT NOT NULL, - "lightning_address" TEXT, - "avatar" TEXT NOT NULL, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Story" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "body" TEXT NOT NULL, - "thumbnail_image" TEXT NOT NULL, - "cover_image" TEXT NOT NULL, - "votes_count" INTEGER NOT NULL DEFAULT 0, - "topic_id" INTEGER NOT NULL, - "user_id" INTEGER, - - CONSTRAINT "Story_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Question" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "body" TEXT NOT NULL, - "thumbnail_image" TEXT NOT NULL, - "votes_count" INTEGER NOT NULL DEFAULT 0, - "topic_id" INTEGER NOT NULL, - "user_id" INTEGER, - - CONSTRAINT "Question_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Topic" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "icon" TEXT NOT NULL, - - CONSTRAINT "Topic_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "PostComment" ( - "id" SERIAL NOT NULL, - "body" TEXT NOT NULL, - "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "votes_count" INTEGER NOT NULL DEFAULT 0, - "parent_comment_id" INTEGER, - "user_id" INTEGER, - "story_id" INTEGER, - "question_id" INTEGER, - - CONSTRAINT "PostComment_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Hackathon" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "date" TEXT NOT NULL, - "cover_image" TEXT NOT NULL, - "description" TEXT NOT NULL, - "location" TEXT NOT NULL, - "website" TEXT NOT NULL, - "votes_count" INTEGER NOT NULL DEFAULT 0, - - CONSTRAINT "Hackathon_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_StoryToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateTable -CREATE TABLE "_QuestionToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateTable -CREATE TABLE "_HackathonToTopic" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "User_username_key" ON "User"("username"); - --- CreateIndex -CREATE UNIQUE INDEX "Topic_title_key" ON "Topic"("title"); - --- CreateIndex -CREATE UNIQUE INDEX "_StoryToTag_AB_unique" ON "_StoryToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_StoryToTag_B_index" ON "_StoryToTag"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_QuestionToTag_AB_unique" ON "_QuestionToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_QuestionToTag_B_index" ON "_QuestionToTag"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_HackathonToTopic_AB_unique" ON "_HackathonToTopic"("A", "B"); - --- CreateIndex -CREATE INDEX "_HackathonToTopic_B_index" ON "_HackathonToTopic"("B"); - --- AddForeignKey -ALTER TABLE "Story" ADD CONSTRAINT "Story_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Story" ADD CONSTRAINT "Story_topic_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "Topic"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Question" ADD CONSTRAINT "Question_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Question" ADD CONSTRAINT "Question_topic_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "Topic"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_story_id_fkey" FOREIGN KEY ("story_id") REFERENCES "Story"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_question_id_fkey" FOREIGN KEY ("question_id") REFERENCES "Question"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_parent_comment_id_fkey" FOREIGN KEY ("parent_comment_id") REFERENCES "PostComment"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_StoryToTag" ADD FOREIGN KEY ("A") REFERENCES "Story"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_StoryToTag" ADD FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_QuestionToTag" ADD FOREIGN KEY ("A") REFERENCES "Question"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_QuestionToTag" ADD FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_HackathonToTopic" ADD FOREIGN KEY ("A") REFERENCES "Hackathon"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_HackathonToTopic" ADD FOREIGN KEY ("B") REFERENCES "Topic"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20220519171237_add_created_at_updated_at_to_stories_questions/migration.sql b/prisma/migrations/20220519171237_add_created_at_updated_at_to_stories_questions/migration.sql deleted file mode 100644 index d2b44df..0000000 --- a/prisma/migrations/20220519171237_add_created_at_updated_at_to_stories_questions/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `created_at` on the `PostComment` table. All the data in the column will be lost. - - You are about to drop the column `date` on the `Question` table. All the data in the column will be lost. - - You are about to drop the column `date` on the `Story` table. All the data in the column will be lost. - - Added the required column `updatedAt` to the `Question` table without a default value. This is not possible if the table is not empty. - - Added the required column `updatedAt` to the `Story` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "PostComment" DROP COLUMN "created_at", -ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "Question" DROP COLUMN "date", -ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; - --- AlterTable -ALTER TABLE "Story" DROP COLUMN "date", -ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; diff --git a/prisma/migrations/20220520054239_remove_thumbnail_img_col/migration.sql b/prisma/migrations/20220520054239_remove_thumbnail_img_col/migration.sql deleted file mode 100644 index 1f692cf..0000000 --- a/prisma/migrations/20220520054239_remove_thumbnail_img_col/migration.sql +++ /dev/null @@ -1,20 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `date` on the `Hackathon` table. All the data in the column will be lost. - - You are about to drop the column `thumbnail_image` on the `Question` table. All the data in the column will be lost. - - You are about to drop the column `thumbnail_image` on the `Story` table. All the data in the column will be lost. - - Added the required column `end_date` to the `Hackathon` table without a default value. This is not possible if the table is not empty. - - Added the required column `start_date` to the `Hackathon` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Hackathon" DROP COLUMN "date", -ADD COLUMN "end_date" DATE NOT NULL, -ADD COLUMN "start_date" DATE NOT NULL; - --- AlterTable -ALTER TABLE "Question" DROP COLUMN "thumbnail_image"; - --- AlterTable -ALTER TABLE "Story" DROP COLUMN "thumbnail_image"; diff --git a/prisma/migrations/20220520073846_rename_created_at_to_created_at/migration.sql b/prisma/migrations/20220520073846_rename_created_at_to_created_at/migration.sql deleted file mode 100644 index 5a9cc09..0000000 --- a/prisma/migrations/20220520073846_rename_created_at_to_created_at/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `created_at` on the `Project` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Project" DROP COLUMN "created_at", -ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/migrations/20220520084451_add_name_column_to_users_table/migration.sql b/prisma/migrations/20220520084451_add_name_column_to_users_table/migration.sql deleted file mode 100644 index d632f20..0000000 --- a/prisma/migrations/20220520084451_add_name_column_to_users_table/migration.sql +++ /dev/null @@ -1,17 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `username` on the `User` table. All the data in the column will be lost. - - A unique constraint covering the columns `[name]` on the table `User` will be added. If there are existing duplicate values, this will fail. - - Added the required column `name` to the `User` table without a default value. This is not possible if the table is not empty. - -*/ --- DropIndex -DROP INDEX "User_username_key"; - --- AlterTable -ALTER TABLE "User" DROP COLUMN "username", -ADD COLUMN "name" TEXT NOT NULL; - --- CreateIndex -CREATE UNIQUE INDEX "User_name_key" ON "User"("name"); diff --git a/prisma/migrations/20220520134308_add_excerpt_column_to_story_and_question/migration.sql b/prisma/migrations/20220520134308_add_excerpt_column_to_story_and_question/migration.sql deleted file mode 100644 index a338582..0000000 --- a/prisma/migrations/20220520134308_add_excerpt_column_to_story_and_question/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - Added the required column `excerpt` to the `Question` table without a default value. This is not possible if the table is not empty. - - Added the required column `excerpt` to the `Story` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Question" ADD COLUMN "excerpt" TEXT NOT NULL; - --- AlterTable -ALTER TABLE "Story" ADD COLUMN "excerpt" TEXT NOT NULL; diff --git a/prisma/migrations/20220521073620_make_vote_generic/migration.sql b/prisma/migrations/20220521073620_make_vote_generic/migration.sql deleted file mode 100644 index e31c22b..0000000 --- a/prisma/migrations/20220521073620_make_vote_generic/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `project_id` on the `Vote` table. All the data in the column will be lost. - - Added the required column `item_id` to the `Vote` table without a default value. This is not possible if the table is not empty. - - Added the required column `item_type` to the `Vote` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "Vote" DROP CONSTRAINT "Vote_project_id_fkey"; - --- AlterTable -ALTER TABLE "Vote" DROP COLUMN "project_id", -ADD COLUMN "item_id" INTEGER NOT NULL, -ADD COLUMN "item_type" TEXT NOT NULL; diff --git a/prisma/migrations/20220524142531_create_donations_table/migration.sql b/prisma/migrations/20220524142531_create_donations_table/migration.sql deleted file mode 100644 index f727b5a..0000000 --- a/prisma/migrations/20220524142531_create_donations_table/migration.sql +++ /dev/null @@ -1,16 +0,0 @@ --- CreateTable -CREATE TABLE "Donation" ( - "id" SERIAL NOT NULL, - "amount" INTEGER NOT NULL, - "createdAt" DATE NOT NULL DEFAULT CURRENT_TIMESTAMP, - "payment_request" TEXT, - "payment_hash" TEXT, - "preimage" TEXT, - "paid" BOOLEAN NOT NULL DEFAULT false, - "donor_id" INTEGER, - - CONSTRAINT "Donation_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Donation" ADD CONSTRAINT "Donation_donor_id_fkey" FOREIGN KEY ("donor_id") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220601065659_add_pub_key_to_user/migration.sql b/prisma/migrations/20220601065659_add_pub_key_to_user/migration.sql deleted file mode 100644 index b10c750..0000000 --- a/prisma/migrations/20220601065659_add_pub_key_to_user/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[pubKey]` on the table `User` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "User" ADD COLUMN "email" TEXT, -ADD COLUMN "pubKey" TEXT, -ADD COLUMN "website" TEXT, -ALTER COLUMN "avatar" DROP NOT NULL, -ALTER COLUMN "name" DROP NOT NULL; - --- CreateTable -CREATE TABLE "GeneratedK1" ( - "value" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "GeneratedK1_pkey" PRIMARY KEY ("value") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_pubKey_key" ON "User"("pubKey"); diff --git a/prisma/migrations/20220604062034_add_join_date_column_to_user/migration.sql b/prisma/migrations/20220604062034_add_join_date_column_to_user/migration.sql deleted file mode 100644 index 6148dc7..0000000 --- a/prisma/migrations/20220604062034_add_join_date_column_to_user/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "join_date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/migrations/20220604085918_add_new_cols_to_user/migration.sql b/prisma/migrations/20220604085918_add_new_cols_to_user/migration.sql deleted file mode 100644 index 26cd661..0000000 --- a/prisma/migrations/20220604085918_add_new_cols_to_user/migration.sql +++ /dev/null @@ -1,6 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "bio" TEXT, -ADD COLUMN "github" TEXT, -ADD COLUMN "location" TEXT, -ADD COLUMN "role" TEXT NOT NULL DEFAULT E'user', -ADD COLUMN "twitter" TEXT; diff --git a/prisma/migrations/20220604110334_add_more_cols_to_user_table/migration.sql b/prisma/migrations/20220604110334_add_more_cols_to_user_table/migration.sql deleted file mode 100644 index 330d7b9..0000000 --- a/prisma/migrations/20220604110334_add_more_cols_to_user_table/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "jobTitle" TEXT, -ADD COLUMN "linkedin" TEXT; diff --git a/prisma/migrations/20220607112221_add_sid_to_generatedk1_table/migration.sql b/prisma/migrations/20220607112221_add_sid_to_generatedk1_table/migration.sql deleted file mode 100644 index 296d0bf..0000000 --- a/prisma/migrations/20220607112221_add_sid_to_generatedk1_table/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "GeneratedK1" ADD COLUMN "sid" TEXT; diff --git a/prisma/migrations/20220614113018_drop_topics_and_update_tags/migration.sql b/prisma/migrations/20220614113018_drop_topics_and_update_tags/migration.sql deleted file mode 100644 index 9d25885..0000000 --- a/prisma/migrations/20220614113018_drop_topics_and_update_tags/migration.sql +++ /dev/null @@ -1,46 +0,0 @@ -/* - Warnings: - - - You are about to drop the `Topic` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `_HackathonToTopic` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "Question" DROP CONSTRAINT "Question_topic_id_fkey"; - --- DropForeignKey -ALTER TABLE "Story" DROP CONSTRAINT "Story_topic_id_fkey"; - --- DropForeignKey -ALTER TABLE "_HackathonToTopic" DROP CONSTRAINT "_HackathonToTopic_A_fkey"; - --- DropForeignKey -ALTER TABLE "_HackathonToTopic" DROP CONSTRAINT "_HackathonToTopic_B_fkey"; - --- AlterTable -ALTER TABLE "Tag" ADD COLUMN "icon" TEXT, -ADD COLUMN "isOfficial" BOOLEAN NOT NULL DEFAULT false; - --- DropTable -DROP TABLE "Topic"; - --- DropTable -DROP TABLE "_HackathonToTopic"; - --- CreateTable -CREATE TABLE "_HackathonToTag" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "_HackathonToTag_AB_unique" ON "_HackathonToTag"("A", "B"); - --- CreateIndex -CREATE INDEX "_HackathonToTag_B_index" ON "_HackathonToTag"("B"); - --- AddForeignKey -ALTER TABLE "_HackathonToTag" ADD FOREIGN KEY ("A") REFERENCES "Hackathon"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_HackathonToTag" ADD FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20220614124708_remove_topic_id_col/migration.sql b/prisma/migrations/20220614124708_remove_topic_id_col/migration.sql deleted file mode 100644 index b2fac15..0000000 --- a/prisma/migrations/20220614124708_remove_topic_id_col/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `topic_id` on the `Question` table. All the data in the column will be lost. - - You are about to drop the column `topic_id` on the `Story` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Question" DROP COLUMN "topic_id"; - --- AlterTable -ALTER TABLE "Story" DROP COLUMN "topic_id"; diff --git a/prisma/migrations/20220623155452_remove_unique_from_user_name/migration.sql b/prisma/migrations/20220623155452_remove_unique_from_user_name/migration.sql deleted file mode 100644 index 7258b14..0000000 --- a/prisma/migrations/20220623155452_remove_unique_from_user_name/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- DropIndex -DROP INDEX "User_name_key"; diff --git a/prisma/migrations/20220708131731_make_story_cover_image_optional/migration.sql b/prisma/migrations/20220708131731_make_story_cover_image_optional/migration.sql deleted file mode 100644 index a99de4b..0000000 --- a/prisma/migrations/20220708131731_make_story_cover_image_optional/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Story" ALTER COLUMN "cover_image" DROP NOT NULL; diff --git a/prisma/migrations/20220711095800_add_description_to_tags/migration.sql b/prisma/migrations/20220711095800_add_description_to_tags/migration.sql deleted file mode 100644 index d2cc7f8..0000000 --- a/prisma/migrations/20220711095800_add_description_to_tags/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Tag" ADD COLUMN "description" TEXT; diff --git a/prisma/migrations/20220712141806_add_is_published_field_to_story/migration.sql b/prisma/migrations/20220712141806_add_is_published_field_to_story/migration.sql deleted file mode 100644 index d91a82b..0000000 --- a/prisma/migrations/20220712141806_add_is_published_field_to_story/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Story" ADD COLUMN "is_published" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/migrations/20220712142314_make_story_published_by_default/migration.sql b/prisma/migrations/20220712142314_make_story_published_by_default/migration.sql deleted file mode 100644 index 5c790b9..0000000 --- a/prisma/migrations/20220712142314_make_story_published_by_default/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Story" ALTER COLUMN "is_published" SET DEFAULT true; diff --git a/prisma/migrations/20220719145740_add_nostr_keys/migration.sql b/prisma/migrations/20220719145740_add_nostr_keys/migration.sql deleted file mode 100644 index 40e8859..0000000 --- a/prisma/migrations/20220719145740_add_nostr_keys/migration.sql +++ /dev/null @@ -1,6 +0,0 @@ --- AlterTable -ALTER TABLE "Question" ADD COLUMN "is_published" BOOLEAN NOT NULL DEFAULT true; - --- AlterTable -ALTER TABLE "User" ADD COLUMN "nostr_prv_key" TEXT, -ADD COLUMN "nostr_pub_key" TEXT; diff --git a/prisma/migrations/20220720103112_update_created_at_comment_col/migration.sql b/prisma/migrations/20220720103112_update_created_at_comment_col/migration.sql deleted file mode 100644 index 654685d..0000000 --- a/prisma/migrations/20220720103112_update_created_at_comment_col/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `createdAt` on the `PostComment` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "PostComment" DROP COLUMN "createdAt", -ADD COLUMN "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/migrations/20220728122744_make_comments_id_string/migration.sql b/prisma/migrations/20220728122744_make_comments_id_string/migration.sql deleted file mode 100644 index dd674a8..0000000 --- a/prisma/migrations/20220728122744_make_comments_id_string/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ -/* - Warnings: - - - The primary key for the `PostComment` table will be changed. If it partially fails, the table could be left without primary key constraint. - -*/ --- DropForeignKey -ALTER TABLE "PostComment" DROP CONSTRAINT "PostComment_parent_comment_id_fkey"; - --- AlterTable -ALTER TABLE "PostComment" DROP CONSTRAINT "PostComment_pkey", -ALTER COLUMN "id" DROP DEFAULT, -ALTER COLUMN "id" SET DATA TYPE TEXT, -ALTER COLUMN "parent_comment_id" SET DATA TYPE TEXT, -ADD CONSTRAINT "PostComment_pkey" PRIMARY KEY ("id"); -DROP SEQUENCE "PostComment_id_seq"; - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_parent_comment_id_fkey" FOREIGN KEY ("parent_comment_id") REFERENCES "PostComment"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220728150508_change_comment_id_type/migration.sql b/prisma/migrations/20220728150508_change_comment_id_type/migration.sql deleted file mode 100644 index ec1822c..0000000 --- a/prisma/migrations/20220728150508_change_comment_id_type/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - Warnings: - - - The primary key for the `PostComment` table will be changed. If it partially fails, the table could be left without primary key constraint. - - The `id` column on the `PostComment` table would be dropped and recreated. This will lead to data loss if there is data in the column. - - The `parent_comment_id` column on the `PostComment` table would be dropped and recreated. This will lead to data loss if there is data in the column. - -*/ --- DropForeignKey -ALTER TABLE "PostComment" DROP CONSTRAINT "PostComment_parent_comment_id_fkey"; - --- AlterTable -ALTER TABLE "PostComment" DROP CONSTRAINT "PostComment_pkey", -ADD COLUMN "nostr_id" TEXT, -DROP COLUMN "id", -ADD COLUMN "id" SERIAL NOT NULL, -DROP COLUMN "parent_comment_id", -ADD COLUMN "parent_comment_id" INTEGER, -ADD CONSTRAINT "PostComment_pkey" PRIMARY KEY ("id"); - --- AddForeignKey -ALTER TABLE "PostComment" ADD CONSTRAINT "PostComment_parent_comment_id_fkey" FOREIGN KEY ("parent_comment_id") REFERENCES "PostComment"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220808073740_add_userkeys_table/migration.sql b/prisma/migrations/20220808073740_add_userkeys_table/migration.sql deleted file mode 100644 index 1d6b0e2..0000000 --- a/prisma/migrations/20220808073740_add_userkeys_table/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- CreateTable -CREATE TABLE "UserKey" ( - "key" TEXT NOT NULL, - "user_id" INTEGER, - - CONSTRAINT "UserKey_pkey" PRIMARY KEY ("key") -); - --- AddForeignKey -ALTER TABLE "UserKey" ADD CONSTRAINT "UserKey_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220809081452_add_name_to_user_key/migration.sql b/prisma/migrations/20220809081452_add_name_to_user_key/migration.sql deleted file mode 100644 index e04904a..0000000 --- a/prisma/migrations/20220809081452_add_name_to_user_key/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "UserKey" ADD COLUMN "name" TEXT NOT NULL DEFAULT E'New Key Name'; diff --git a/prisma/migrations/20220822112427_add_roles_skills_to_users_table/migration.sql b/prisma/migrations/20220822112427_add_roles_skills_to_users_table/migration.sql deleted file mode 100644 index e1a4a18..0000000 --- a/prisma/migrations/20220822112427_add_roles_skills_to_users_table/migration.sql +++ /dev/null @@ -1,57 +0,0 @@ --- AlterTable -ALTER TABLE "UserKey" ALTER COLUMN "name" SET DEFAULT E'My new wallet key'; - --- CreateTable -CREATE TABLE "UsersOnWorkRoles" ( - "userId" INTEGER NOT NULL, - "roleId" INTEGER NOT NULL, - - CONSTRAINT "UsersOnWorkRoles_pkey" PRIMARY KEY ("userId","roleId") -); - --- CreateTable -CREATE TABLE "WorkRole" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "icon" TEXT NOT NULL, - - CONSTRAINT "WorkRole_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Skill" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - - CONSTRAINT "Skill_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_SkillToUser" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "WorkRole_title_key" ON "WorkRole"("title"); - --- CreateIndex -CREATE UNIQUE INDEX "Skill_title_key" ON "Skill"("title"); - --- CreateIndex -CREATE UNIQUE INDEX "_SkillToUser_AB_unique" ON "_SkillToUser"("A", "B"); - --- CreateIndex -CREATE INDEX "_SkillToUser_B_index" ON "_SkillToUser"("B"); - --- AddForeignKey -ALTER TABLE "UsersOnWorkRoles" ADD CONSTRAINT "UsersOnWorkRoles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UsersOnWorkRoles" ADD CONSTRAINT "UsersOnWorkRoles_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "WorkRole"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_SkillToUser" ADD FOREIGN KEY ("A") REFERENCES "Skill"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_SkillToUser" ADD FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20220822113244_add_level_field_to_user_roles_table/migration.sql b/prisma/migrations/20220822113244_add_level_field_to_user_roles_table/migration.sql deleted file mode 100644 index 16db1e9..0000000 --- a/prisma/migrations/20220822113244_add_level_field_to_user_roles_table/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `level` to the `UsersOnWorkRoles` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "UsersOnWorkRoles" ADD COLUMN "level" TEXT NOT NULL; diff --git a/prisma/migrations/20220822122053_change_level_field_to_int/migration.sql b/prisma/migrations/20220822122053_change_level_field_to_int/migration.sql deleted file mode 100644 index 019c60e..0000000 --- a/prisma/migrations/20220822122053_change_level_field_to_int/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - Changed the type of `level` on the `UsersOnWorkRoles` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - -*/ --- AlterTable -ALTER TABLE "UsersOnWorkRoles" DROP COLUMN "level", -ADD COLUMN "level" INTEGER NOT NULL; diff --git a/prisma/migrations/20220825083012_add_hosted_image_table/migration.sql b/prisma/migrations/20220825083012_add_hosted_image_table/migration.sql deleted file mode 100644 index c02630d..0000000 --- a/prisma/migrations/20220825083012_add_hosted_image_table/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ --- CreateTable -CREATE TABLE "HostedImage" ( - "id" TEXT NOT NULL, - "filename" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "is_used" BOOLEAN NOT NULL DEFAULT false, - - CONSTRAINT "HostedImage_pkey" PRIMARY KEY ("id") -); diff --git a/prisma/migrations/20220831121710_update_hosted_image_table/migration.sql b/prisma/migrations/20220831121710_update_hosted_image_table/migration.sql deleted file mode 100644 index e25ab98..0000000 --- a/prisma/migrations/20220831121710_update_hosted_image_table/migration.sql +++ /dev/null @@ -1,29 +0,0 @@ -/* - Warnings: - - - The primary key for the `HostedImage` table will be changed. If it partially fails, the table could be left without primary key constraint. - - The `id` column on the `HostedImage` table would be dropped and recreated. This will lead to data loss if there is data in the column. - - Added the required column `provider` to the `HostedImage` table without a default value. This is not possible if the table is not empty. - - Added the required column `provider_image_id` to the `HostedImage` table without a default value. This is not possible if the table is not empty. - - Added the required column `url` to the `HostedImage` table without a default value. This is not possible if the table is not empty. - -*/ - --- START Custom SQL --- Because of the breaking changes, we have to apply some custom SQL. --- By chance, the previous HostedImage migration is not used it production, so we can remove all data from this table -DELETE FROM "HostedImage"; --- END Custom SQL - - --- AlterTable -ALTER TABLE "HostedImage" DROP CONSTRAINT "HostedImage_pkey", -ADD COLUMN "provider" TEXT NOT NULL, -ADD COLUMN "provider_image_id" TEXT NOT NULL, -ADD COLUMN "url" TEXT NOT NULL, -DROP COLUMN "id", -ADD COLUMN "id" SERIAL NOT NULL, -ADD CONSTRAINT "HostedImage_pkey" PRIMARY KEY ("id"); - --- AlterTable -ALTER TABLE "UserKey" ALTER COLUMN "name" SET DEFAULT E'My new wallet key'; diff --git a/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql b/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql deleted file mode 100644 index 54a0f2f..0000000 --- a/prisma/migrations/20220906083327_add_project_recruit_roles_tabel/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ --- CreateTable -CREATE TABLE "ProjectRecruitRoles" ( - "projectId" INTEGER NOT NULL, - "roleId" INTEGER NOT NULL, - "level" INTEGER NOT NULL, - - CONSTRAINT "ProjectRecruitRoles_pkey" PRIMARY KEY ("projectId","roleId") -); - --- AddForeignKey -ALTER TABLE "ProjectRecruitRoles" ADD CONSTRAINT "ProjectRecruitRoles_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "WorkRole"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ProjectRecruitRoles" ADD CONSTRAINT "ProjectRecruitRoles_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20220907081831_create_tournament_tables/migration.sql b/prisma/migrations/20220907081831_create_tournament_tables/migration.sql deleted file mode 100644 index 9b417f2..0000000 --- a/prisma/migrations/20220907081831_create_tournament_tables/migration.sql +++ /dev/null @@ -1,102 +0,0 @@ --- CreateTable -CREATE TABLE "Tournament" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "description" TEXT NOT NULL, - "thumbnail_image" TEXT NOT NULL, - "cover_image" TEXT NOT NULL, - "start_date" DATE NOT NULL, - "end_date" DATE NOT NULL, - "location" TEXT NOT NULL, - "website" TEXT NOT NULL, - "votes_count" INTEGER NOT NULL DEFAULT 0, - - CONSTRAINT "Tournament_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TournamentPrize" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "amount" TEXT NOT NULL, - "image" TEXT NOT NULL, - "tournament_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentPrize_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TournamentJudge" ( - "id" SERIAL NOT NULL, - "name" TEXT NOT NULL, - "company" TEXT NOT NULL, - "twitter" TEXT, - "tournament_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentJudge_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TournamentFAQ" ( - "id" SERIAL NOT NULL, - "question" TEXT NOT NULL, - "answer" TEXT NOT NULL, - "tournament_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentFAQ_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TournamentEvent" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "image" TEXT NOT NULL, - "description" TEXT NOT NULL, - "date" DATE NOT NULL, - "location" TEXT NOT NULL, - "website" TEXT NOT NULL, - "type" INTEGER NOT NULL, - "tournament_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentEvent_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "TournamentParticipant" ( - "tournament_id" INTEGER NOT NULL, - "user_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentParticipant_pkey" PRIMARY KEY ("tournament_id","user_id") -); - --- CreateTable -CREATE TABLE "TournamentProject" ( - "tournament_id" INTEGER NOT NULL, - "project_id" INTEGER NOT NULL, - - CONSTRAINT "TournamentProject_pkey" PRIMARY KEY ("tournament_id","project_id") -); - --- AddForeignKey -ALTER TABLE "TournamentPrize" ADD CONSTRAINT "TournamentPrize_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentJudge" ADD CONSTRAINT "TournamentJudge_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentFAQ" ADD CONSTRAINT "TournamentFAQ_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentEvent" ADD CONSTRAINT "TournamentEvent_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentParticipant" ADD CONSTRAINT "TournamentParticipant_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentParticipant" ADD CONSTRAINT "TournamentParticipant_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentProject" ADD CONSTRAINT "TournamentProject_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentProject" ADD CONSTRAINT "TournamentProject_tournament_id_fkey" FOREIGN KEY ("tournament_id") REFERENCES "Tournament"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql b/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql deleted file mode 100644 index 777faca..0000000 --- a/prisma/migrations/20220907083457_update_tournament_event_date_field/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `date` on the `TournamentEvent` table. All the data in the column will be lost. - - Added the required column `ends_at` to the `TournamentEvent` table without a default value. This is not possible if the table is not empty. - - Added the required column `starts_at` to the `TournamentEvent` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "TournamentEvent" DROP COLUMN "date", -ADD COLUMN "ends_at" DATE NOT NULL, -ADD COLUMN "starts_at" DATE NOT NULL; diff --git a/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql b/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql deleted file mode 100644 index 64ce7a1..0000000 --- a/prisma/migrations/20220907085319_add_avatar_to_tournament_judge/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `avatar` to the `TournamentJudge` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "TournamentJudge" ADD COLUMN "avatar" TEXT NOT NULL; diff --git a/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql b/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql deleted file mode 100644 index 2b563a1..0000000 --- a/prisma/migrations/20220908065418_add_email_and_hackingstatus_to_tournament_participant/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - Added the required column `email` to the `TournamentParticipant` table without a default value. This is not possible if the table is not empty. - - Added the required column `hacking_status` to the `TournamentParticipant` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "TournamentParticipant" ADD COLUMN "email" TEXT NOT NULL, -ADD COLUMN "hacking_status" INTEGER NOT NULL; diff --git a/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql b/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql deleted file mode 100644 index 4bb777b..0000000 --- a/prisma/migrations/20220909043627_add_created_at_to_keys_and_participations/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "TournamentParticipant" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; - --- AlterTable -ALTER TABLE "UserKey" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql b/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql deleted file mode 100644 index 3834a6f..0000000 --- a/prisma/migrations/20220909064845_add_discord_to_user_table/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "discord" TEXT; diff --git a/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql b/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql deleted file mode 100644 index b5dd52e..0000000 --- a/prisma/migrations/20220911174549_remove_only_date_constraints/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- AlterTable -ALTER TABLE "Donation" ALTER COLUMN "createdAt" SET DATA TYPE TIMESTAMP(3); - --- AlterTable -ALTER TABLE "Tournament" ALTER COLUMN "start_date" SET DATA TYPE TIMESTAMP(3), -ALTER COLUMN "end_date" SET DATA TYPE TIMESTAMP(3); - --- AlterTable -ALTER TABLE "TournamentEvent" ALTER COLUMN "ends_at" SET DATA TYPE TIMESTAMP(3), -ALTER COLUMN "starts_at" SET DATA TYPE TIMESTAMP(3); diff --git a/prisma/migrations/20220912140653_update_hosted_image_rel_table/migration.sql b/prisma/migrations/20220912140653_update_hosted_image_rel_table/migration.sql deleted file mode 100644 index 4e5eb9a..0000000 --- a/prisma/migrations/20220912140653_update_hosted_image_rel_table/migration.sql +++ /dev/null @@ -1,74 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[image_id]` on the table `Award` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[cover_image_id]` on the table `Category` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[cover_image_id]` on the table `Hackathon` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[thumbnail_image_id]` on the table `Project` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[cover_image_id]` on the table `Project` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[cover_image_id]` on the table `Story` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[avatar_id]` on the table `User` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "Award" ADD COLUMN "image_id" INTEGER; - --- AlterTable -ALTER TABLE "Category" ADD COLUMN "cover_image_id" INTEGER; - --- AlterTable -ALTER TABLE "Hackathon" ADD COLUMN "cover_image_id" INTEGER; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "cover_image_id" INTEGER, -ADD COLUMN "screenshots_ids" INTEGER[], -ADD COLUMN "thumbnail_image_id" INTEGER; - --- AlterTable -ALTER TABLE "Story" ADD COLUMN "body_image_ids" INTEGER[], -ADD COLUMN "cover_image_id" INTEGER; - --- AlterTable -ALTER TABLE "User" ADD COLUMN "avatar_id" INTEGER; - --- CreateIndex -CREATE UNIQUE INDEX "Award_image_id_key" ON "Award"("image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Category_cover_image_id_key" ON "Category"("cover_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Hackathon_cover_image_id_key" ON "Hackathon"("cover_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Project_thumbnail_image_id_key" ON "Project"("thumbnail_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Project_cover_image_id_key" ON "Project"("cover_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Story_cover_image_id_key" ON "Story"("cover_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "User_avatar_id_key" ON "User"("avatar_id"); - --- AddForeignKey -ALTER TABLE "User" ADD CONSTRAINT "User_avatar_id_fkey" FOREIGN KEY ("avatar_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Category" ADD CONSTRAINT "Category_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_thumbnail_image_id_fkey" FOREIGN KEY ("thumbnail_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Award" ADD CONSTRAINT "Award_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Story" ADD CONSTRAINT "Story_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Hackathon" ADD CONSTRAINT "Hackathon_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220913134026_update_tournament_image_rel/migration.sql b/prisma/migrations/20220913134026_update_tournament_image_rel/migration.sql deleted file mode 100644 index 038339d..0000000 --- a/prisma/migrations/20220913134026_update_tournament_image_rel/migration.sql +++ /dev/null @@ -1,52 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[thumbnail_image_id]` on the table `Tournament` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[cover_image_id]` on the table `Tournament` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[image_id]` on the table `TournamentEvent` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[avatar_id]` on the table `TournamentJudge` will be added. If there are existing duplicate values, this will fail. - - A unique constraint covering the columns `[image_id]` on the table `TournamentPrize` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "Tournament" ADD COLUMN "cover_image_id" INTEGER, -ADD COLUMN "thumbnail_image_id" INTEGER; - --- AlterTable -ALTER TABLE "TournamentEvent" ADD COLUMN "image_id" INTEGER; - --- AlterTable -ALTER TABLE "TournamentJudge" ADD COLUMN "avatar_id" INTEGER; - --- AlterTable -ALTER TABLE "TournamentPrize" ADD COLUMN "image_id" INTEGER; - --- CreateIndex -CREATE UNIQUE INDEX "Tournament_thumbnail_image_id_key" ON "Tournament"("thumbnail_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "Tournament_cover_image_id_key" ON "Tournament"("cover_image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "TournamentEvent_image_id_key" ON "TournamentEvent"("image_id"); - --- CreateIndex -CREATE UNIQUE INDEX "TournamentJudge_avatar_id_key" ON "TournamentJudge"("avatar_id"); - --- CreateIndex -CREATE UNIQUE INDEX "TournamentPrize_image_id_key" ON "TournamentPrize"("image_id"); - --- AddForeignKey -ALTER TABLE "Tournament" ADD CONSTRAINT "Tournament_thumbnail_image_id_fkey" FOREIGN KEY ("thumbnail_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Tournament" ADD CONSTRAINT "Tournament_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentPrize" ADD CONSTRAINT "TournamentPrize_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentJudge" ADD CONSTRAINT "TournamentJudge_avatar_id_fkey" FOREIGN KEY ("avatar_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "TournamentEvent" ADD CONSTRAINT "TournamentEvent_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220916130117_add_capabilities_project/migration.sql b/prisma/migrations/20220916130117_add_capabilities_project/migration.sql deleted file mode 100644 index dd8f200..0000000 --- a/prisma/migrations/20220916130117_add_capabilities_project/migration.sql +++ /dev/null @@ -1,38 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ADD COLUMN "discord" TEXT NOT NULL DEFAULT E'', -ADD COLUMN "github" TEXT NOT NULL DEFAULT E'', -ADD COLUMN "hashtag" TEXT NOT NULL DEFAULT E'', -ADD COLUMN "launch_status" TEXT NOT NULL DEFAULT E'', -ADD COLUMN "tagline" TEXT NOT NULL DEFAULT E'', -ADD COLUMN "twitter" TEXT NOT NULL DEFAULT E''; - --- CreateTable -CREATE TABLE "Capability" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "icon" TEXT, - "is_official" BOOLEAN NOT NULL DEFAULT false, - - CONSTRAINT "Capability_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "_CapabilityToProject" ( - "A" INTEGER NOT NULL, - "B" INTEGER NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "Capability_title_key" ON "Capability"("title"); - --- CreateIndex -CREATE UNIQUE INDEX "_CapabilityToProject_AB_unique" ON "_CapabilityToProject"("A", "B"); - --- CreateIndex -CREATE INDEX "_CapabilityToProject_B_index" ON "_CapabilityToProject"("B"); - --- AddForeignKey -ALTER TABLE "_CapabilityToProject" ADD FOREIGN KEY ("A") REFERENCES "Capability"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_CapabilityToProject" ADD FOREIGN KEY ("B") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20220918072708_update_project_links_fields/migration.sql b/prisma/migrations/20220918072708_update_project_links_fields/migration.sql deleted file mode 100644 index 3b23f83..0000000 --- a/prisma/migrations/20220918072708_update_project_links_fields/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `is_official` on the `Capability` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Capability" DROP COLUMN "is_official"; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "slack" TEXT, -ADD COLUMN "telegram" TEXT, -ALTER COLUMN "discord" DROP NOT NULL, -ALTER COLUMN "discord" DROP DEFAULT, -ALTER COLUMN "github" DROP NOT NULL, -ALTER COLUMN "github" DROP DEFAULT, -ALTER COLUMN "twitter" DROP NOT NULL, -ALTER COLUMN "twitter" DROP DEFAULT; diff --git a/prisma/migrations/20220918123547_add_project_makers_table/migration.sql b/prisma/migrations/20220918123547_add_project_makers_table/migration.sql deleted file mode 100644 index 42fc30a..0000000 --- a/prisma/migrations/20220918123547_add_project_makers_table/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ --- CreateTable -CREATE TABLE "ProjectMember" ( - "projectId" INTEGER NOT NULL, - "userId" INTEGER NOT NULL, - "level" TEXT NOT NULL, - - CONSTRAINT "ProjectMember_pkey" PRIMARY KEY ("projectId","userId") -); - --- AddForeignKey -ALTER TABLE "ProjectMember" ADD CONSTRAINT "ProjectMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ProjectMember" ADD CONSTRAINT "ProjectMember_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20220918125433_rename_projectmember_level_to_role/migration.sql b/prisma/migrations/20220918125433_rename_projectmember_level_to_role/migration.sql deleted file mode 100644 index 9fd5ea2..0000000 --- a/prisma/migrations/20220918125433_rename_projectmember_level_to_role/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `level` on the `ProjectMember` table. All the data in the column will be lost. - - Added the required column `role` to the `ProjectMember` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "ProjectMember" DROP COLUMN "level", -ADD COLUMN "role" TEXT NOT NULL; diff --git a/prisma/migrations/20220918130530_change_default_value_for_launch_status_project/migration.sql b/prisma/migrations/20220918130530_change_default_value_for_launch_status_project/migration.sql deleted file mode 100644 index 11cc0f5..0000000 --- a/prisma/migrations/20220918130530_change_default_value_for_launch_status_project/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ALTER COLUMN "launch_status" SET DEFAULT E'Launched'; diff --git a/prisma/migrations/20220920093026_add_contact_email_to_project/migration.sql b/prisma/migrations/20220920093026_add_contact_email_to_project/migration.sql deleted file mode 100644 index 9624cc6..0000000 --- a/prisma/migrations/20220920093026_add_contact_email_to_project/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ADD COLUMN "contact_email" TEXT; diff --git a/prisma/migrations/20221004071127_add_project_to_story/migration.sql b/prisma/migrations/20221004071127_add_project_to_story/migration.sql deleted file mode 100644 index 4e3c638..0000000 --- a/prisma/migrations/20221004071127_add_project_to_story/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "Story" ADD COLUMN "project_id" INTEGER; - --- AddForeignKey -ALTER TABLE "Story" ADD CONSTRAINT "Story_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml deleted file mode 100644 index fbffa92..0000000 --- a/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma deleted file mode 100644 index c931a45..0000000 --- a/prisma/schema.prisma +++ /dev/null @@ -1,448 +0,0 @@ -datasource db { - provider = "postgresql" - url = env("DATABASE_PROXY_URL") -} - -generator client { - provider = "prisma-client-js" -} - -// ----------------- -// Shared -// ----------------- - -model Tag { - id Int @id @default(autoincrement()) - title String @unique - icon String? - description String? - isOfficial Boolean @default(false) - - project Project[] - stories Story[] - questions Question[] - hackathons Hackathon[] -} - -model Vote { - id Int @id @default(autoincrement()) - item_id Int - item_type String - amount_in_sat Int - payment_request String? - payment_hash String? - preimage String? - paid Boolean @default(false) -} - -// ----------------- -// Users -// ----------------- - -model User { - id Int @id @default(autoincrement()) - pubKey String? @unique - name String? - avatar String? - avatar_id Int? @unique - avatar_rel HostedImage? @relation("User_Avatar", fields: [avatar_id], references: [id]) - role String @default("user") - - email String? - jobTitle String? - lightning_address String? - website String? - twitter String? - github String? - discord String? - linkedin String? - bio String? - location String? - nostr_prv_key String? - nostr_pub_key String? - - join_date DateTime @default(now()) - - stories Story[] - questions Question[] - posts_comments PostComment[] - donations Donation[] - userKeys UserKey[] - skills Skill[] - roles UsersOnWorkRoles[] - projects ProjectMember[] - - tournaments TournamentParticipant[] -} - -model UserKey { - key String @id - name String @default("My new wallet key") - createdAt DateTime @default(now()) - - user User? @relation(fields: [user_id], references: [id]) - user_id Int? -} - -model UsersOnWorkRoles { - user User @relation(fields: [userId], references: [id]) - userId Int - role WorkRole @relation(fields: [roleId], references: [id]) - roleId Int - - level Int - - @@id([userId, roleId]) -} - -model WorkRole { - id Int @id @default(autoincrement()) - title String @unique - icon String - users UsersOnWorkRoles[] - projects ProjectRecruitRoles[] -} - -model Skill { - id Int @id @default(autoincrement()) - title String @unique - - users User[] -} - -// ----------------- -// Projects -// ----------------- - -model Category { - id Int @id @default(autoincrement()) - title String - cover_image String? - cover_image_id Int? @unique - cover_image_rel HostedImage? @relation("Category_CoverImage", fields: [cover_image_id], references: [id]) - icon String? - - project Project[] -} - -model Project { - id Int @id @default(autoincrement()) - title String - description String - screenshots String[] - screenshots_ids Int[] - website String - discord String? - twitter String? - github String? - telegram String? - slack String? - contact_email String? - thumbnail_image String? - thumbnail_image_id Int? @unique - thumbnail_image_rel HostedImage? @relation("Project_Thumbnail", fields: [thumbnail_image_id], references: [id]) - cover_image String? - cover_image_id Int? @unique - cover_image_rel HostedImage? @relation("Project_CoverImage", fields: [cover_image_id], references: [id]) - lightning_address String? - lnurl_callback_url String? - tagline String @default("") - launch_status String @default("Launched") - hashtag String @default("") - - category Category @relation(fields: [category_id], references: [id]) - category_id Int - votes_count Int @default(0) - createdAt DateTime @default(now()) - - awards Award[] - tags Tag[] - capabilities Capability[] - - members ProjectMember[] - recruit_roles ProjectRecruitRoles[] - tournaments TournamentProject[] - stories Story[] -} - -model ProjectRecruitRoles { - project Project @relation(fields: [projectId], references: [id]) - projectId Int - role WorkRole @relation(fields: [roleId], references: [id]) - roleId Int - - level Int - - @@id([projectId, roleId]) -} - -model ProjectMember { - project Project @relation(fields: [projectId], references: [id]) - projectId Int - user User @relation(fields: [userId], references: [id]) - userId Int - - role String // Admin | Maker | (new_roles_later) - - @@id([projectId, userId]) -} - -model Award { - id Int @id @default(autoincrement()) - title String - image String - image_id Int? @unique - image_rel HostedImage? @relation("Award_Image", fields: [image_id], references: [id]) - url String - - project Project @relation(fields: [project_id], references: [id]) - project_id Int -} - -// ----------------- -// Posts -// ----------------- - -model Story { - id Int @id @default(autoincrement()) - title String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - body String - body_image_ids Int[] - excerpt String - cover_image String? - cover_image_id Int? @unique - cover_image_rel HostedImage? @relation("Story_CoverImage", fields: [cover_image_id], references: [id]) - votes_count Int @default(0) - is_published Boolean @default(true) - - tags Tag[] - - user User? @relation(fields: [user_id], references: [id]) - user_id Int? - - comments PostComment[] @relation("StoryComment") - - project Project? @relation(fields: [project_id], references: [id]) - project_id Int? -} - -model Question { - id Int @id @default(autoincrement()) - title String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - body String - excerpt String - votes_count Int @default(0) - is_published Boolean @default(true) - - tags Tag[] - - user User? @relation(fields: [user_id], references: [id]) - user_id Int? - - comments PostComment[] @relation("QuestionComment") -} - -model PostComment { - id Int @id @default(autoincrement()) - nostr_id String? - body String - created_at DateTime @default(now()) - votes_count Int @default(0) - - replies PostComment[] @relation("PostComment_Replies") - parent_comment_id Int? - parent_comment PostComment? @relation("PostComment_Replies", fields: [parent_comment_id], references: [id]) - - user User? @relation(fields: [user_id], references: [id]) - user_id Int? - - story Story? @relation("StoryComment", fields: [story_id], references: [id]) - story_id Int? - - question Question? @relation("QuestionComment", fields: [question_id], references: [id]) - question_id Int? -} - -// ----------------- -// Hackathons -// ----------------- -model Hackathon { - id Int @id @default(autoincrement()) - title String - start_date DateTime @db.Date - end_date DateTime @db.Date - cover_image String - cover_image_id Int? @unique - cover_image_rel HostedImage? @relation("Hackathon_CoverImage", fields: [cover_image_id], references: [id]) - description String - location String - website String - votes_count Int @default(0) - - tags Tag[] -} - -// ----------------- -// Donations -// ----------------- -model Donation { - id Int @id @default(autoincrement()) - amount Int - createdAt DateTime @default(now()) - payment_request String? - payment_hash String? - preimage String? - paid Boolean @default(false) - - donor User? @relation(fields: [donor_id], references: [id]) - donor_id Int? -} - -// ----------------- -// Auth -// ----------------- -model GeneratedK1 { - value String @id - sid String? - createdAt DateTime @default(now()) -} - -// ----------------- -// Hosted Image -// ----------------- -model HostedImage { - id Int @id @default(autoincrement()) - filename String - provider_image_id String - provider String - url String - createdAt DateTime @default(now()) - is_used Boolean @default(false) - - ProjectThumbnail Project? @relation("Project_Thumbnail") - ProjectCoverImage Project? @relation("Project_CoverImage") - CategoryCoverImage Category? @relation("Category_CoverImage") - AwardImage Award? @relation("Award_Image") - HackathonCoverImage Hackathon? @relation("Hackathon_CoverImage") - StoryCoverImage Story? @relation("Story_CoverImage") - User User? @relation("User_Avatar") - TournamentThumbnail Tournament? @relation("Tournament_ThumbnailImage") - Tournament_CoverImage Tournament? @relation("Tournament_CoverImage") - TournamentPrize_Image TournamentPrize? @relation("TournamentPrize_Image") - TournamentJudge_Avatar TournamentJudge? @relation("TournamentJudge_Avatar") - TournamentEvent_Image TournamentEvent? @relation("TournamentEvent_Image") -} - -// ----------------- -// Tournament -// ----------------- -model Tournament { - id Int @id @default(autoincrement()) - title String - description String - thumbnail_image String - thumbnail_image_id Int? @unique - thumbnail_image_rel HostedImage? @relation("Tournament_ThumbnailImage", fields: [thumbnail_image_id], references: [id]) - cover_image String - cover_image_id Int? @unique - cover_image_rel HostedImage? @relation("Tournament_CoverImage", fields: [cover_image_id], references: [id]) - start_date DateTime - end_date DateTime - location String - website String - votes_count Int @default(0) - - prizes TournamentPrize[] - judges TournamentJudge[] - faqs TournamentFAQ[] - events TournamentEvent[] - participants TournamentParticipant[] - projects TournamentProject[] -} - -model TournamentPrize { - id Int @id @default(autoincrement()) - title String - amount String - image String - image_id Int? @unique - image_rel HostedImage? @relation("TournamentPrize_Image", fields: [image_id], references: [id]) - - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int -} - -model TournamentJudge { - id Int @id @default(autoincrement()) - name String - avatar String - avatar_id Int? @unique - avatar_rel HostedImage? @relation("TournamentJudge_Avatar", fields: [avatar_id], references: [id]) - company String - twitter String? - - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int -} - -model TournamentFAQ { - id Int @id @default(autoincrement()) - question String - answer String - - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int -} - -model TournamentEvent { - id Int @id @default(autoincrement()) - title String - image String - image_id Int? @unique - image_rel HostedImage? @relation("TournamentEvent_Image", fields: [image_id], references: [id]) - description String - starts_at DateTime - ends_at DateTime - location String - website String - type Int - - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int -} - -model TournamentParticipant { - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int - user User @relation(fields: [user_id], references: [id]) - user_id Int - createdAt DateTime @default(now()) - - email String - hacking_status Int - - @@id([tournament_id, user_id]) -} - -model TournamentProject { - tournament Tournament @relation(fields: [tournament_id], references: [id]) - tournament_id Int - project Project @relation(fields: [project_id], references: [id]) - project_id Int - - @@id([tournament_id, project_id]) -} - -// ----------------- -// Capability -// ----------------- -model Capability { - id Int @id @default(autoincrement()) - title String @unique - icon String? - project Project[] -} diff --git a/prisma/seed/data.js b/prisma/seed/data.js deleted file mode 100644 index 9ebd9e4..0000000 --- a/prisma/seed/data.js +++ /dev/null @@ -1,569 +0,0 @@ -const { randomItem, randomItems, random, getCoverImage } = require("./helpers") - -const categories = [ - { - "id": 5, - "title": "Wallet" - }, - { - "id": 2, - "title": "Social" - }, - { - "id": 8, - "title": "Shopping" - }, - { - "id": 11, - "title": "Shock the Web ⚡️" - }, - { - "id": 9, - "title": "Misc / Other" - }, - { - "id": 7, - "title": "Media & News" - }, - { - "id": 4, - "title": "Gaming" - }, - { - "id": 1, - "title": "Finance" - }, - { - "id": 10, - "title": "Exchange" - }, - { - "id": 3, - "title": "Art & Collectibles" - }, - { - "id": 6, - "title": "Analytics" - } -] - -const tags = [ - { - id: 1, - title: 'Bitcoin', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: "🅱", - isOfficial: true, - }, - { - id: 2, - title: 'Lightning', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: "⚡", - isOfficial: true, - }, - { - id: 3, - title: 'Webln', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: "🔗", - isOfficial: true, - }, - { - id: 4, - title: 'Gaming', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: "🎮", - isOfficial: true, - }, - { - - id: 5, - title: 'Design', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: '🎨', - isOfficial: true, - }, - { - - id: 6, - title: 'Launch', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: '🚀', - isOfficial: true, - }, - { - - id: 7, - title: 'Brainstory', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: '🧠', - isOfficial: true, - }, - { - - id: 8, - title: 'Development', - description: 'Lorem ipsum dolor sit amort consectetur, adipisicing elit. Possimus officia sit numquam nobis iure atque ab sunt nihil voluptatibus', - icon: '💻', - isOfficial: true, - } -] - -const projects = [ - { - "id": 22, - "title": "Geyser Fund", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/geyser-fund_cover.png", - "thumbnail_image": "https://user-images.githubusercontent.com/36778205/157433567-4b1e41db-23d4-4a80-b48f-ee248ee87f1e.jpg", - "website": "https://geyser.fund/", - "lightning_address": "divineorgan67@walletofsatoshi.com", - "votes_count": 232, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 16, - "title": "Alby", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/alby_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/alby_thumbnail.png", - "website": "https://getalby.com/", - "lightning_address": "hello@getalby.com", - "votes_count": 215, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 20, - "title": "Lightning.Video", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-video_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-video_thumbnail.png", - "website": "https://lightning.video/", - "lightning_address": "moritz@getalby.com", - "votes_count": 175, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 1, - "title": "Kollider", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/kollider_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/kollider_thumbnail.png", - "website": "https://kollider.xyz/", - "lightning_address": "johns@getalby.com", - "votes_count": 120, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 12, - "title": "Bitrefill", - "cover_image": "http://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/bitrefill_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/bitrefill_thumbnail.png", - "website": "https://www.bitrefill.com/buy", - "lightning_address": "moritz@getalby.com", - "votes_count": 25, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 7, - "title": "Wavlake", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/wavlake_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/wavlake_thumbnail.png", - "website": "https://www.wavlake.com/", - "lightning_address": "moritz@getalby.com", - "votes_count": 25, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 3, - "title": "Sparkshot", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/sparkshot_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/sparkshot_thumbnail.png", - "website": "https://sparkshot.io/", - "lightning_address": "johns@getalby.com", - "votes_count": 11, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 17, - "title": "Lightning Gifts", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-gifts_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-gifts_thumbnail.png", - "website": "https://lightning.gifts/", - "lightning_address": "moritz@getalby.com", - "votes_count": 10, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 4, - "title": "Amboss Space", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/amboss-space_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/amboss-space_thumbnail.png", - "website": "https://amboss.space/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 5, - "title": "LN Blackjack", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnblackjack_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnblackjack_thumbnail.png", - "website": "https://www.lnblackjack.com/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 19, - "title": "Y'alls ", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/yalls_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/yalls_thumbnail.png", - "website": "https://yalls.org/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 13, - "title": "Lightning Network Stores", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-network-stores_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-network-stores_thumbnail.png", - "website": "https://lightningnetworkstores.com/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 9, - "title": "Lightning Poker", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-poker_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-poker_thumbnail.png", - "website": "https://lightning-poker.com/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 6, - "title": "LNGames", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lngames_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lngames_thumbnail.png", - "website": "https://lngames.net/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 21, - "title": "Starbackr", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/starbackr_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/starbackr_thumbail.png", - "website": "https://www.starbackr.com/", - "lightning_address": "moritz@geralby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 8, - "title": "LOFT", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/loft-trade_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/loft-trade_thumbnail.png", - "website": "https://loft.trade/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 10, - "title": "Lightning Roulette", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-roulette_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lightning-roulette_thumbnail.png", - "website": "https://lightning-roulette.com/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 14, - "title": "Sats 4 Likes", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/sats-4-likes-cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/sats-4-likes_thumbnail.png", - "website": "https://kriptode.com/satsforlikes/index.html", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 18, - "title": "Scarce City", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/scarce-city_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/scarce-city_thumbnail.png", - "website": "https://scarce.city/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 15, - "title": "lnshort.it", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnshort-it_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnshort-it_thumbnail.png", - "website": "https://lnshort.it/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 11, - "title": "Stacker News", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/stacker-news_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/stacker-news_thumbnail.png", - "website": "https://stacker.news/", - "lightning_address": "moritz@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - }, - { - "id": 2, - "title": "LN Markets", - "cover_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnmarkets_cover.png", - "thumbnail_image": "https://fra1.digitaloceanspaces.com/alby-storage/makers-bolt-fun/bolt.fund_thumbnails_covers/lnmarkets_thumbnail.png", - "website": "https://lnmarkets.com/", - "lightning_address": "johns@getalby.com", - "votes_count": 0, - "category_id": randomItem(categories).id, - tags: randomItems(random(2, 3), tags) - } -] - -const hackathons = [ - { - title: 'Fulmo Hackday', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, - { - title: 'Lightning Leagues', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, - { - title: 'Surfing on Lightning', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, - { - title: 'Lightning Startups', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, - { - title: 'Design-a-thon', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, - { - title: 'Lightning Olympics', - start_date: new Date(2022, 2, 22), - end_date: new Date(2022, 2, 28), - location: "Instanbul, Turkey", - cover_image: getCoverImage(), - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.", - tags: randomItems(3, tags), - website: "https://bolt.fun/hackathons/shock-the-web" - }, -] - -const roles = [ - { - id: 1, - title: "Frontend Dev", - icon: "💄" - }, - { - id: 2, - title: "Backend Dev", - icon: "💻️" - }, { - id: 3, - title: "UI/UX Designer", - icon: "🌈️️" - }, - { - id: 4, - title: "Community Manager", - icon: "🎉️️" - }, - { - id: 5, - title: "Founder", - icon: "🦄️" - }, - { - id: 6, - title: "Marketer", - icon: "🚨️" - }, - { - id: 7, - title: "Content Creator", - icon: "🎥️" - }, - { - id: 8, - title: "Researcher", - icon: "🔬" - }, - { - id: 9, - title: "Data engineer", - icon: "💿️" - }, - { - id: 10, - title: "Growth hacker", - icon: "📉️" - }, - { - id: 11, - title: "Technical Writer", - icon: "✍️️" - }, -] - -const skills = [ - { - id: 1, - title: "Figma" - }, - { - id: 2, - title: "Prototyping" - }, { - id: 3, - title: "Writing" - }, { - id: 4, - title: "CSS" - }, { - id: 5, - title: "React.js" - }, { - id: 6, - title: "Wordpress" - }, { - id: 7, - title: "Principle app" - }, { - id: 8, - title: "UX design" - }, { - id: 9, - title: "User research" - }, { - id: 10, - title: "User testing" - }, -] - -const capabilities = [ - { - id: 1, - title: 'Mobile', - icon: '📱' - }, - { - id: 2, - title: 'Web', - icon: '💻' - }, - { - id: 3, - title: 'WebLN', - icon: '🎛️' - }, - { - id: 4, - title: 'LNURL-auth', - icon: '🔑️️' - }, - { - id: 5, - title: 'LNURL-pay', - icon: '💸' - }, - { - id: 6, - title: 'LNURL-channel', - icon: '🕳️️' - }, - { - id: 7, - title: 'LNURL-withdraw', - icon: '🎬️' - }, - { - id: 8, - title: 'BOLT 11', - icon: '⚡' - }, - { - id: 9, - title: 'BOLT 12', - icon: '⚡' - }, -] - -module.exports = { - categories, - projects, - tags, - hackathons, - roles, - skills, - capabilities, -} \ No newline at end of file diff --git a/prisma/seed/data/tournament.seed.js b/prisma/seed/data/tournament.seed.js deleted file mode 100644 index 34f7202..0000000 --- a/prisma/seed/data/tournament.seed.js +++ /dev/null @@ -1,232 +0,0 @@ - - -const tournament = { - __typename: "Tournament", - id: 12, - title: "Legends of Lightning ⚡️", - start_date: "2022-10-12T21:00:00.000Z", - end_date: "2022-11-30T22:00:00.000Z", - cover_image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/1d5d2c86-fe46-4478-6909-bb3c425c0d00/public", - thumbnail_image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/37fb9cd6-e4f1-43f9-c3fe-7c3e119d5600/public", - location: "Online", - website: "#", - description: // this field accepts markdown - `## Tournament Details -BOLT🔩FUN’s maiden tournament, **Legends of Lightning** ⚡ will be an online global competition for makers to learn, connect, collaborate, and experiment with building innovative applications and tools with bitcoin and lightning. - -Spanning a 2-month period, makers can form teams, hack on projects, and show off their progress, activity, and updates as they compete for up to **$10,000 in bitcoin prizes**. - -BOLT🔩FUN has partnered with a number of events, meetups, and hackathons to provide makers the opportunity to brainstorm, design, build, and accelerate their tournament projects over the course of a couple of months. At the end of the tournament, a panel of judges will access and score all submitted projects - announcing the winners in the second week of December! - - `, // markdown - prizes: [ - { - title: "stw3 champion", - amount: "$ 5k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39217dcf-c900-46be-153f-169e3a1f0400/public", - }, - { - title: "2nd place", - amount: "$ 2.5k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/39cdb7c8-5fbf-49ff-32cf-fdabc3aa2d00/public", - }, - { - title: "3rd place ", - amount: "$ 1.5k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/75958797-73b2-4a62-52df-9f0f98c53900/public", - }, - { - title: "best design ", - amount: "$ 1k", - image: "https://imagedelivery.net/wyrwp3c-j0gDDUWgnE7lig/fa7b7cdd-7c06-4ebe-1a2d-94af9d2dae00/public", - } - ], - - events: [ - { - title: "Tab Conf 22", - starts_at: "2022-10-13T21:00:00.000Z", - ends_at: "2022-10-15T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "Atlanta, GA", - type: 1, /** EVent typs encoding - * - Twitter Space: 0, - Workshop: 1, - IRL Meetup: 2, - Online Meetup: 3, - */ - website: "https://2022.tabconf.com/" - }, - { - title: "Bitcoin Amsterdam", - starts_at: "2022-10-12T21:00:00.000Z", - ends_at: "2022-10-14T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "Amsterdam, NL", - type: 2, - website: "https://b.tc/conference/amsterdam" - }, - { - title: "Lugano’s Plan ₿", - starts_at: "2022-10-28T21:00:00.000Z", - ends_at: "2022-11-04T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "Lugano, CH", - type: 3, - website: "https://planb.lugano.ch/" - }, - { - title: "Adopting Bitcoin 22", - starts_at: "2022-11-15T21:00:00.000Z", - ends_at: "2022-11-17T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "El Salvador", - type: 2, - website: "https://adoptingbitcoin.org/2022/" - }, - - { - title: "PlebTLV", - starts_at: "2022-10-23T21:00:00.000Z", - ends_at: "2022-10-23T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "Tel Aviv", - type: 2, - website: "https://plebtlv.com/" - }, - { - title: "Bitcoin Designathon", - starts_at: "2022-10-12T21:00:00.000Z", - ends_at: "2022-10-16T22:00:00.000Z", - description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam morbi pellentesque velit congue. Aliquet rutrum a, augue vitae tincidunt ac egestas. Mauris nec fringilla diam eget fusce malesuada cum parturient. Nulla pretium purus odio odio.", - image: 'https://picsum.photos/id/10/400/800', - links: [], - location: "Online", - type: 2, - website: "https://bitcoin.design" - }, - ], - judges: [ - { - name: "Roy Sheinfeld", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Breez", - twitter: "@therealkingonly" - }, - { - name: "John Carvalho", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Synonym", - twitter: "@BitcoinErrorLog" - }, - { - name: "Nifty Nei", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Blockstream", - twitter: "@niftynei" - }, - { - name: "Oleg Mikhalsky", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Fulgur Ventures", - twitter: "@olegmikh1" - }, - { - name: "Alyse Kileen", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Stillmark VC", - twitter: "@AlyseKilleen" - }, - { - name: "Johns Beharry", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "Peak Shift", - twitter: "@johnsBeharry" - }, - { - name: "Ben Price", - avatar: "https://s3-alpha-sig.figma.com/img/5e65/c22c/673b8f74ac43f024b036dbc4e6479e0d?Expires=1662940800&Signature=GR54s7FBcLGcPTVclWdmPjzU92tyrYpdUbbDUYKMUkdQbxq2yQlUhZ-AOLDHhOPY4P2G3aW2yT16b1AUbC8RBx1boH25MSrH-jpn6X57IJA-4ZeHP8zCo-yjTLpb8Gn~vudIi9rPfbwJ34stp-VeOAYMuOHlah3YO-B4MBsBv-NqhP7BMY4zz9vGdBLZhOjYQYdLZ2494Ae6L5FpD1ah3WD3U5qUN9dDvYvAtqYfhQeBOnsG6PfYoq8LouCuERC4S26BeooPg8UdGUCf324-SjEihCoL8mQFq80PSsaAZl5~EBOKRUx14FOprizMusaYN0K06E~fjDIDbM2Rmc9Xjg__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA", - company: "The Bitcoin Company", - twitter: "@abitcoinperson" - }, - ], - - faqs: [ - { - question: "When does the tournament start and end?", - answer: - `The tournament starts when team and project registrations open on 12th October. The tournament will finish with submissions closing on 30th November, 2022. Judges will then score projects and announce the winners on the 12th December.` - }, - { - question: "When and how do we register our projects?", - answer: - `Makers can register their projects anytime between 12th October - 30th November. If a project is added on the tournament page, it is automatically registered and it will be judged at the end of the tournament.` - }, - { - question: "How will projects be judged?", - answer: - `Projects will be judged and scored on the following criteria: - -**1). 🎯 Value Proposition** -Does the project have a product market fit? Does it provide value to the bitcoin ecosystem and beyond? - -**2). 🚨 Innovation** -Is it something we've seen before or does it bring something new and exciting to bitcoin and beyond? - -**3). 👁️ Transparency (#BuildInPublic)** -Encouraging makers to #BuildInPublic. Has the project’s team been transparent throughout their product design and development journey? - -**4). ✅ Execution** -Makers should focus on attention to detail. How well has the project been executed? - -**5). 🍒 UIUX Design** -Design can separate the good from the bad. Taking into account both UI and UX, how well has the application or feature been designed? - -**6). 🔥 Je ne sais quoi** -Does the project have that extra level of pizazz or coolness? Does it raise the bar?` - }, - { - question: "Can I submit a project that I hacked on during another event?", - answer: - `Makers can submit their projects from other hackathons, events, and meetups that are registered as events within The Long Night tournament. This allows makers to take advantage of IRL + online meetups, workshops, hackerspaces, inspirational weekend events, and more.` - }, - { - question: "Can I submit multiple projects?", - answer: - `Yes, makers can submit multiple projects. However we encourage makers to focus on quality rather than quantity.` - }, - { - question: "How can I find other makers or projects to team up with?", - answer: - `You can see a list of makers who are open to connect in the tournament’s Makers tab. You can also search for projects that are looking to recruit members.` - }, - { - question: "This is my first time hacking on bitcoin, is there any help?", - answer: - `We collected some awesome design, development, and project management resources here to get you up and running. You can also watch workshops and tutorials from BOLT🔩FUN’s previous ShockTheWeb⚡hackathons here.` - }, - { - question: "Not sure what to hack on?", - answer: - `Not sure where to get started? Need an idea to hack on? Not to worry, we’ve collected a list of great project ideas for you to look at here.` - }, - { - question: "How can I #BuildInPublic?", - answer: - `Using BOLT🔩FUN Stories ✍️, makers can transparently document their project’s design, development, and management processes. This will help other makers learn from one another, decreasing essential onboarding and learning time, whilst inspiring more great bitcoin apps to be built and innovated on. To see an example of this type of transparent reporting, check out this story here.` - }, - ], -} - -module.exports = { tournament }; \ No newline at end of file diff --git a/prisma/seed/helpers.js b/prisma/seed/helpers.js deleted file mode 100644 index 8c83c3b..0000000 --- a/prisma/seed/helpers.js +++ /dev/null @@ -1,51 +0,0 @@ -function random(min, max) { - return Math.random() * (max - min) + min; -} - -function randomItem(args) { - return args[Math.floor(Math.random() * args.length)]; -} - -function randomItems(cnt, args) { - return shuffle(args).slice(0, Math.floor(cnt)); -} - -function shuffle(_array) { - let array = [..._array] - let currentIndex = array.length, randomIndex; - - // While there remain elements to shuffle. - while (currentIndex !== 0) { - - // Pick a remaining element. - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex--; - - // And swap it with the current element. - [array[currentIndex], array[randomIndex]] = [ - array[randomIndex], array[currentIndex]]; - } - - return array; -} - - -let coverImgsCntr = -1; - -function getCoverImage() { - const coverImgs = [ - 'https://picsum.photos/id/10/1600/900', - 'https://picsum.photos/id/1000/1600/900', - 'https://picsum.photos/id/1002/1600/900', - 'https://picsum.photos/id/1018/1600/900', - ] - - return coverImgs[(++coverImgsCntr) % coverImgs.length] -} - -module.exports = { - random, - randomItem, - randomItems, - getCoverImage, -} \ No newline at end of file diff --git a/prisma/seed/index.js b/prisma/seed/index.js deleted file mode 100644 index 80b378e..0000000 --- a/prisma/seed/index.js +++ /dev/null @@ -1,539 +0,0 @@ -const { PrismaClient } = require("@prisma/client"); -const { generatePrivateKey, getPublicKey } = require("../../api/utils/nostr-tools"); -const { categories, projects, tags, hackathons, roles, skills, capabilities } = require("./data"); -const Chance = require('chance'); -const { getCoverImage, randomItems, random } = require("./helpers"); -const { tournament: tournamentMock } = require("./data/tournament.seed"); - -const chance = new Chance(); - - -const prisma = new PrismaClient() - - -async function purge() { - await prisma.award.deleteMany(); - await prisma.tag.deleteMany(); - await prisma.vote.deleteMany(); - await prisma.project.deleteMany(); - await prisma.category.deleteMany(); -} - - -async function generateNostrKeys() { - const allUsers = await prisma.user.findMany({ - where: { - nostr_prv_key: null - } - }) - for (const user of allUsers) { - - const prvkey = generatePrivateKey(); - const pubkey = getPublicKey(prvkey); - - await prisma.user.update({ - where: { - id: user.id, - }, - data: { - nostr_prv_key: prvkey, - nostr_pub_key: pubkey - } - }) - } -} - - - -async function main() { - // console.log("Purging old data"); - // await purge() - - // await createCategories(); - - // await createTags(); - - // await createProjects(); - - // await createStories(); - - // await createHackathons(); - - // await fillUserKeysTable() - - // await createRoles(); - - // await createSkills(); - - // await createTournament(); - - // await migrateOldImages(); - - // await createCapabilities(); - - // await createHashtags(); -} - -async function migrateOldImages() { - console.log('Migrating old images data to HostedImage'); - - // Can't use prisma method createMany() for columns like Project.screenshots, because this method doesn't return created IDs. - - /** - * Project - **/ - const projects = await prisma.project.findMany({ - select: { - id: true, - screenshots: true, - cover_image: true, - thumbnail_image: true - } - }) - for (const project of projects) { - /** - * Project.screenshots to Project.screenshots_ids - **/ - let projectScreenshotIds = []; - for (const screenshot of project.screenshots) { - let hostedImageId = await _insertInHostedImage(screenshot) - projectScreenshotIds.push(hostedImageId); - } - if (projectScreenshotIds.length > 0) { - await _updateObjectWithHostedImageId(prisma.project, project.id, { - screenshots_ids: projectScreenshotIds, - }) - } - - /** - * Project.cover_image to Project.cover_image_id - **/ - if (project.cover_image) { - let hostedImageId = await _insertInHostedImage(project.cover_image) - await _updateObjectWithHostedImageId(prisma.project, project.id, { - cover_image_id: hostedImageId, - }) - } - - /** - * Project.thumbnail_image to Project.thumbnail_image_id - **/ - if (project.cover_image) { - let hostedImageId = await _insertInHostedImage(project.thumbnail_image) - await _updateObjectWithHostedImageId(prisma.project, project.id, { - thumbnail_image_id: hostedImageId, - }) - } - } - - /** - * Category - **/ - const categories = await prisma.category.findMany({ - select: { - id: true, - cover_image: true, - } - }) - for (const category of categories) { - if (category.cover_image) { - let hostedImageId = await _insertInHostedImage(category.cover_image) - await _updateObjectWithHostedImageId(prisma.category, category.id, { - cover_image_id: hostedImageId, - }) - } - } - - /** - * Award - **/ - const awards = await prisma.award.findMany({ - select: { - id: true, - image: true, - } - }) - for (const award of awards) { - if (award.image) { - let hostedImageId = await _insertInHostedImage(award.image) - await _updateObjectWithHostedImageId(prisma.award, award.id, { - image_id: hostedImageId, - }) - } - } - - /** - * Hackaton - **/ - const hackatons = await prisma.hackathon.findMany({ - select: { - id: true, - cover_image: true, - } - }) - for (const hackaton of hackatons) { - if (hackaton.cover_image) { - let hostedImageId = await _insertInHostedImage(hackaton.cover_image) - await _updateObjectWithHostedImageId(prisma.hackathon, hackaton.id, { - cover_image_id: hostedImageId, - }) - } - } - - /** - * Story - **/ - const stories = await prisma.story.findMany({ - select: { - id: true, - cover_image: true, - body: true, - } - }) - for (const story of stories) { - /** - * Story.body to Story.body_image_ids - **/ - let bodyImageIds = []; - const regex = /(?:!\[(.*?)\]\((.*?)\))/g - let match; - while ((match = regex.exec(story.body))) { - const [, , value] = match - let hostedImageId = await _insertInHostedImage(value) - bodyImageIds.push(hostedImageId) - } - if (bodyImageIds.length > 0) { - await _updateObjectWithHostedImageId(prisma.story, story.id, { - body_image_ids: bodyImageIds, - }) - } - - /** - * Story.cover_image to Story.cover_image_id - **/ - if (story.cover_image) { - let hostedImageId = await _insertInHostedImage(story.cover_image) - await _updateObjectWithHostedImageId(prisma.story, story.id, { - cover_image_id: hostedImageId, - }) - } - } - - /** - * User - **/ - const users = await prisma.user.findMany({ - select: { - id: true, - avatar: true, - } - }) - for (const user of users) { - if (user.avatar) { - let hostedImageId = await _insertInHostedImage(user.avatar) - await _updateObjectWithHostedImageId(prisma.user, user.id, { - avatar_id: hostedImageId, - }) - } - } - - /** - * Tournament - **/ - const tournaments = await prisma.tournament.findMany({ - select: { - id: true, - thumbnail_image: true, - cover_image: true, - } - }) - for (const tournament of tournaments) { - if (tournament.thumbnail_image) { - let hostedImageId = await _insertInHostedImage(tournament.thumbnail_image) - await _updateObjectWithHostedImageId(prisma.tournament, tournament.id, { - thumbnail_image_id: hostedImageId, - }) - } - if (tournament.cover_image) { - let hostedImageId = await _insertInHostedImage(tournament.cover_image) - await _updateObjectWithHostedImageId(prisma.tournament, tournament.id, { - cover_image_id: hostedImageId, - }) - } - } - - /** - * TournamentPrize - **/ - const tournamentPrizes = await prisma.tournamentPrize.findMany({ - select: { - id: true, - image: true, - } - }) - for (const tournament of tournamentPrizes) { - if (tournament.image) { - let hostedImageId = await _insertInHostedImage(tournament.image) - await _updateObjectWithHostedImageId(prisma.tournamentPrize, tournament.id, { - image_id: hostedImageId, - }) - } - } - - /** - * TournamentJudge - **/ - const tournamentJudges = await prisma.tournamentJudge.findMany({ - select: { - id: true, - avatar: true, - } - }) - for (const tournament of tournamentJudges) { - if (tournament.avatar) { - let hostedImageId = await _insertInHostedImage(tournament.avatar) - await _updateObjectWithHostedImageId(prisma.tournamentJudge, tournament.id, { - avatar_id: hostedImageId, - }) - } - } - /** - * TournamentEvent - **/ - const tournamentEvents = await prisma.tournamentEvent.findMany({ - select: { - id: true, - image: true, - } - }) - for (const tournament of tournamentEvents) { - if (tournament.image) { - let hostedImageId = await _insertInHostedImage(tournament.image) - await _updateObjectWithHostedImageId(prisma.tournamentEvent, tournament.id, { - image_id: hostedImageId, - }) - } - } -} - -async function _insertInHostedImage(url) { - const newHostedImage = await prisma.hostedImage.create({ - data: { - filename: "default.png", - provider: "external", - provider_image_id: "", - url, - is_used: true - } - }); - return newHostedImage.id; -} -async function _updateObjectWithHostedImageId(prismaObject, objectId, data) { - await prismaObject.update({ - where: { id: objectId }, - data, - }); -} - -async function createCategories() { - console.log("Creating Categories"); - await prisma.category.createMany({ - data: categories.map(item => ({ - id: item.id, - title: item.title, - cover_image: 'https://via.placeholder.com/1920x850.png?text=Category+Cover+Image', - icon: '🎭' - })) - }) -} - -async function createTags() { - console.log("Creating Tags"); - await prisma.tag.createMany({ - data: tags.map(item => ({ - id: item.id, - title: item.title, - description: item.description, - isOfficial: item.isOfficial, - icon: item.icon, - })) - }) -} - -async function createProjects() { - console.log("Creating Projects"); - - for (let i = 0; i < projects.length; i++) { - const item = projects[i]; - const { tags, ...feilds } = item - await prisma.project.create({ - data: { - ...feilds, - tags: { - connect: tags.map(t => ({ - id: t.id - })) - }, - description: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.", - screenshots: Array(4).fill('https://via.placeholder.com/1280x729.png?text=Project+Screenshot') - } - }) - } -} - -async function createStories() { - console.log("Creating Stories"); - - const user = await prisma.user.findFirst(); - - for (let i = 0; i < 15; i++) { - const randomTags = randomItems(random(2, 5), tags) - await prisma.story.create({ - data: { - body: chance.paragraph(), - excerpt: chance.paragraph({ sentences: 1 }), - title: chance.sentence({ words: chance.integer({ min: 3, max: 7 }) }), - cover_image: getCoverImage(), - is_published: true, - tags: { - connect: randomTags.map(t => ({ id: t.id })) - }, - user_id: user.id, - votes_count: Math.floor(random(10, 6600)), - } - }) - } -} - -async function createHackathons() { - console.log("Creating Hackathons"); - - for (let i = 0; i < hackathons.length; i++) { - const item = hackathons[i]; - const { tags, ...feilds } = item - await prisma.hackathon.create({ - data: { - ...feilds, - tags: { - connect: tags.map(t => ({ - id: t.id - })) - }, - description: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.", - } - }) - } -} - -async function fillUserKeysTable() { - console.log('Filling Users Keys Table'); - const allUsers = await prisma.user.findMany({ - select: { - id: true, - pubKey: true, - } - }) - - await prisma.userKey.createMany({ - data: allUsers.filter(u => !!u.pubKey).map(u => ({ - key: u.pubKey, - user_id: u.id - })) - }) -} - -async function createRoles() { - console.log("Creating Users Roles"); - await prisma.workRole.createMany({ - data: roles.map(item => ({ - id: item.id, - title: item.title, - icon: item.icon, - })) - }) -} - -async function createSkills() { - console.log("Creating Users Skills"); - await prisma.skill.createMany({ - data: skills.map(item => ({ - id: item.id, - title: item.title, - })) - }) -} - -async function createTournament() { - console.log("Creating Tournament"); - - const createdTournament = await prisma.tournament.create({ - data: { - title: tournamentMock.title, - description: tournamentMock.description, - start_date: tournamentMock.start_date, - end_date: tournamentMock.end_date, - thumbnail_image: tournamentMock.thumbnail_image, - cover_image: tournamentMock.cover_image, - location: tournamentMock.location, - website: tournamentMock.website, - - faqs: { - createMany: { - data: tournamentMock.faqs.map(f => ({ question: f.question, answer: f.answer })) - } - }, - prizes: { - createMany: { - data: tournamentMock.prizes.map(p => ({ title: p.title, image: p.image, amount: p.amount })) - } - }, - judges: { - createMany: { - data: tournamentMock.judges.map(j => ({ name: j.name, company: j.company, twitter: j.twitter, avatar: j.avatar })) - } - }, - events: { - createMany: { - data: tournamentMock.events.map(e => ({ title: e.title, description: e.description, starts_at: e.starts_at, ends_at: e.ends_at, image: e.image, location: e.location, type: e.type, website: e.website })) - } - }, - - } - }) - -} - -async function createCapabilities() { - console.log("Creating Capabilities"); - await prisma.capability.createMany({ - data: capabilities - }) -} - -async function createHashtags() { - console.log("Creating Hashtags for projects"); - const projects = await prisma.project.findMany({ select: { title: true, id: true } }); - for (let i = 0; i < projects.length; i++) { - const project = projects[i]; - await prisma.project.update({ - where: { id: project.id }, - data: { - hashtag: project.title.toLowerCase() - .trim() - .replace(/[^\w\s-]/g, '') - .replace(/[\s_-]+/g, '_') - .replace(/^-+|-+$/g, '') - } - }) - } -} - - -main() - .catch((e) => { - console.error(e) - process.exit(1) - }) - .finally(async () => { - await prisma.$disconnect() - }) \ No newline at end of file diff --git a/public/assets/icons/flag-icon.svg b/public/assets/icons/flag-icon.svg deleted file mode 100644 index 6621a84..0000000 --- a/public/assets/icons/flag-icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/assets/icons/join-discord.svg b/public/assets/icons/join-discord.svg deleted file mode 100644 index da52ce2..0000000 --- a/public/assets/icons/join-discord.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/assets/icons/lightning-big.svg b/public/assets/icons/lightning-big.svg deleted file mode 100644 index 56cbf6b..0000000 --- a/public/assets/icons/lightning-big.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/assets/icons/lightning-small.svg b/public/assets/icons/lightning-small.svg deleted file mode 100644 index 781b618..0000000 --- a/public/assets/icons/lightning-small.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/assets/icons/nut.svg b/public/assets/icons/nut.svg deleted file mode 100644 index b7590c0..0000000 --- a/public/assets/icons/nut.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/public/assets/icons/success-icon.svg b/public/assets/icons/success-icon.svg deleted file mode 100644 index 0bfb465..0000000 --- a/public/assets/icons/success-icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/assets/images/barcode.jpg b/public/assets/images/barcode.jpg deleted file mode 100644 index bd2463b..0000000 Binary files a/public/assets/images/barcode.jpg and /dev/null differ diff --git a/public/assets/images/header-2.jfif b/public/assets/images/header-2.jfif deleted file mode 100644 index bdebaa8..0000000 Binary files a/public/assets/images/header-2.jfif and /dev/null differ diff --git a/public/assets/images/header.jpg b/public/assets/images/header.jpg deleted file mode 100644 index 66d5bf1..0000000 Binary files a/public/assets/images/header.jpg and /dev/null differ diff --git a/public/assets/images/join-discord-card.jpg b/public/assets/images/join-discord-card.jpg deleted file mode 100644 index f5eabe8..0000000 Binary files a/public/assets/images/join-discord-card.jpg and /dev/null differ diff --git a/public/assets/images/logo.png b/public/assets/images/logo.png deleted file mode 100644 index f37db45..0000000 Binary files a/public/assets/images/logo.png and /dev/null differ diff --git a/public/assets/images/logos/fulgur_logo.svg b/public/assets/images/logos/fulgur_logo.svg deleted file mode 100644 index cd585ef..0000000 --- a/public/assets/images/logos/fulgur_logo.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/assets/images/nut_3d.png b/public/assets/images/nut_3d.png deleted file mode 100644 index 955694b..0000000 Binary files a/public/assets/images/nut_3d.png and /dev/null differ diff --git a/public/assets/images/og-thumbnail.jpg b/public/assets/images/og-thumbnail.jpg deleted file mode 100644 index e035738..0000000 Binary files a/public/assets/images/og-thumbnail.jpg and /dev/null differ diff --git a/public/assets/images/stw2.jfif b/public/assets/images/stw2.jfif deleted file mode 100644 index c54e9e0..0000000 Binary files a/public/assets/images/stw2.jfif and /dev/null differ