first commit
Some checks failed
ci / ci (22, ubuntu-latest) (push) Has been cancelled

This commit is contained in:
AlucardDev
2026-08-28 23:32:07 +03:00
commit 7d4ff5962c
35 changed files with 15426 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
export default defineOAuthGitHubEventHandler({
async onSuccess(event, { user }) {
await setUserSession(event, { user })
return sendRedirect(event, '/todos')
}
})

View File

@@ -0,0 +1,29 @@
import { z } from 'zod'
import { db, schema } from 'hub:db'
import { and, eq } from 'drizzle-orm'
const ParamsSchema = z.object({
id: z.coerce.number().int()
})
export default eventHandler(async (event) => {
const { id } = await getValidatedRouterParams(event, ParamsSchema.parse)
const { user } = await requireUserSession(event)
// Delete todo for the current user
const deletedTodos = await db.delete(schema.todos).where(
and(
eq(schema.todos.id, id),
eq(schema.todos.userId, user.id)
)
).returning()
const deletedTodo = deletedTodos[0]
if (!deletedTodo) {
throw createError({
statusCode: 404,
message: 'Todo not found'
})
}
return deletedTodo
})

View File

@@ -0,0 +1,34 @@
import { z } from 'zod'
import { db, schema } from 'hub:db'
import { and, eq } from 'drizzle-orm'
const ParamsSchema = z.object({
id: z.coerce.number().int()
})
const BodySchema = z.object({
completed: z.boolean()
})
export default eventHandler(async (event) => {
const { id } = await getValidatedRouterParams(event, ParamsSchema.parse)
const { completed } = await readValidatedBody(event, BodySchema.parse)
const { user } = await requireUserSession(event)
// Update todo for the current user
const updatedTodos = await db.update(schema.todos).set({
completed: completed ? 1 : 0
}).where(and(
eq(schema.todos.id, id),
eq(schema.todos.userId, user.id)
)).returning()
const todo = updatedTodos[0]
if (!todo) {
throw createError({
statusCode: 404,
message: 'Todo not found'
})
}
return todo
})

View File

@@ -0,0 +1,11 @@
import { db, schema } from 'hub:db'
import { eq } from 'drizzle-orm'
export default eventHandler(async (event) => {
const { user } = await requireUserSession(event)
// List todos for the current user
const todos = await db.select().from(schema.todos).where(eq(schema.todos.userId, user.id))
return todos
})

View File

@@ -0,0 +1,20 @@
import { z } from 'zod'
import { db, schema } from 'hub:db'
const BodySchema = z.object({
title: z.string().min(1).max(100)
})
export default eventHandler(async (event) => {
const { title } = await readValidatedBody(event, body => BodySchema.parse(body))
const { user } = await requireUserSession(event)
// Insert todo for the current user
const todos = await db.insert(schema.todos).values({
userId: user.id,
title,
createdAt: new Date()
}).returning()
return todos[0]
})

12
server/api/todos/stats.ts Normal file
View File

@@ -0,0 +1,12 @@
import { db, schema } from 'hub:db'
import { sql } from 'drizzle-orm'
export default eventHandler(async () => {
// Count the total number of todos
const result = await db.select({
todos: sql<number>`count(*)`,
users: sql<number>`count(distinct(${schema.todos.userId}))`
}).from(schema.todos)
return result[0]
})

View File

@@ -0,0 +1,7 @@
CREATE TABLE `todos` (
`id` integer PRIMARY KEY NOT NULL,
`user_id` integer NOT NULL,
`title` text NOT NULL,
`completed` integer DEFAULT 0 NOT NULL,
`created_at` integer NOT NULL
);

View File

@@ -0,0 +1,64 @@
{
"version": "6",
"dialect": "sqlite",
"id": "91b7734d-d696-4df6-9b68-d865ff714cbb",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"todos": {
"name": "todos",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"completed": {
"name": "completed",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1764775050537,
"tag": "0000_brainy_nehzno",
"breakpoints": true
}
]
}

9
server/db/schema.ts Normal file
View File

@@ -0,0 +1,9 @@
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
export const todos = sqliteTable('todos', {
id: integer('id').primaryKey(),
userId: integer('user_id').notNull(), // GitHub Id
title: text('title').notNull(),
completed: integer('completed').notNull().default(0),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull()
})

3
server/tsconfig.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}