introduce TRPC and service layer
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
console.log('AppHeader.vuew - setup script');
|
||||
const supabase = useSupabaseAuthClient();
|
||||
const user = useSupabaseUser();
|
||||
|
||||
|
||||
29
lib/services/notes.service.ts
Normal file
29
lib/services/notes.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
export default class NotesService {
|
||||
private prisma: PrismaClient;
|
||||
|
||||
constructor( prisma: PrismaClient) {
|
||||
this.prisma = prisma;
|
||||
}
|
||||
|
||||
async getAllNotes() {
|
||||
return this.prisma.note.findMany();
|
||||
}
|
||||
|
||||
async getNotesForAccountId(account_id: number) {
|
||||
return this.prisma.note.findMany({ where: { account_id } });
|
||||
}
|
||||
|
||||
async createNote( account_id: number, note_text: string ) {
|
||||
return this.prisma.note.create({ data: { account_id, note_text }});
|
||||
}
|
||||
|
||||
async updateNote(id: number, note_text: string) {
|
||||
return this.prisma.note.update({ where: { id }, data: { note_text } });
|
||||
}
|
||||
|
||||
async deleteNote(id: number) {
|
||||
return this.prisma.note.delete({ where: { id } });
|
||||
}
|
||||
}
|
||||
47
lib/services/user.service.ts
Normal file
47
lib/services/user.service.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { UtilService } from './util.service';
|
||||
|
||||
const TRIAL_PLAN_NAME = '3 Month Trial'; // TODO - some sort of config.. this will change for every use of the boilerplate
|
||||
|
||||
export default class UserService {
|
||||
private prisma: PrismaClient;
|
||||
|
||||
constructor( prisma: PrismaClient) {
|
||||
this.prisma = prisma;
|
||||
}
|
||||
|
||||
async getUserBySupabaseId(supabase_uid: string) {
|
||||
return this.prisma.user.findFirst({ where: { supabase_uid }, include: { membership: true } });
|
||||
}
|
||||
|
||||
async getUserById(id: number) {
|
||||
return this.prisma.user.findFirstOrThrow({ where: { id }, include: { membership: true } });
|
||||
}
|
||||
|
||||
async createUser( supabase_uid: string, display_name: string ) {
|
||||
const trialPlan = await this.prisma.plan.findFirstOrThrow({ where: { name: TRIAL_PLAN_NAME}});
|
||||
return this.prisma.user.create({
|
||||
data:{
|
||||
supabase_uid: supabase_uid,
|
||||
display_name: display_name,
|
||||
membership: {
|
||||
create: {
|
||||
account: {
|
||||
create: {
|
||||
plan_id: trialPlan.id,
|
||||
name: display_name,
|
||||
features: trialPlan.features, //copy in features from the plan, plan_id is a loose association and settings can change independently
|
||||
current_period_ends: UtilService.addMonths(new Date(),3),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
include: { membership: true },
|
||||
});
|
||||
}
|
||||
|
||||
async deleteUser(id: number) {
|
||||
return this.prisma.user.delete({ where: { id } });
|
||||
}
|
||||
}
|
||||
10
lib/services/util.service.ts
Normal file
10
lib/services/util.service.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export class UtilService {
|
||||
public static addMonths(date: Date, months: number): Date {
|
||||
const d = date.getDate();
|
||||
date.setMonth(date.getMonth() + +months);
|
||||
if (date.getDate() != d) {
|
||||
date.setDate(0);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
build: {
|
||||
transpile: ['trpc-nuxt']
|
||||
},
|
||||
typescript: {
|
||||
shim: false
|
||||
},
|
||||
|
||||
112
package-lock.json
generated
112
package-lock.json
generated
@@ -5,6 +5,12 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@trpc/client": "^10.9.0",
|
||||
"@trpc/server": "^10.9.0",
|
||||
"trpc-nuxt": "^0.5.0",
|
||||
"zod": "^3.20.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxtjs/supabase": "^0.3.0",
|
||||
"@prisma/client": "^4.9.0",
|
||||
@@ -1581,6 +1587,19 @@
|
||||
"cross-fetch": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@trpc/client": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@trpc/client/-/client-10.9.0.tgz",
|
||||
"integrity": "sha512-id6318qpgqllNOuBp7nuciXFPXCe+zae5d4r1hze6Eyp5fFFNO58TqA+4Q44KIcHgpfWyW2egs6iPeql3PrdKA==",
|
||||
"peerDependencies": {
|
||||
"@trpc/server": "10.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@trpc/server": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.9.0.tgz",
|
||||
"integrity": "sha512-5psyZgbvy29pJND32hwkWTMbv6s86IbsPOeDopsgNF0VegZT6Dsijmb7Ub/TDhuJVQVq5u4u5briMXi3SxmBkw=="
|
||||
},
|
||||
"node_modules/@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
@@ -2851,8 +2870,7 @@
|
||||
"node_modules/cookie-es": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-0.5.0.tgz",
|
||||
"integrity": "sha512-RyZrFi6PNpBFbIaQjXDlFIhFVqV42QeKSZX1yQIl6ihImq6vcHNGMtqQ/QzY3RMPuYSkvsRwtnt5M9NeYxKt0g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RyZrFi6PNpBFbIaQjXDlFIhFVqV42QeKSZX1yQIl6ihImq6vcHNGMtqQ/QzY3RMPuYSkvsRwtnt5M9NeYxKt0g=="
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
@@ -3207,8 +3225,7 @@
|
||||
"node_modules/destr": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/destr/-/destr-1.2.2.tgz",
|
||||
"integrity": "sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA=="
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
"version": "1.2.0",
|
||||
@@ -4050,7 +4067,6 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/h3/-/h3-1.1.0.tgz",
|
||||
"integrity": "sha512-kx3u+RMzY963fU8NNT2ePWgsryAn9DNztPqbHia/M7HgA+rtXKjHjED9/uidcYPmImNwAfJsCachCzh2T3QH2A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cookie-es": "^0.5.0",
|
||||
"destr": "^1.2.2",
|
||||
@@ -5156,8 +5172,7 @@
|
||||
"node_modules/node-fetch-native": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz",
|
||||
"integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg=="
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
@@ -5366,7 +5381,6 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.0.0.tgz",
|
||||
"integrity": "sha512-d40aof8czZFSQKJa4+F7Ch3UC5D631cK1TTUoK+iNEut9NoiCL+u0vykl/puYVUS2df4tIQl5upQcolIcEzQjQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"destr": "^1.2.1",
|
||||
"node-fetch-native": "^1.0.1",
|
||||
@@ -5376,8 +5390,7 @@
|
||||
"node_modules/ohash": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-1.0.0.tgz",
|
||||
"integrity": "sha512-kxSyzq6tt+6EE/xCnD1XaFhCCjUNUaz3X30rJp6mnjGLXAAvuPFqohMdv0aScWzajR45C29HyBaXZ8jXBwnh9A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-kxSyzq6tt+6EE/xCnD1XaFhCCjUNUaz3X30rJp6mnjGLXAAvuPFqohMdv0aScWzajR45C29HyBaXZ8jXBwnh9A=="
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.4.1",
|
||||
@@ -6233,8 +6246,7 @@
|
||||
"node_modules/radix3": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.0.0.tgz",
|
||||
"integrity": "sha512-6n3AEXth91ASapMVKiEh2wrbFJmI+NBilrWE0AbiGgfm0xet0QXC8+a3K19r1UVYjUjctUgB053c3V/J6V0kCQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-6n3AEXth91ASapMVKiEh2wrbFJmI+NBilrWE0AbiGgfm0xet0QXC8+a3K19r1UVYjUjctUgB053c3V/J6V0kCQ=="
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
@@ -7117,6 +7129,24 @@
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/trpc-nuxt": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/trpc-nuxt/-/trpc-nuxt-0.5.0.tgz",
|
||||
"integrity": "sha512-PZpmwc2QYkC1CWxGo3brFwou88zoP6cB9+GmlIffJJLKCmTY7XzIfarNxSbCocdeymJjMpcL/94t9kJm85/eTQ==",
|
||||
"dependencies": {
|
||||
"h3": "^1.0.2",
|
||||
"ofetch": "^1.0.0",
|
||||
"ohash": "^1.0.0",
|
||||
"ufo": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13.0 || ^18.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trpc/client": "^10.8.0",
|
||||
"@trpc/server": "^10.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
@@ -7153,8 +7183,7 @@
|
||||
"node_modules/ufo": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz",
|
||||
"integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA=="
|
||||
},
|
||||
"node_modules/ultrahtml": {
|
||||
"version": "1.2.0",
|
||||
@@ -8431,6 +8460,14 @@
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.20.2",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.20.2.tgz",
|
||||
"integrity": "sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -9511,6 +9548,17 @@
|
||||
"cross-fetch": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"@trpc/client": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@trpc/client/-/client-10.9.0.tgz",
|
||||
"integrity": "sha512-id6318qpgqllNOuBp7nuciXFPXCe+zae5d4r1hze6Eyp5fFFNO58TqA+4Q44KIcHgpfWyW2egs6iPeql3PrdKA==",
|
||||
"requires": {}
|
||||
},
|
||||
"@trpc/server": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.9.0.tgz",
|
||||
"integrity": "sha512-5psyZgbvy29pJND32hwkWTMbv6s86IbsPOeDopsgNF0VegZT6Dsijmb7Ub/TDhuJVQVq5u4u5briMXi3SxmBkw=="
|
||||
},
|
||||
"@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
@@ -10474,8 +10522,7 @@
|
||||
"cookie-es": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-0.5.0.tgz",
|
||||
"integrity": "sha512-RyZrFi6PNpBFbIaQjXDlFIhFVqV42QeKSZX1yQIl6ihImq6vcHNGMtqQ/QzY3RMPuYSkvsRwtnt5M9NeYxKt0g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RyZrFi6PNpBFbIaQjXDlFIhFVqV42QeKSZX1yQIl6ihImq6vcHNGMtqQ/QzY3RMPuYSkvsRwtnt5M9NeYxKt0g=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.3",
|
||||
@@ -10735,8 +10782,7 @@
|
||||
"destr": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/destr/-/destr-1.2.2.tgz",
|
||||
"integrity": "sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA=="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.2.0",
|
||||
@@ -11374,7 +11420,6 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/h3/-/h3-1.1.0.tgz",
|
||||
"integrity": "sha512-kx3u+RMzY963fU8NNT2ePWgsryAn9DNztPqbHia/M7HgA+rtXKjHjED9/uidcYPmImNwAfJsCachCzh2T3QH2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cookie-es": "^0.5.0",
|
||||
"destr": "^1.2.2",
|
||||
@@ -12237,8 +12282,7 @@
|
||||
"node-fetch-native": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz",
|
||||
"integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg=="
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "1.3.1",
|
||||
@@ -12398,7 +12442,6 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.0.0.tgz",
|
||||
"integrity": "sha512-d40aof8czZFSQKJa4+F7Ch3UC5D631cK1TTUoK+iNEut9NoiCL+u0vykl/puYVUS2df4tIQl5upQcolIcEzQjQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"destr": "^1.2.1",
|
||||
"node-fetch-native": "^1.0.1",
|
||||
@@ -12408,8 +12451,7 @@
|
||||
"ohash": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-1.0.0.tgz",
|
||||
"integrity": "sha512-kxSyzq6tt+6EE/xCnD1XaFhCCjUNUaz3X30rJp6mnjGLXAAvuPFqohMdv0aScWzajR45C29HyBaXZ8jXBwnh9A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-kxSyzq6tt+6EE/xCnD1XaFhCCjUNUaz3X30rJp6mnjGLXAAvuPFqohMdv0aScWzajR45C29HyBaXZ8jXBwnh9A=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
@@ -12985,8 +13027,7 @@
|
||||
"radix3": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.0.0.tgz",
|
||||
"integrity": "sha512-6n3AEXth91ASapMVKiEh2wrbFJmI+NBilrWE0AbiGgfm0xet0QXC8+a3K19r1UVYjUjctUgB053c3V/J6V0kCQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-6n3AEXth91ASapMVKiEh2wrbFJmI+NBilrWE0AbiGgfm0xet0QXC8+a3K19r1UVYjUjctUgB053c3V/J6V0kCQ=="
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
@@ -13654,6 +13695,17 @@
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"dev": true
|
||||
},
|
||||
"trpc-nuxt": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/trpc-nuxt/-/trpc-nuxt-0.5.0.tgz",
|
||||
"integrity": "sha512-PZpmwc2QYkC1CWxGo3brFwou88zoP6cB9+GmlIffJJLKCmTY7XzIfarNxSbCocdeymJjMpcL/94t9kJm85/eTQ==",
|
||||
"requires": {
|
||||
"h3": "^1.0.2",
|
||||
"ofetch": "^1.0.0",
|
||||
"ohash": "^1.0.0",
|
||||
"ufo": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
@@ -13684,8 +13736,7 @@
|
||||
"ufo": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz",
|
||||
"integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA=="
|
||||
},
|
||||
"ultrahtml": {
|
||||
"version": "1.2.0",
|
||||
@@ -14525,6 +14576,11 @@
|
||||
"compress-commons": "^4.1.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
}
|
||||
},
|
||||
"zod": {
|
||||
"version": "3.20.2",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.20.2.tgz",
|
||||
"integrity": "sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,11 @@
|
||||
"@prisma/client": "^4.9.0",
|
||||
"nuxt": "^3.1.1",
|
||||
"prisma": "^4.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trpc/client": "^10.9.0",
|
||||
"@trpc/server": "^10.9.0",
|
||||
"trpc-nuxt": "^0.5.0",
|
||||
"zod": "^3.20.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
middleware: ['auth'],
|
||||
});
|
||||
|
||||
const notes = await $fetch('/api/notes')
|
||||
const { $client } = useNuxtApp()
|
||||
const { data: notes } = await $client.notes.useQuery({ text: 'client' })
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<h3>{{ user?.user_metadata.full_name }}'s Dashboard</h3>
|
||||
<p v-for="note in notes">{{ note.note_text }}</p><!-- TODO - wtf.. typing-->
|
||||
<div>Stuff</div>
|
||||
<h3>{{ user?.user_metadata.full_name }}'s Notes Dashboard</h3>
|
||||
<p v-for="note in notes?.notes">{{ note.note_text }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
22
plugins/trpcClient.ts
Normal file
22
plugins/trpcClient.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { createTRPCNuxtClient, httpBatchLink } from 'trpc-nuxt/client'
|
||||
import type { AppRouter } from '~/server/api/trpc/[trpc]'
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
/**
|
||||
* createTRPCNuxtClient adds a `useQuery` composable
|
||||
* built on top of `useAsyncData`.
|
||||
*/
|
||||
const client = createTRPCNuxtClient<AppRouter>({
|
||||
links: [
|
||||
httpBatchLink({
|
||||
url: '/api/trpc',
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
return {
|
||||
provide: {
|
||||
client,
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { serverSupabaseClient } from '#supabase/server';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const client = serverSupabaseClient(event)
|
||||
const user = await client.auth.getUser();
|
||||
|
||||
const dbUser = await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
supabase_uid: user.data.id // TODO - this shit is messy.. typing
|
||||
},
|
||||
include: {
|
||||
membership: true, // Return all fields
|
||||
},
|
||||
});
|
||||
|
||||
const data = await prisma.note.findMany({
|
||||
where:{
|
||||
account_id: dbUser.membership?.account_id
|
||||
}
|
||||
});
|
||||
return data;
|
||||
})
|
||||
37
server/api/trpc/[trpc].ts
Normal file
37
server/api/trpc/[trpc].ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* This is the API-handler of your app that contains all your API routes.
|
||||
* On a bigger app, you will probably want to split this file up into multiple files.
|
||||
*/
|
||||
import { createNuxtApiHandler } from 'trpc-nuxt'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { publicProcedure, router } from '~/server/trpc/trpc'
|
||||
import { createContext } from '~~/server/trpc/context';
|
||||
import NotesService from '~~/lib/services/notes.service';
|
||||
|
||||
export const appRouter = router({
|
||||
notes: publicProcedure
|
||||
.input(
|
||||
z.object({
|
||||
text: z.string().nullish(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const notesService = new NotesService(ctx.prisma);
|
||||
const notes = await notesService.getNotesForAccountId(ctx.dbUser.membership?.account_id);
|
||||
return {
|
||||
notes,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
// export only the type definition of the API
|
||||
// None of the actual implementation is exposed to the client
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
// export API handler
|
||||
export default createNuxtApiHandler({
|
||||
router: appRouter,
|
||||
createContext: createContext,
|
||||
onError({ error}) { console.error(error)}, // TODO - logging and reporting
|
||||
})
|
||||
43
server/trpc/context.ts
Normal file
43
server/trpc/context.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import type { inferAsyncReturnType } from '@trpc/server'
|
||||
import { H3Event } from 'h3';
|
||||
import { serverSupabaseClient } from '#supabase/server';
|
||||
import SupabaseClient from '@supabase/supabase-js/dist/module/SupabaseClient';
|
||||
import { User } from '@supabase/supabase-js';
|
||||
import UserService from '~~/lib/services/user.service';
|
||||
|
||||
let prisma: PrismaClient | undefined
|
||||
let supabase: SupabaseClient | undefined
|
||||
let user: User | null = null;
|
||||
let dbUser: any | undefined
|
||||
|
||||
export async function createContext(event: H3Event){
|
||||
if (!supabase) {
|
||||
supabase = serverSupabaseClient(event)
|
||||
}
|
||||
if (!user) {
|
||||
({data: { user }} = await supabase.auth.getUser());
|
||||
}
|
||||
if (!prisma) {
|
||||
prisma = new PrismaClient()
|
||||
}
|
||||
if (!dbUser && user) {
|
||||
const userService = new UserService(prisma);
|
||||
dbUser = await userService.getUserBySupabaseId(user.id);
|
||||
|
||||
if (!dbUser && user) {
|
||||
dbUser = await userService.createUser( user.id, user.user_metadata.full_name );
|
||||
console.log(`\n Created user \n ${JSON.stringify(dbUser)}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - This seems excessive, trim context when I have figured out what I actually need
|
||||
return {
|
||||
supabase,
|
||||
user,
|
||||
prisma,
|
||||
dbUser,
|
||||
}
|
||||
};
|
||||
|
||||
export type Context = inferAsyncReturnType<typeof createContext>
|
||||
21
server/trpc/trpc.ts
Normal file
21
server/trpc/trpc.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This is your entry point to setup the root configuration for tRPC on the server.
|
||||
* - `initTRPC` should only be used once per app.
|
||||
* - We export only the functionality that we use so we can enforce which base procedures should be used
|
||||
*
|
||||
* Learn how to create protected base procedures and other things below:
|
||||
* @see https://trpc.io/docs/v10/router
|
||||
* @see https://trpc.io/docs/v10/procedures
|
||||
*/
|
||||
import { initTRPC } from '@trpc/server'
|
||||
import { Context } from './context';
|
||||
|
||||
const t = initTRPC.context<Context>().create()
|
||||
|
||||
/**
|
||||
* Unprotected procedure
|
||||
**/
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
export const router = t.router;
|
||||
export const middleware = t.middleware;
|
||||
Reference in New Issue
Block a user