chore: base project skeleton and db schema
This commit is contained in:
31
internal/database/db.go
Normal file
31
internal/database/db.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
47
internal/database/models.go
Normal file
47
internal/database/models.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
Provider string `json:"provider"`
|
||||
ProviderAccountID string `json:"provider_account_id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type Anime struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
ImageUrl string `json:"image_url"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type WatchListEntry struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
AnimeID int64 `json:"anime_id"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
26
internal/database/querier.go
Normal file
26
internal/database/querier.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error)
|
||||
CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
|
||||
DeleteSession(ctx context.Context, id string) error
|
||||
DeleteUserSessions(ctx context.Context, userID string) error
|
||||
DeleteWatchListEntry(ctx context.Context, arg DeleteWatchListEntryParams) error
|
||||
GetSession(ctx context.Context, id string) (Session, error)
|
||||
GetUser(ctx context.Context, id string) (User, error)
|
||||
GetUserByUsername(ctx context.Context, username string) (User, error)
|
||||
GetUserWatchList(ctx context.Context, userID string) ([]GetUserWatchListRow, error)
|
||||
GetWatchListEntry(ctx context.Context, arg GetWatchListEntryParams) (WatchListEntry, error)
|
||||
UpsertAnime(ctx context.Context, arg UpsertAnimeParams) (Anime, error)
|
||||
UpsertWatchListEntry(ctx context.Context, arg UpsertWatchListEntryParams) (WatchListEntry, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
||||
55
internal/database/queries.sql
Normal file
55
internal/database/queries.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
-- name: GetUser :one
|
||||
SELECT * FROM user WHERE id = ? LIMIT 1;
|
||||
|
||||
-- name: GetUserByUsername :one
|
||||
SELECT * FROM user WHERE username = ? LIMIT 1;
|
||||
|
||||
-- name: CreateUser :one
|
||||
INSERT INTO user (id, username, password_hash)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateSession :one
|
||||
INSERT INTO session (id, user_id, expires_at)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetSession :one
|
||||
SELECT * FROM session WHERE id = ? LIMIT 1;
|
||||
|
||||
-- name: DeleteSession :exec
|
||||
DELETE FROM session WHERE id = ?;
|
||||
|
||||
-- name: DeleteUserSessions :exec
|
||||
DELETE FROM session WHERE user_id = ?;
|
||||
|
||||
-- name: UpsertAnime :one
|
||||
INSERT INTO anime (id, title, image_url)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
title = excluded.title,
|
||||
image_url = excluded.image_url
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpsertWatchListEntry :one
|
||||
INSERT INTO watch_list_entry (id, user_id, anime_id, status, updated_at)
|
||||
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (user_id, anime_id) DO UPDATE SET
|
||||
status = excluded.status,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetWatchListEntry :one
|
||||
SELECT * FROM watch_list_entry
|
||||
WHERE user_id = ? AND anime_id = ? LIMIT 1;
|
||||
|
||||
-- name: GetUserWatchList :many
|
||||
SELECT e.*, a.title, a.image_url
|
||||
FROM watch_list_entry e
|
||||
JOIN anime a ON e.anime_id = a.id
|
||||
WHERE e.user_id = ?
|
||||
ORDER BY e.updated_at DESC;
|
||||
|
||||
-- name: DeleteWatchListEntry :exec
|
||||
DELETE FROM watch_list_entry
|
||||
WHERE user_id = ? AND anime_id = ?;
|
||||
277
internal/database/queries.sql.go
Normal file
277
internal/database/queries.sql.go
Normal file
@@ -0,0 +1,277 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: queries.sql
|
||||
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const createSession = `-- name: CreateSession :one
|
||||
INSERT INTO session (id, user_id, expires_at)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING id, user_id, expires_at, created_at
|
||||
`
|
||||
|
||||
type CreateSessionParams struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error) {
|
||||
row := q.db.QueryRowContext(ctx, createSession, arg.ID, arg.UserID, arg.ExpiresAt)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createUser = `-- name: CreateUser :one
|
||||
INSERT INTO user (id, username, password_hash)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING id, username, password_hash, created_at
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, createUser, arg.ID, arg.Username, arg.PasswordHash)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteSession = `-- name: DeleteSession :exec
|
||||
DELETE FROM session WHERE id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSession(ctx context.Context, id string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteSession, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteUserSessions = `-- name: DeleteUserSessions :exec
|
||||
DELETE FROM session WHERE user_id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteUserSessions(ctx context.Context, userID string) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteUserSessions, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteWatchListEntry = `-- name: DeleteWatchListEntry :exec
|
||||
DELETE FROM watch_list_entry
|
||||
WHERE user_id = ? AND anime_id = ?
|
||||
`
|
||||
|
||||
type DeleteWatchListEntryParams struct {
|
||||
UserID string `json:"user_id"`
|
||||
AnimeID int64 `json:"anime_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteWatchListEntry(ctx context.Context, arg DeleteWatchListEntryParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteWatchListEntry, arg.UserID, arg.AnimeID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getSession = `-- name: GetSession :one
|
||||
SELECT id, user_id, expires_at, created_at FROM session WHERE id = ? LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSession(ctx context.Context, id string) (Session, error) {
|
||||
row := q.db.QueryRowContext(ctx, getSession, id)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUser = `-- name: GetUser :one
|
||||
SELECT id, username, password_hash, created_at FROM user WHERE id = ? LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUser(ctx context.Context, id string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUser, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserByUsername = `-- name: GetUserByUsername :one
|
||||
SELECT id, username, password_hash, created_at FROM user WHERE username = ? LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserByUsername, username)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.PasswordHash,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserWatchList = `-- name: GetUserWatchList :many
|
||||
SELECT e.id, e.user_id, e.anime_id, e.status, e.created_at, e.updated_at, a.title, a.image_url
|
||||
FROM watch_list_entry e
|
||||
JOIN anime a ON e.anime_id = a.id
|
||||
WHERE e.user_id = ?
|
||||
ORDER BY e.updated_at DESC
|
||||
`
|
||||
|
||||
type GetUserWatchListRow struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
AnimeID int64 `json:"anime_id"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Title string `json:"title"`
|
||||
ImageUrl string `json:"image_url"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetUserWatchList(ctx context.Context, userID string) ([]GetUserWatchListRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getUserWatchList, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetUserWatchListRow
|
||||
for rows.Next() {
|
||||
var i GetUserWatchListRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.AnimeID,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Title,
|
||||
&i.ImageUrl,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWatchListEntry = `-- name: GetWatchListEntry :one
|
||||
SELECT id, user_id, anime_id, status, created_at, updated_at FROM watch_list_entry
|
||||
WHERE user_id = ? AND anime_id = ? LIMIT 1
|
||||
`
|
||||
|
||||
type GetWatchListEntryParams struct {
|
||||
UserID string `json:"user_id"`
|
||||
AnimeID int64 `json:"anime_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetWatchListEntry(ctx context.Context, arg GetWatchListEntryParams) (WatchListEntry, error) {
|
||||
row := q.db.QueryRowContext(ctx, getWatchListEntry, arg.UserID, arg.AnimeID)
|
||||
var i WatchListEntry
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.AnimeID,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertAnime = `-- name: UpsertAnime :one
|
||||
INSERT INTO anime (id, title, image_url)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
title = excluded.title,
|
||||
image_url = excluded.image_url
|
||||
RETURNING id, title, image_url, created_at
|
||||
`
|
||||
|
||||
type UpsertAnimeParams struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
ImageUrl string `json:"image_url"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertAnime(ctx context.Context, arg UpsertAnimeParams) (Anime, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertAnime, arg.ID, arg.Title, arg.ImageUrl)
|
||||
var i Anime
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.ImageUrl,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertWatchListEntry = `-- name: UpsertWatchListEntry :one
|
||||
INSERT INTO watch_list_entry (id, user_id, anime_id, status, updated_at)
|
||||
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (user_id, anime_id) DO UPDATE SET
|
||||
status = excluded.status,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
RETURNING id, user_id, anime_id, status, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpsertWatchListEntryParams struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
AnimeID int64 `json:"anime_id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertWatchListEntry(ctx context.Context, arg UpsertWatchListEntryParams) (WatchListEntry, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertWatchListEntry,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
arg.AnimeID,
|
||||
arg.Status,
|
||||
)
|
||||
var i WatchListEntry
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.AnimeID,
|
||||
&i.Status,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
Reference in New Issue
Block a user