OpenAI integration and Note generation from prompt
This commit is contained in:
@@ -12,4 +12,6 @@ STRIPE_CALLBACK_URL=http://localhost:3000
|
|||||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
||||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||||
|
|
||||||
DATABASE_URL="postgresql://postgres:xxxxxxxxxxxxx@db.xxxxxxxxxxxxx.supabase.co:5432/postgres"
|
DATABASE_URL="postgresql://postgres:xxxxxxxxxxxxx@db.xxxxxxxxxxxxx.supabase.co:5432/postgres"
|
||||||
|
|
||||||
|
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
@@ -11,6 +11,7 @@ Please don't hitch your wagon to this star just yet... I'm coding this in the op
|
|||||||
- Pinia (State Store. I liked vuex a lot, in particular explicit mutations but gotta go with the cool crowd)
|
- Pinia (State Store. I liked vuex a lot, in particular explicit mutations but gotta go with the cool crowd)
|
||||||
- Stripe (Payments including Webhook integration)
|
- Stripe (Payments including Webhook integration)
|
||||||
- Tailwind + daisyUI (Tailwind because everybody is using it, daisyUI because I suck at tailwind)
|
- Tailwind + daisyUI (Tailwind because everybody is using it, daisyUI because I suck at tailwind)
|
||||||
|
- OpenAI (text completions with AI)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
### User Management
|
### User Management
|
||||||
@@ -71,6 +72,7 @@ Please don't hitch your wagon to this star just yet... I'm coding this in the op
|
|||||||
- [x] Max Notes limit property on Plan
|
- [x] Max Notes limit property on Plan
|
||||||
- [x] Max Notes enforced
|
- [x] Max Notes enforced
|
||||||
- [x] Add, Delete notes on Dashboard
|
- [x] Add, Delete notes on Dashboard
|
||||||
|
- [x] AI Note generation with OpenAI
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
- [x] Manual test scenario for auth and sub workflows passing
|
- [x] Manual test scenario for auth and sub workflows passing
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import prisma_client from '~~/prisma/prisma.client';
|
import prisma_client from '~~/prisma/prisma.client';
|
||||||
|
import { openai } from './openai.client';
|
||||||
|
|
||||||
export default class NotesService {
|
export default class NotesService {
|
||||||
async getAllNotes() {
|
async getAllNotes() {
|
||||||
@@ -33,4 +34,20 @@ export default class NotesService {
|
|||||||
async deleteNote(id: number) {
|
async deleteNote(id: number) {
|
||||||
return prisma_client.note.delete({ where: { id } });
|
return prisma_client.note.delete({ where: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async generateAINoteFromPrompt(userPrompt: string) {
|
||||||
|
const prompt = `
|
||||||
|
Write an interesting short note about ${userPrompt}.
|
||||||
|
Restrict the note to a single paragraph.
|
||||||
|
`
|
||||||
|
const completion = await openai.createCompletion({
|
||||||
|
model: "text-davinci-003",
|
||||||
|
prompt,
|
||||||
|
temperature: 0.6,
|
||||||
|
stop: "\n\n",
|
||||||
|
max_tokens: 1000,
|
||||||
|
n: 1,
|
||||||
|
});
|
||||||
|
return completion.data.choices[0].text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
lib/services/openai.client.ts
Normal file
9
lib/services/openai.client.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Configuration, OpenAIApi } from "openai";
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
|
||||||
|
const configuration = new Configuration({
|
||||||
|
apiKey: config.openAIKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const openai = new OpenAIApi(configuration);
|
||||||
@@ -18,6 +18,7 @@ export default defineNuxtConfig({
|
|||||||
subscriptionGraceDays: 3,
|
subscriptionGraceDays: 3,
|
||||||
initialPlanName: 'Free Trial',
|
initialPlanName: 'Free Trial',
|
||||||
initialPlanActiveMonths: 1,
|
initialPlanActiveMonths: 1,
|
||||||
|
openAIKey: process.env.OPENAI_API_KEY,
|
||||||
public: {
|
public: {
|
||||||
debugMode: true,
|
debugMode: true,
|
||||||
siteRootUrl: 'http://localhost:3000',
|
siteRootUrl: 'http://localhost:3000',
|
||||||
|
|||||||
110
package-lock.json
generated
110
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"@trpc/server": "^10.9.0",
|
"@trpc/server": "^10.9.0",
|
||||||
"daisyui": "^2.51.5",
|
"daisyui": "^2.51.5",
|
||||||
"generate-password-ts": "^1.6.3",
|
"generate-password-ts": "^1.6.3",
|
||||||
|
"openai": "^3.2.1",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"stripe": "^11.12.0",
|
"stripe": "^11.12.0",
|
||||||
"superjson": "^1.12.2",
|
"superjson": "^1.12.2",
|
||||||
@@ -2914,6 +2915,11 @@
|
|||||||
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==",
|
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
|
},
|
||||||
"node_modules/at-least-node": {
|
"node_modules/at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@@ -2955,6 +2961,14 @@
|
|||||||
"postcss": "^8.1.0"
|
"postcss": "^8.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.14.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -3595,6 +3609,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
|
||||||
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
|
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
@@ -4097,6 +4122,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
|
||||||
"integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
|
"integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/delegates": {
|
"node_modules/delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||||
@@ -4720,7 +4753,6 @@
|
|||||||
"version": "1.15.2",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -4736,6 +4768,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/formdata-polyfill": {
|
"node_modules/formdata-polyfill": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
@@ -6374,7 +6419,6 @@
|
|||||||
"version": "1.52.0",
|
"version": "1.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
@@ -6383,7 +6427,6 @@
|
|||||||
"version": "2.1.35",
|
"version": "2.1.35",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mime-db": "1.52.0"
|
"mime-db": "1.52.0"
|
||||||
},
|
},
|
||||||
@@ -7161,6 +7204,15 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openai": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.26.0",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ora": {
|
"node_modules/ora": {
|
||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz",
|
||||||
@@ -13417,6 +13469,11 @@
|
|||||||
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==",
|
"integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
|
},
|
||||||
"at-least-node": {
|
"at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||||
@@ -13436,6 +13493,14 @@
|
|||||||
"postcss-value-parser": "^4.2.0"
|
"postcss-value-parser": "^4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "^1.14.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -13874,6 +13939,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
|
||||||
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
|
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
|
||||||
},
|
},
|
||||||
|
"combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"requires": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"commander": {
|
"commander": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
@@ -14245,6 +14318,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
|
||||||
"integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
|
"integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
|
||||||
},
|
},
|
||||||
|
"delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||||
|
},
|
||||||
"delegates": {
|
"delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||||
@@ -14731,8 +14809,17 @@
|
|||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.15.2",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||||
"dev": true
|
},
|
||||||
|
"form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"formdata-polyfill": {
|
"formdata-polyfill": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
@@ -16003,14 +16090,12 @@
|
|||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.52.0",
|
"version": "1.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.35",
|
"version": "2.1.35",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "1.52.0"
|
"mime-db": "1.52.0"
|
||||||
}
|
}
|
||||||
@@ -16633,6 +16718,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"openai": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==",
|
||||||
|
"requires": {
|
||||||
|
"axios": "^0.26.0",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ora": {
|
"ora": {
|
||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"@trpc/server": "^10.9.0",
|
"@trpc/server": "^10.9.0",
|
||||||
"daisyui": "^2.51.5",
|
"daisyui": "^2.51.5",
|
||||||
"generate-password-ts": "^1.6.3",
|
"generate-password-ts": "^1.6.3",
|
||||||
|
"openai": "^3.2.1",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"stripe": "^11.12.0",
|
"stripe": "^11.12.0",
|
||||||
"superjson": "^1.12.2",
|
"superjson": "^1.12.2",
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
newNoteText.value = '';
|
newNoteText.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function genNote(){
|
||||||
|
const genNoteText = await notesStore.generateAINoteFromPrompt(newNoteText.value)
|
||||||
|
newNoteText.value = genNoteText;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await accountStore.init();
|
await accountStore.init();
|
||||||
await notesStore.fetchNotesForCurrentUser();
|
await notesStore.fetchNotesForCurrentUser();
|
||||||
@@ -28,13 +33,18 @@
|
|||||||
<h2 class="text-4xl font-extrabold tracking-tight text-gray-900 sm:text-5xl md:text-6xl mb-4">Notes Dashboard</h2>
|
<h2 class="text-4xl font-extrabold tracking-tight text-gray-900 sm:text-5xl md:text-6xl mb-4">Notes Dashboard</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full max-w-md mb-8">
|
<div v-if="activeMembership && (activeMembership.access === ACCOUNT_ACCESS.READ_WRITE || activeMembership.access === ACCOUNT_ACCESS.ADMIN || activeMembership.access === ACCOUNT_ACCESS.OWNER)" class="w-full max-w-md mx-auto mb-3">
|
||||||
<div v-if="activeMembership && (activeMembership.access === ACCOUNT_ACCESS.READ_WRITE || activeMembership.access === ACCOUNT_ACCESS.ADMIN || activeMembership.access === ACCOUNT_ACCESS.OWNER)" class="flex flex-row">
|
<textarea v-model="newNoteText" type="text" class="w-full rounded-l-md py-2 px-4 border-gray-400 border-2 focus:outline-none focus:border-blue-500" rows="5" placeholder="Add a note..."/>
|
||||||
<input v-model="newNoteText" type="text" class="w-full rounded-l-md py-2 px-4 border-gray-400 border-2 focus:outline-none focus:border-blue-500" placeholder="Add a note...">
|
<div class="flex justify-evenly">
|
||||||
<button @click.prevent="addNote()" type="button"
|
<button @click.prevent="addNote()" type="button"
|
||||||
class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-r-md focus:outline-none focus:shadow-outline-blue">
|
class="px-4 py-2 text-white bg-blue-500 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
|
<button @click.prevent="genNote()" type="button"
|
||||||
|
class="px-4 py-2 text-white bg-orange-500 rounded-md hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-opacity-50">
|
||||||
|
Gen
|
||||||
|
<Icon name="mdi:magic" class="h-6 w-6"/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const user = useSupabaseUser()
|
|||||||
<li>
|
<li>
|
||||||
<Icon name="skill-icons:postgresql-dark" class="h-12 w-12 mb-2" />
|
<Icon name="skill-icons:postgresql-dark" class="h-12 w-12 mb-2" />
|
||||||
<h3 class="text-xl font-medium text-gray-900">PostgreSQL</h3>
|
<h3 class="text-xl font-medium text-gray-900">PostgreSQL</h3>
|
||||||
<p class="mt-2 text-base text-gray-500">The Progressive JavaScript Framework</p>
|
<p class="mt-2 text-base text-gray-500">Relational Database</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Icon name="logos:prisma" class="h-12 w-12 mb-2" />
|
<Icon name="logos:prisma" class="h-12 w-12 mb-2" />
|
||||||
@@ -86,6 +86,11 @@ const user = useSupabaseUser()
|
|||||||
<h3 class="text-xl font-medium text-gray-900">Vue.js</h3>
|
<h3 class="text-xl font-medium text-gray-900">Vue.js</h3>
|
||||||
<p class="mt-2 text-base text-gray-500">The Progressive JavaScript Framework</p>
|
<p class="mt-2 text-base text-gray-500">The Progressive JavaScript Framework</p>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<Icon name="logos:openai-icon" class="h-12 w-12 mb-2" />
|
||||||
|
<h3 class="text-xl font-medium text-gray-900">OpenAI</h3>
|
||||||
|
<p class="mt-2 text-base text-gray-500">AI Completions including Note generation from prompt</p>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,4 +38,13 @@ export const notesRouter = router({
|
|||||||
note,
|
note,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
generateAINoteFromPrompt: readWriteProcedure
|
||||||
|
.input(z.object({ user_prompt: z.string() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const notesService = new NotesService();
|
||||||
|
const noteText = (ctx.activeAccountId)?await notesService.generateAINoteFromPrompt(input.user_prompt):null;
|
||||||
|
return {
|
||||||
|
noteText
|
||||||
|
}
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
@@ -2,10 +2,6 @@ import { Note } from ".prisma/client"
|
|||||||
import { defineStore, storeToRefs } from "pinia"
|
import { defineStore, storeToRefs } from "pinia"
|
||||||
import { Ref } from "vue";
|
import { Ref } from "vue";
|
||||||
|
|
||||||
interface State {
|
|
||||||
notes: Note[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note) the Notes Store needs to be a 'Setup Store' (https://pinia.vuejs.org/core-concepts/#setup-stores)
|
Note) the Notes Store needs to be a 'Setup Store' (https://pinia.vuejs.org/core-concepts/#setup-stores)
|
||||||
because this enables the use of the watch on the Account Store
|
because this enables the use of the watch on the Account Store
|
||||||
@@ -42,10 +38,16 @@ export const useNotesStore = defineStore('notes', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generateAINoteFromPrompt(user_prompt: string) {
|
||||||
|
const { $client } = useNuxtApp();
|
||||||
|
const { noteText } = await $client.notes.generateAINoteFromPrompt.query({user_prompt});
|
||||||
|
return noteText?noteText:'';
|
||||||
|
}
|
||||||
|
|
||||||
// if the active account changes, fetch notes again (i.e dynamic.. probabl overkill)
|
// if the active account changes, fetch notes again (i.e dynamic.. probabl overkill)
|
||||||
watch(activeAccountId, async (val, oldVal)=> {
|
watch(activeAccountId, async (val, oldVal)=> {
|
||||||
await fetchNotesForCurrentUser()
|
await fetchNotesForCurrentUser()
|
||||||
});
|
});
|
||||||
|
|
||||||
return { notes: _notes, fetchNotesForCurrentUser, createNote, deleteNote }
|
return { notes: _notes, fetchNotesForCurrentUser, createNote, deleteNote, generateAINoteFromPrompt}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user