code: user,nextjs,get (5 files)

This commit is contained in:
2025-12-26 00:04:03 +00:00
parent 115b679983
commit 9b8be90a73
5 changed files with 11 additions and 191 deletions
@@ -5,18 +5,24 @@ import type { User } from '../../types/level-types'
* Get user by email from DBAL.
* Single-responsibility lambda for email lookup.
*/
export const getUserByEmail = async (email: string): Promise<User | null> => {
export const getUserByEmail = async (
email: string,
options?: { tenantId?: string }
): Promise<User | null> => {
const adapter = getAdapter()
const result = await adapter.list('User', {
filter: { email },
const record = await adapter.findFirst('User', {
where: {
email,
...(options?.tenantId ? { tenantId: options.tenantId } : {}),
},
})
if (result.data.length === 0) {
if (!record) {
return null
}
const userData = result.data[0] as Record<string, unknown>
const userData = record as Record<string, unknown>
return {
id: String(userData.id),
@@ -1,63 +0,0 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
const mockFindFirst = vi.fn()
const mockAdapter = { findFirst: mockFindFirst }
vi.mock('../dbal-client', () => ({
getAdapter: () => mockAdapter,
}))
import { getUserByEmail } from './get-user-by-email'
describe('getUserByEmail', () => {
beforeEach(() => {
mockFindFirst.mockReset()
})
it('returns null when user not found', async () => {
mockFindFirst.mockResolvedValue(null)
const result = await getUserByEmail('missing@example.com')
expect(mockFindFirst).toHaveBeenCalledWith('User', { where: { email: 'missing@example.com' } })
expect(result).toBeNull()
})
it('returns user when found', async () => {
mockFindFirst.mockResolvedValue({
id: 'user_2',
username: 'bob',
email: 'bob@example.com',
role: 'user',
profilePicture: 'pic.png',
bio: null,
createdAt: BigInt(2000),
tenantId: 'tenant_2',
isInstanceOwner: true,
})
const result = await getUserByEmail('bob@example.com')
expect(result).toEqual({
id: 'user_2',
username: 'bob',
email: 'bob@example.com',
role: 'user',
profilePicture: 'pic.png',
bio: undefined,
createdAt: 2000,
tenantId: 'tenant_2',
isInstanceOwner: true,
})
})
it('includes tenant filter when provided', async () => {
mockFindFirst.mockResolvedValue(null)
await getUserByEmail('bob@example.com', { tenantId: 'tenant_2' })
expect(mockFindFirst).toHaveBeenCalledWith('User', {
where: { email: 'bob@example.com', tenantId: 'tenant_2' },
})
})
})
@@ -1,30 +0,0 @@
import { getAdapter } from '../dbal-client'
import type { User } from '../../types/level-types'
export async function getUserByEmail(
email: string,
options?: { tenantId?: string }
): Promise<User | null> {
const adapter = getAdapter()
const record = await adapter.findFirst('User', {
where: {
email,
...(options?.tenantId ? { tenantId: options.tenantId } : {}),
},
})
if (!record) return null
const user = record as any
return {
id: user.id,
username: user.username,
email: user.email,
role: user.role as any,
profilePicture: user.profilePicture || undefined,
bio: user.bio || undefined,
createdAt: Number(user.createdAt),
tenantId: user.tenantId || undefined,
isInstanceOwner: user.isInstanceOwner,
}
}
@@ -1,63 +0,0 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
const mockFindFirst = vi.fn()
const mockAdapter = { findFirst: mockFindFirst }
vi.mock('../dbal-client', () => ({
getAdapter: () => mockAdapter,
}))
import { getUserByUsername } from './get-user-by-username'
describe('getUserByUsername', () => {
beforeEach(() => {
mockFindFirst.mockReset()
})
it('returns null when user not found', async () => {
mockFindFirst.mockResolvedValue(null)
const result = await getUserByUsername('missing')
expect(mockFindFirst).toHaveBeenCalledWith('User', { where: { username: 'missing' } })
expect(result).toBeNull()
})
it('returns user when found', async () => {
mockFindFirst.mockResolvedValue({
id: 'user_1',
username: 'alice',
email: 'alice@example.com',
role: 'admin',
profilePicture: null,
bio: 'Bio',
createdAt: BigInt(1000),
tenantId: null,
isInstanceOwner: false,
})
const result = await getUserByUsername('alice')
expect(result).toEqual({
id: 'user_1',
username: 'alice',
email: 'alice@example.com',
role: 'admin',
profilePicture: undefined,
bio: 'Bio',
createdAt: 1000,
tenantId: undefined,
isInstanceOwner: false,
})
})
it('includes tenant filter when provided', async () => {
mockFindFirst.mockResolvedValue(null)
await getUserByUsername('alice', { tenantId: 'tenant_1' })
expect(mockFindFirst).toHaveBeenCalledWith('User', {
where: { username: 'alice', tenantId: 'tenant_1' },
})
})
})
@@ -1,30 +0,0 @@
import { getAdapter } from '../dbal-client'
import type { User } from '../../types/level-types'
export async function getUserByUsername(
username: string,
options?: { tenantId?: string }
): Promise<User | null> {
const adapter = getAdapter()
const record = await adapter.findFirst('User', {
where: {
username,
...(options?.tenantId ? { tenantId: options.tenantId } : {}),
},
})
if (!record) return null
const user = record as any
return {
id: user.id,
username: user.username,
email: user.email,
role: user.role as any,
profilePicture: user.profilePicture || undefined,
bio: user.bio || undefined,
createdAt: Number(user.createdAt),
tenantId: user.tenantId || undefined,
isInstanceOwner: user.isInstanceOwner,
}
}