ok do sqlite
This commit is contained in:
parent
feb0187704
commit
d32bf5a1f3
6 changed files with 1571 additions and 40 deletions
1508
package-lock.json
generated
1508
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
WHERE
|
||||||
|
LOWER(title) LIKE ? OR
|
||||||
|
LOWER(content) LIKE ? OR
|
||||||
|
LOWER(tags) LIKE ?
|
||||||
|
ORDER BY createdAt DESC`,
|
||||||
|
lowerCaseQuery,
|
||||||
|
lowerCaseQuery,
|
||||||
|
lowerCaseQuery
|
||||||
|
);
|
||||||
|
|
||||||
return prompts.filter(prompt => {
|
return results.map(row => ({
|
||||||
const inTitle = prompt.title.toLowerCase().includes(lowerCaseQuery);
|
...row,
|
||||||
const inContent = prompt.content.toLowerCase().includes(lowerCaseQuery);
|
tags: JSON.parse(row.tags),
|
||||||
const inTags = prompt.tags.some(tag => tag.toLowerCase().includes(lowerCaseQuery));
|
}));
|
||||||
return inTitle || inContent || inTags;
|
|
||||||
}).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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: {} };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
41
src/lib/db.ts
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue