diff --git a/.env.example b/.env.example index d0d1d01..69de436 100644 --- a/.env.example +++ b/.env.example @@ -14,6 +14,6 @@ PINATA_JWT= PINATA_GATEWAY= # Change to your website URL -# For development: set to http://localhost:3000 +# For development: SITE_URL=http://localhost:3000 SITE_URL=https://memes.markto.market NEXT_PUBLIC_ACCOUNT_HANDLE= diff --git a/server.ts b/server.ts index 55da595..8d23e55 100644 --- a/server.ts +++ b/server.ts @@ -1,11 +1,15 @@ import { createServer } from 'http'; import { parse } from 'url'; import next from 'next'; +import { DataSource, EntityTarget } from 'typeorm'; // Reference: https://github.com/motdotla/dotenv?tab=readme-ov-file#how-do-i-use-dotenv-with-import import 'dotenv/config' import { QuotesService } from './quotes-service'; +import { initializeDataSource } from './src/data-source'; +import { Payment } from './src/entity/Payment'; +import { Tweet } from './src/entity/Tweet'; const port = parseInt(process.env.PORT || '3000', 10); const app = next({ dev: process.env.NODE_ENV !== 'production' }); @@ -16,16 +20,25 @@ const quotesService = new QuotesService(); declare global { namespace NodeJS { interface Global { - quotesService: typeof quotesService + quotesService: QuotesService + appDataSource: DataSource + entities: { [key: string]: EntityTarget} } } } // TODO: Look for a better way to use quotesService // Initialize global quotes service -(global as any).quotesService = quotesService +global.quotesService = quotesService + +global.entities = { + Payment, + Tweet +}; app.prepare().then(async() => { + global.appDataSource = await initializeDataSource(); + const server = createServer(async (req, res) => { const parsedUrl = parse(req.url!, true); diff --git a/src/app/api/flux/route.ts b/src/app/api/flux/route.ts index 73b5b2e..afd9193 100644 --- a/src/app/api/flux/route.ts +++ b/src/app/api/flux/route.ts @@ -3,7 +3,6 @@ import BN from 'bn.js'; import { fal } from "@fal-ai/client" import { FLUX_MODELS } from '../../../services/fluxService' -import { initializeDataSource } from '../../../data-source' import { verifyPayment, markSignatureAsUsed } from '../../../utils/verifyPayment'; import { uploadToPinata } from '../../../utils/uploadToPinata'; @@ -22,8 +21,6 @@ const IMAGE_HEIGHT: number = 1024 export async function POST(req: NextRequest): Promise { try { - await initializeDataSource(); - const { prompt, modelId, transactionSignature } = await req.json(); const host = req.headers.get("host"); // Get the hostname from request headers const protocol = req.headers.get("x-forwarded-proto") || "http"; // Handle reverse proxies diff --git a/src/app/api/tweet/route.ts b/src/app/api/tweet/route.ts index bf187c6..c965fab 100644 --- a/src/app/api/tweet/route.ts +++ b/src/app/api/tweet/route.ts @@ -1,13 +1,9 @@ import { NextRequest, NextResponse } from 'next/server'; import { saveTweet, verifySignatureInTweet } from '../../../utils/verifyTweet'; -import { initializeDataSource } from '../../../data-source'; export async function POST(req: NextRequest): Promise { try { - // TODO: Move initialization to server file - await initializeDataSource(); - const { tweetUrl } = await req.json(); const url = `https://publish.twitter.com/oembed?url=${tweetUrl}&maxwidth=600`; diff --git a/src/data-source.ts b/src/data-source.ts index 0c4986b..df8bfdb 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -1,24 +1,21 @@ import { DataSource } from 'typeorm'; -import { Payment } from './entity/Payment'; - -export const AppDataSource = new DataSource({ - type: 'sqlite', - database: './database.sqlite', - synchronize: true, - logging: false, - // entities: [__dirname + "./entity/*{.js,.ts}"], - entities: [Payment], - migrations: [], - subscribers: [], -}); - export async function initializeDataSource() { try { - if (!AppDataSource.isInitialized){ - await AppDataSource.initialize(); - console.log('Data Source has been initialized!'); - }; + console.log('Initializing Data Source'); + + const appDataSource = new DataSource({ + type: 'sqlite', + database: './database.sqlite', + synchronize: true, + logging: false, + entities: [global.entities.Payment, global.entities.Tweet], + migrations: [], + subscribers: [], + }); + + await appDataSource.initialize(); + return appDataSource; } catch (err) { console.error('Error during Data Source initialization:', err); throw err; diff --git a/src/utils/verifyPayment.ts b/src/utils/verifyPayment.ts index 2b5f91a..92986d8 100644 --- a/src/utils/verifyPayment.ts +++ b/src/utils/verifyPayment.ts @@ -4,7 +4,6 @@ import BN from 'bn.js'; import { Connection } from '@solana/web3.js'; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; -import { AppDataSource } from '../data-source'; import { Payment } from '../entity/Payment'; assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required'); @@ -22,7 +21,7 @@ const connection = new Connection( ); export async function isSignatureUsed(transactionSignature: string): Promise { - const paymentRepository = AppDataSource.getRepository(Payment); + const paymentRepository = global.appDataSource.getRepository(global.entities.Payment); const payment = await paymentRepository.findOneBy({ transactionSignature }); if (payment) { return true; @@ -31,8 +30,8 @@ export async function isSignatureUsed(transactionSignature: string): Promise { - await AppDataSource.transaction(async (transactionalEntityManager) => { - const paymentRepository = transactionalEntityManager.getRepository(Payment); + await global.appDataSource.transaction(async (transactionalEntityManager) => { + const paymentRepository = transactionalEntityManager.getRepository(global.entities.Payment); // Check if the payment with the given signature already exists const exists = await paymentRepository.exists({ where: { transactionSignature } }); diff --git a/src/utils/verifyTweet.ts b/src/utils/verifyTweet.ts index e4eec30..c7ddc5e 100644 --- a/src/utils/verifyTweet.ts +++ b/src/utils/verifyTweet.ts @@ -1,16 +1,14 @@ -import { AppDataSource } from '../data-source'; -import { Payment } from '../entity/Payment'; import { Tweet } from '../entity/Tweet'; export async function verifySignatureInTweet(transactionSignature: string): Promise { - const paymentRepository = AppDataSource.getRepository(Payment); + const paymentRepository = global.appDataSource.getRepository(global.entities.Payment); const payment = await paymentRepository.findOneBy({ transactionSignature }); if (!payment) { return false; } - const tweetRepository = AppDataSource.getRepository(Tweet); + const tweetRepository = global.appDataSource.getRepository(global.entities.Tweet); const tweet = await tweetRepository.findOneBy({ transactionSignature }); if (tweet) { @@ -21,8 +19,8 @@ export async function verifySignatureInTweet(transactionSignature: string): Prom } export async function saveTweet(data: Partial): Promise<{ isFourthUser: boolean }> { - return await AppDataSource.transaction(async (transactionalEntityManager) => { - const tweetRepository = transactionalEntityManager.getRepository(Tweet); + return await global.appDataSource.transaction(async (transactionalEntityManager) => { + const tweetRepository = transactionalEntityManager.getRepository(global.entities.Tweet); const tweet = await tweetRepository.save(data);