ok do sqlite

This commit is contained in:
Aun Ali 2025-08-09 15:48:05 +00:00
parent feb0187704
commit d32bf5a1f3
6 changed files with 1571 additions and 40 deletions

1508
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -51,6 +51,8 @@
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"recharts": "^2.15.1", "recharts": "^2.15.1",
"sqlite": "^5.1.1",
"sqlite3": "^5.1.7",
"tailwind-merge": "^3.0.1", "tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"zod": "^3.24.2" "zod": "^3.24.2"

View file

@ -2,26 +2,32 @@
'use server'; 'use server';
import { revalidatePath } from 'next/cache'; import { revalidatePath } from 'next/cache';
import { prompts as dbPrompts } from './data'; import { getDb } from './db';
import type { Prompt } from './types'; import type { Prompt } from './types';
import { suggestTags as suggestTagsFlow } from '@/ai/flows/suggest-tags'; import { suggestTags as suggestTagsFlow } from '@/ai/flows/suggest-tags';
import { suggestTitle as suggestTitleFlow } from '@/ai/flows/suggest-title'; import { suggestTitle as suggestTitleFlow } from '@/ai/flows/suggest-title';
import { z } from 'zod'; import { z } from 'zod';
// In-memory store, mimicking a database.
let prompts: Prompt[] = [...dbPrompts];
export async function getPrompts(query: string = ''): Promise<Prompt[]> { export async function getPrompts(query: string = ''): Promise<Prompt[]> {
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate network delay const db = await getDb();
const lowerCaseQuery = `%${query.toLowerCase()}%`;
const lowerCaseQuery = query.toLowerCase(); const results = await db.all(
`SELECT * FROM prompts
return prompts.filter(prompt => { WHERE
const inTitle = prompt.title.toLowerCase().includes(lowerCaseQuery); LOWER(title) LIKE ? OR
const inContent = prompt.content.toLowerCase().includes(lowerCaseQuery); LOWER(content) LIKE ? OR
const inTags = prompt.tags.some(tag => tag.toLowerCase().includes(lowerCaseQuery)); LOWER(tags) LIKE ?
return inTitle || inContent || inTags; ORDER BY createdAt DESC`,
}).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); lowerCaseQuery,
lowerCaseQuery,
lowerCaseQuery
);
return results.map(row => ({
...row,
tags: JSON.parse(row.tags),
}));
} }
const CreatePromptSchema = z.object({ const CreatePromptSchema = z.object({
@ -48,24 +54,23 @@ export async function createPrompt(prevState: any, formData: FormData) {
const { content, notes, tags } = validatedFields.data; const { content, notes, tags } = validatedFields.data;
try { try {
const db = await getDb();
const { title } = await suggestTitleFlow({ promptText: content }); const { title } = await suggestTitleFlow({ promptText: content });
const newPrompt: Prompt = { await db.run(
id: Date.now().toString(), 'INSERT INTO prompts (title, content, notes, tags, createdAt) VALUES (?, ?, ?, ?, ?)',
title, title,
content, content,
notes, notes,
tags: JSON.parse(tags), tags, // Already a JSON string
createdAt: new Date().toISOString(), new Date().toISOString()
}; );
// Add to the start of the array to show newest first
prompts.unshift(newPrompt);
revalidatePath('/'); revalidatePath('/');
return { message: 'Prompt created successfully.', success: true }; return { message: 'Prompt created successfully.', success: true };
} catch (e) { } catch (e) {
console.error(e);
return { message: 'An unexpected error occurred.', errors: {} }; return { message: 'An unexpected error occurred.', errors: {} };
} }
} }

View file

@ -1,8 +1,8 @@
import type { Prompt } from './types'; import type { Prompt } from './types';
export const prompts: Prompt[] = [ // This data is now only used to seed the database on its first run.
export const initialPrompts: Omit<Prompt, 'id'>[] = [
{ {
id: '1',
title: 'Blog Post Ideas Generator', title: 'Blog Post Ideas Generator',
content: 'Generate 10 blog post ideas for a blog about AI development. The ideas should be catchy, relevant to current trends, and suitable for a technical audience. For each idea, provide a brief description and a potential headline.', content: 'Generate 10 blog post ideas for a blog about AI development. The ideas should be catchy, relevant to current trends, and suitable for a technical audience. For each idea, provide a brief description and a potential headline.',
tags: ['writing', 'ai', 'content-creation'], tags: ['writing', 'ai', 'content-creation'],
@ -10,21 +10,18 @@ export const prompts: Prompt[] = [
notes: 'Great for weekly content planning.' notes: 'Great for weekly content planning.'
}, },
{ {
id: '2',
title: 'Python Code Refactoring', title: 'Python Code Refactoring',
content: 'Act as a senior Python developer. Take the following code snippet and refactor it for better readability, performance, and adherence to PEP 8 standards. Explain the changes you made and why.', content: 'Act as a senior Python developer. Take the following code snippet and refactor it for better readability, performance, and adherence to PEP 8 standards. Explain the changes you made and why.',
tags: ['python', 'code', 'development', 'refactoring'], tags: ['python', 'code', 'development', 'refactoring'],
createdAt: new Date(new Date().setDate(new Date().getDate()-2)).toISOString(), createdAt: new Date(new Date().setDate(new Date().getDate()-2)).toISOString(),
}, },
{ {
id: '3',
title: 'Marketing Campaign Slogans', title: 'Marketing Campaign Slogans',
content: 'Create 5 compelling slogans for a new brand of eco-friendly coffee. The slogans should be short, memorable, and highlight the brand\'s commitment to sustainability.', content: 'Create 5 compelling slogans for a new brand of eco-friendly coffee. The slogans should be short, memorable, and highlight the brand\'s commitment to sustainability.',
tags: ['marketing', 'copywriting', 'branding'], tags: ['marketing', 'copywriting', 'branding'],
createdAt: new Date(new Date().setDate(new Date().getDate()-3)).toISOString(), createdAt: new Date(new Date().setDate(new Date().getDate()-3)).toISOString(),
}, },
{ {
id: '4',
title: 'Explain Quantum Computing', title: 'Explain Quantum Computing',
content: 'Explain the concept of quantum computing to a 12-year-old. Use simple analogies and avoid technical jargon as much as possible. Cover the ideas of qubits, superposition, and entanglement.', content: 'Explain the concept of quantum computing to a 12-year-old. Use simple analogies and avoid technical jargon as much as possible. Cover the ideas of qubits, superposition, and entanglement.',
tags: ['education', 'science', 'complex-topics'], tags: ['education', 'science', 'complex-topics'],
@ -32,28 +29,24 @@ export const prompts: Prompt[] = [
notes: 'Useful for breaking down difficult concepts for presentations.' notes: 'Useful for breaking down difficult concepts for presentations.'
}, },
{ {
id: '5',
title: 'Generate SQL Query', title: 'Generate SQL Query',
content: 'Given a database schema with two tables, `users` (id, name, email, signup_date) and `orders` (id, user_id, amount, order_date), write a SQL query to find the total order amount for each user in the last 30 days.', content: 'Given a database schema with two tables, `users` (id, name, email, signup_date) and `orders` (id, user_id, amount, order_date), write a SQL query to find the total order amount for each user in the last 30 days.',
tags: ['sql', 'database', 'code'], tags: ['sql', 'database', 'code'],
createdAt: new Date(new Date().setDate(new Date().getDate()-5)).toISOString(), createdAt: new Date(new Date().setDate(new Date().getDate()-5)).toISOString(),
}, },
{ {
id: '6',
title: 'Social Media Post for Product Launch', title: 'Social Media Post for Product Launch',
content: 'Write a social media post for Twitter announcing the launch of a new productivity app called "Zenith". The tone should be exciting and engaging. Include relevant hashtags.', content: 'Write a social media post for Twitter announcing the launch of a new productivity app called "Zenith". The tone should be exciting and engaging. Include relevant hashtags.',
tags: ['social-media', 'marketing', 'launch'], tags: ['social-media', 'marketing', 'launch'],
createdAt: new Date(new Date().setDate(new Date().getDate()-6)).toISOString(), createdAt: new Date(new Date().setDate(new Date().getDate()-6)).toISOString(),
}, },
{ {
id: '7',
title: 'Midjourney Prompt for a Spaceship', title: 'Midjourney Prompt for a Spaceship',
content: 'Generate a detailed Midjourney prompt to create a photorealistic image of a sleek, futuristic exploration spaceship floating in front of a nebula. The design should be minimalist, with glowing blue accents. Include parameters for aspect ratio and style.', content: 'Generate a detailed Midjourney prompt to create a photorealistic image of a sleek, futuristic exploration spaceship floating in front of a nebula. The design should be minimalist, with glowing blue accents. Include parameters for aspect ratio and style.',
tags: ['midjourney', 'image-generation', 'art'], tags: ['midjourney', 'image-generation', 'art'],
createdAt: new Date(new Date().setDate(new Date().getDate()-7)).toISOString(), createdAt: new Date(new Date().setDate(new Date().getDate()-7)).toISOString(),
}, },
{ {
id: '8',
title: 'Recipe from Ingredients', title: 'Recipe from Ingredients',
content: 'I have chicken breasts, broccoli, garlic, and lemon in my fridge. Create a simple and healthy recipe I can make for dinner tonight. Provide step-by-step instructions.', content: 'I have chicken breasts, broccoli, garlic, and lemon in my fridge. Create a simple and healthy recipe I can make for dinner tonight. Provide step-by-step instructions.',
tags: ['food', 'recipe', 'lifestyle'], tags: ['food', 'recipe', 'lifestyle'],

41
src/lib/db.ts Normal file
View file

@ -0,0 +1,41 @@
// This file uses server-side code.
import { open } from 'sqlite';
import sqlite3 from 'sqlite3';
import { initialPrompts } from './data';
// Singleton pattern to ensure only one database connection is created.
let db: Awaited<ReturnType<typeof open>> | null = null;
export async function getDb() {
if (!db) {
const newDb = await open({
filename: './database.db',
driver: sqlite3.Database,
});
// Perform migrations
await newDb.exec(`
CREATE TABLE IF NOT EXISTS prompts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL,
notes TEXT,
tags TEXT NOT NULL,
createdAt TEXT NOT NULL
);
`);
// Seed initial data if the table is empty
const countResult = await newDb.get('SELECT COUNT(*) as count FROM prompts');
if (countResult && countResult.count === 0) {
const stmt = await newDb.prepare('INSERT INTO prompts (title, content, notes, tags, createdAt) VALUES (?, ?, ?, ?, ?)');
for (const prompt of initialPrompts) {
await stmt.run(prompt.title, prompt.content, prompt.notes, JSON.stringify(prompt.tags), prompt.createdAt);
}
await stmt.finalize();
}
db = newDb;
}
return db;
}

View file

@ -1,5 +1,5 @@
export interface Prompt { export interface Prompt {
id: string; id: number;
title: string; title: string;
content: string; content: string;
notes?: string; notes?: string;