From 29fb3054a5aa9bd7c13a13b38821486ac3bbdd20 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Sun, 21 Sep 2025 13:51:13 +0200 Subject: [PATCH] chore: add sqlc queries and stubs --- go.mod | 6 + go.sum | 30 +++++ internal/driver/db/db.go | 32 +++++ internal/driver/db/login_events.sql.go | 89 +++++++++++++ internal/driver/db/models.go | 51 ++++++++ internal/driver/db/queries/login_events.sql | 11 ++ .../driver/db/queries/user_oauth_accounts.sql | 15 +++ internal/driver/db/queries/user_passwords.sql | 16 +++ internal/driver/db/queries/users.sql | 14 +++ internal/driver/db/sqlc.yaml | 2 +- internal/driver/db/user_oauth_accounts.sql.go | 117 ++++++++++++++++++ internal/driver/db/user_passwords.sql.go | 80 ++++++++++++ internal/driver/db/users.sql.go | 93 ++++++++++++++ 13 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 internal/driver/db/db.go create mode 100644 internal/driver/db/login_events.sql.go create mode 100644 internal/driver/db/models.go create mode 100644 internal/driver/db/queries/login_events.sql create mode 100644 internal/driver/db/queries/user_oauth_accounts.sql create mode 100644 internal/driver/db/queries/user_passwords.sql create mode 100644 internal/driver/db/queries/users.sql create mode 100644 internal/driver/db/user_oauth_accounts.sql.go create mode 100644 internal/driver/db/user_passwords.sql.go create mode 100644 internal/driver/db/users.sql.go diff --git a/go.mod b/go.mod index 68949d3..1cbbd39 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,16 @@ go 1.25.1 require ( github.com/go-chi/chi/v5 v5.2.3 + github.com/google/uuid v1.6.0 + github.com/jackc/pgx/v5 v5.7.6 golang.org/x/oauth2 v0.31.0 ) require ( cloud.google.com/go/compute/metadata v0.8.4 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + golang.org/x/crypto v0.37.0 // indirect golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.24.0 // indirect ) diff --git a/go.sum b/go.sum index e3d5226..cb8888d 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,40 @@ cloud.google.com/go/compute/metadata v0.8.4 h1:oXMa1VMQBVCyewMIOm3WQsnVd9FbKBtm8reqWRaXnHQ= cloud.google.com/go/compute/metadata v0.8.4/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= +github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/driver/db/db.go b/internal/driver/db/db.go new file mode 100644 index 0000000..9d485b5 --- /dev/null +++ b/internal/driver/db/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package db + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/driver/db/login_events.sql.go b/internal/driver/db/login_events.sql.go new file mode 100644 index 0000000..8e12c89 --- /dev/null +++ b/internal/driver/db/login_events.sql.go @@ -0,0 +1,89 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: login_events.sql + +package db + +import ( + "context" + "net/netip" + + "github.com/jackc/pgx/v5/pgtype" +) + +const createLoginEvent = `-- name: CreateLoginEvent :one +INSERT INTO login_events (user_id, provider, success, ip, user_agent) +VALUES ($1, $2, $3, $4, $5) +RETURNING id, user_id, provider, success, ip, user_agent, created_at +` + +type CreateLoginEventParams struct { + UserID pgtype.UUID `json:"user_id"` + Provider pgtype.Text `json:"provider"` + Success bool `json:"success"` + Ip *netip.Addr `json:"ip"` + UserAgent pgtype.Text `json:"user_agent"` +} + +func (q *Queries) CreateLoginEvent(ctx context.Context, arg CreateLoginEventParams) (LoginEvent, error) { + row := q.db.QueryRow(ctx, createLoginEvent, + arg.UserID, + arg.Provider, + arg.Success, + arg.Ip, + arg.UserAgent, + ) + var i LoginEvent + err := row.Scan( + &i.ID, + &i.UserID, + &i.Provider, + &i.Success, + &i.Ip, + &i.UserAgent, + &i.CreatedAt, + ) + return i, err +} + +const listLoginEventsForUser = `-- name: ListLoginEventsForUser :many +SELECT id, user_id, provider, success, ip, user_agent, created_at +FROM login_events +WHERE user_id = $1 +ORDER BY created_at DESC +LIMIT $2 +` + +type ListLoginEventsForUserParams struct { + UserID pgtype.UUID `json:"user_id"` + Limit int32 `json:"limit"` +} + +func (q *Queries) ListLoginEventsForUser(ctx context.Context, arg ListLoginEventsForUserParams) ([]LoginEvent, error) { + rows, err := q.db.Query(ctx, listLoginEventsForUser, arg.UserID, arg.Limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []LoginEvent + for rows.Next() { + var i LoginEvent + if err := rows.Scan( + &i.ID, + &i.UserID, + &i.Provider, + &i.Success, + &i.Ip, + &i.UserAgent, + &i.CreatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/driver/db/models.go b/internal/driver/db/models.go new file mode 100644 index 0000000..25392f7 --- /dev/null +++ b/internal/driver/db/models.go @@ -0,0 +1,51 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package db + +import ( + "net/netip" + + "github.com/google/uuid" + "github.com/jackc/pgx/v5/pgtype" +) + +type LoginEvent struct { + ID uuid.UUID `json:"id"` + UserID pgtype.UUID `json:"user_id"` + Provider pgtype.Text `json:"provider"` + Success bool `json:"success"` + Ip *netip.Addr `json:"ip"` + UserAgent pgtype.Text `json:"user_agent"` + CreatedAt pgtype.Timestamptz `json:"created_at"` +} + +type User struct { + ID uuid.UUID `json:"id"` + Email string `json:"email"` + DisplayName pgtype.Text `json:"display_name"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} + +type UserOauthAccount struct { + ID uuid.UUID `json:"id"` + UserID uuid.UUID `json:"user_id"` + Provider string `json:"provider"` + Subject string `json:"subject"` + Email pgtype.Text `json:"email"` + EmailVerified bool `json:"email_verified"` + Profile []byte `json:"profile"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} + +type UserPassword struct { + UserID uuid.UUID `json:"user_id"` + PasswordHash []byte `json:"password_hash"` + PasswordSalt []byte `json:"password_salt"` + Algorithm string `json:"algorithm"` + CreatedAt pgtype.Timestamptz `json:"created_at"` + UpdatedAt pgtype.Timestamptz `json:"updated_at"` +} diff --git a/internal/driver/db/queries/login_events.sql b/internal/driver/db/queries/login_events.sql new file mode 100644 index 0000000..6705a6b --- /dev/null +++ b/internal/driver/db/queries/login_events.sql @@ -0,0 +1,11 @@ +-- name: CreateLoginEvent :one +INSERT INTO login_events (user_id, provider, success, ip, user_agent) +VALUES ($1, $2, $3, $4, $5) +RETURNING id, user_id, provider, success, ip, user_agent, created_at; + +-- name: ListLoginEventsForUser :many +SELECT id, user_id, provider, success, ip, user_agent, created_at +FROM login_events +WHERE user_id = $1 +ORDER BY created_at DESC +LIMIT $2; diff --git a/internal/driver/db/queries/user_oauth_accounts.sql b/internal/driver/db/queries/user_oauth_accounts.sql new file mode 100644 index 0000000..bb83149 --- /dev/null +++ b/internal/driver/db/queries/user_oauth_accounts.sql @@ -0,0 +1,15 @@ +-- name: CreateUserOAuthAccount :one +INSERT INTO user_oauth_accounts (user_id, provider, subject, email, email_verified, profile) +VALUES ($1, $2, $3, $4, $5, $6) +RETURNING id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at; + +-- name: GetUserOAuthAccountByProviderSubject :one +SELECT id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at +FROM user_oauth_accounts +WHERE provider = $1 AND subject = $2; + +-- name: ListUserOAuthAccountsByUserID :many +SELECT id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at +FROM user_oauth_accounts +WHERE user_id = $1 +ORDER BY created_at DESC; diff --git a/internal/driver/db/queries/user_passwords.sql b/internal/driver/db/queries/user_passwords.sql new file mode 100644 index 0000000..402cdb6 --- /dev/null +++ b/internal/driver/db/queries/user_passwords.sql @@ -0,0 +1,16 @@ +-- name: CreateUserPassword :exec +INSERT INTO user_passwords (user_id, password_hash, password_salt, algorithm) +VALUES ($1, $2, $3, $4); + +-- name: UpdateUserPassword :exec +UPDATE user_passwords +SET password_hash = $1, + password_salt = $2, + algorithm = $3, + updated_at = now() +WHERE user_id = $4; + +-- name: GetUserPassword :one +SELECT user_id, password_hash, password_salt, algorithm, created_at, updated_at +FROM user_passwords +WHERE user_id = $1; diff --git a/internal/driver/db/queries/users.sql b/internal/driver/db/queries/users.sql new file mode 100644 index 0000000..8214f5c --- /dev/null +++ b/internal/driver/db/queries/users.sql @@ -0,0 +1,14 @@ +-- name: CreateUser :one +INSERT INTO users (email, display_name) +VALUES ($1, $2) +RETURNING id, email, display_name, created_at; + +-- name: GetUserByID :one +SELECT id, email, display_name, created_at +FROM users +WHERE id = $1; + +-- name: GetUserByEmail :one +SELECT id, email, display_name, created_at +FROM users +WHERE email = $1; diff --git a/internal/driver/db/sqlc.yaml b/internal/driver/db/sqlc.yaml index 41f7619..ef5676e 100644 --- a/internal/driver/db/sqlc.yaml +++ b/internal/driver/db/sqlc.yaml @@ -7,7 +7,7 @@ sql: gen: go: package: db - out: internal/driver/db/sqlc + out: . emit_json_tags: true sql_package: pgx/v5 emit_interface: false diff --git a/internal/driver/db/user_oauth_accounts.sql.go b/internal/driver/db/user_oauth_accounts.sql.go new file mode 100644 index 0000000..3332f43 --- /dev/null +++ b/internal/driver/db/user_oauth_accounts.sql.go @@ -0,0 +1,117 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: user_oauth_accounts.sql + +package db + +import ( + "context" + + "github.com/google/uuid" + "github.com/jackc/pgx/v5/pgtype" +) + +const createUserOAuthAccount = `-- name: CreateUserOAuthAccount :one +INSERT INTO user_oauth_accounts (user_id, provider, subject, email, email_verified, profile) +VALUES ($1, $2, $3, $4, $5, $6) +RETURNING id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at +` + +type CreateUserOAuthAccountParams struct { + UserID uuid.UUID `json:"user_id"` + Provider string `json:"provider"` + Subject string `json:"subject"` + Email pgtype.Text `json:"email"` + EmailVerified bool `json:"email_verified"` + Profile []byte `json:"profile"` +} + +func (q *Queries) CreateUserOAuthAccount(ctx context.Context, arg CreateUserOAuthAccountParams) (UserOauthAccount, error) { + row := q.db.QueryRow(ctx, createUserOAuthAccount, + arg.UserID, + arg.Provider, + arg.Subject, + arg.Email, + arg.EmailVerified, + arg.Profile, + ) + var i UserOauthAccount + err := row.Scan( + &i.ID, + &i.UserID, + &i.Provider, + &i.Subject, + &i.Email, + &i.EmailVerified, + &i.Profile, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const getUserOAuthAccountByProviderSubject = `-- name: GetUserOAuthAccountByProviderSubject :one +SELECT id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at +FROM user_oauth_accounts +WHERE provider = $1 AND subject = $2 +` + +type GetUserOAuthAccountByProviderSubjectParams struct { + Provider string `json:"provider"` + Subject string `json:"subject"` +} + +func (q *Queries) GetUserOAuthAccountByProviderSubject(ctx context.Context, arg GetUserOAuthAccountByProviderSubjectParams) (UserOauthAccount, error) { + row := q.db.QueryRow(ctx, getUserOAuthAccountByProviderSubject, arg.Provider, arg.Subject) + var i UserOauthAccount + err := row.Scan( + &i.ID, + &i.UserID, + &i.Provider, + &i.Subject, + &i.Email, + &i.EmailVerified, + &i.Profile, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const listUserOAuthAccountsByUserID = `-- name: ListUserOAuthAccountsByUserID :many +SELECT id, user_id, provider, subject, email, email_verified, profile, created_at, updated_at +FROM user_oauth_accounts +WHERE user_id = $1 +ORDER BY created_at DESC +` + +func (q *Queries) ListUserOAuthAccountsByUserID(ctx context.Context, userID uuid.UUID) ([]UserOauthAccount, error) { + rows, err := q.db.Query(ctx, listUserOAuthAccountsByUserID, userID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []UserOauthAccount + for rows.Next() { + var i UserOauthAccount + if err := rows.Scan( + &i.ID, + &i.UserID, + &i.Provider, + &i.Subject, + &i.Email, + &i.EmailVerified, + &i.Profile, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/driver/db/user_passwords.sql.go b/internal/driver/db/user_passwords.sql.go new file mode 100644 index 0000000..0ac2661 --- /dev/null +++ b/internal/driver/db/user_passwords.sql.go @@ -0,0 +1,80 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: user_passwords.sql + +package db + +import ( + "context" + + "github.com/google/uuid" +) + +const createUserPassword = `-- name: CreateUserPassword :exec +INSERT INTO user_passwords (user_id, password_hash, password_salt, algorithm) +VALUES ($1, $2, $3, $4) +` + +type CreateUserPasswordParams struct { + UserID uuid.UUID `json:"user_id"` + PasswordHash []byte `json:"password_hash"` + PasswordSalt []byte `json:"password_salt"` + Algorithm string `json:"algorithm"` +} + +func (q *Queries) CreateUserPassword(ctx context.Context, arg CreateUserPasswordParams) error { + _, err := q.db.Exec(ctx, createUserPassword, + arg.UserID, + arg.PasswordHash, + arg.PasswordSalt, + arg.Algorithm, + ) + return err +} + +const getUserPassword = `-- name: GetUserPassword :one +SELECT user_id, password_hash, password_salt, algorithm, created_at, updated_at +FROM user_passwords +WHERE user_id = $1 +` + +func (q *Queries) GetUserPassword(ctx context.Context, userID uuid.UUID) (UserPassword, error) { + row := q.db.QueryRow(ctx, getUserPassword, userID) + var i UserPassword + err := row.Scan( + &i.UserID, + &i.PasswordHash, + &i.PasswordSalt, + &i.Algorithm, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const updateUserPassword = `-- name: UpdateUserPassword :exec +UPDATE user_passwords +SET password_hash = $1, + password_salt = $2, + algorithm = $3, + updated_at = now() +WHERE user_id = $4 +` + +type UpdateUserPasswordParams struct { + PasswordHash []byte `json:"password_hash"` + PasswordSalt []byte `json:"password_salt"` + Algorithm string `json:"algorithm"` + UserID uuid.UUID `json:"user_id"` +} + +func (q *Queries) UpdateUserPassword(ctx context.Context, arg UpdateUserPasswordParams) error { + _, err := q.db.Exec(ctx, updateUserPassword, + arg.PasswordHash, + arg.PasswordSalt, + arg.Algorithm, + arg.UserID, + ) + return err +} diff --git a/internal/driver/db/users.sql.go b/internal/driver/db/users.sql.go new file mode 100644 index 0000000..e4804e3 --- /dev/null +++ b/internal/driver/db/users.sql.go @@ -0,0 +1,93 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: users.sql + +package db + +import ( + "context" + + "github.com/google/uuid" + "github.com/jackc/pgx/v5/pgtype" +) + +const createUser = `-- name: CreateUser :one +INSERT INTO users (email, display_name) +VALUES ($1, $2) +RETURNING id, email, display_name, created_at +` + +type CreateUserParams struct { + Email string `json:"email"` + DisplayName pgtype.Text `json:"display_name"` +} + +type CreateUserRow struct { + ID uuid.UUID `json:"id"` + Email string `json:"email"` + DisplayName pgtype.Text `json:"display_name"` + CreatedAt pgtype.Timestamptz `json:"created_at"` +} + +func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (CreateUserRow, error) { + row := q.db.QueryRow(ctx, createUser, arg.Email, arg.DisplayName) + var i CreateUserRow + err := row.Scan( + &i.ID, + &i.Email, + &i.DisplayName, + &i.CreatedAt, + ) + return i, err +} + +const getUserByEmail = `-- name: GetUserByEmail :one +SELECT id, email, display_name, created_at +FROM users +WHERE email = $1 +` + +type GetUserByEmailRow struct { + ID uuid.UUID `json:"id"` + Email string `json:"email"` + DisplayName pgtype.Text `json:"display_name"` + CreatedAt pgtype.Timestamptz `json:"created_at"` +} + +func (q *Queries) GetUserByEmail(ctx context.Context, email string) (GetUserByEmailRow, error) { + row := q.db.QueryRow(ctx, getUserByEmail, email) + var i GetUserByEmailRow + err := row.Scan( + &i.ID, + &i.Email, + &i.DisplayName, + &i.CreatedAt, + ) + return i, err +} + +const getUserByID = `-- name: GetUserByID :one +SELECT id, email, display_name, created_at +FROM users +WHERE id = $1 +` + +type GetUserByIDRow struct { + ID uuid.UUID `json:"id"` + Email string `json:"email"` + DisplayName pgtype.Text `json:"display_name"` + CreatedAt pgtype.Timestamptz `json:"created_at"` +} + +func (q *Queries) GetUserByID(ctx context.Context, id uuid.UUID) (GetUserByIDRow, error) { + row := q.db.QueryRow(ctx, getUserByID, id) + var i GetUserByIDRow + err := row.Scan( + &i.ID, + &i.Email, + &i.DisplayName, + &i.CreatedAt, + ) + return i, err +}