mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
Compare commits
14 Commits
claude/fix
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5b6e7c912 | ||
|
|
38e129c50e | ||
|
|
1f5cfe9e77 | ||
|
|
78b8bec29e | ||
|
|
d726f8bb9a | ||
|
|
0943ab50c1 | ||
|
|
99bb647503 | ||
|
|
09310703d2 | ||
|
|
549d0e6298 | ||
|
|
3337584607 | ||
|
|
99a3d500b3 | ||
|
|
574f0a0044 | ||
|
|
6fcba8a44f | ||
|
|
2a7a81412d |
7
fakemui/icons/types.ts
Normal file
7
fakemui/icons/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export interface IconProps extends SVGProps<SVGSVGElement> {
|
||||
size?: number
|
||||
color?: string
|
||||
weight?: 'thin' | 'light' | 'regular' | 'bold' | 'fill' | 'duotone'
|
||||
}
|
||||
8864
frontends/nextjs/package-lock.json
generated
8864
frontends/nextjs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -35,15 +35,19 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@tanstack/react-query": "^5.90.16",
|
||||
"@testing-library/react": "^16.3.1",
|
||||
"@types/node": "^25.0.3",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react-swc": "^4.2.2",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"prettier": "^3.4.2",
|
||||
"prisma": "^7.2.0",
|
||||
"sass": "^1.97.1",
|
||||
"sonner": "^2.0.7",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.50.1",
|
||||
"vitest": "^4.0.16"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// TODO: Implement auth provider component
|
||||
import type { ReactNode } from 'react'
|
||||
export const AuthProvider = ({ children }: { children: ReactNode }) => children
|
||||
export const AuthProviderComponent = ({ children }: { children: ReactNode }) => children
|
||||
@@ -0,0 +1,2 @@
|
||||
// TODO: Implement use-auth hook
|
||||
export { useAuth } from '@/hooks/useAuth'
|
||||
@@ -1,10 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { NextRequest } from 'next/server'
|
||||
|
||||
import { GET } from './route'
|
||||
|
||||
describe('GET /api/health', () => {
|
||||
it('returns OK status and permission level count', async () => {
|
||||
const response = await GET(new Request('http://example.com/api/health'))
|
||||
const response = await GET(new NextRequest('http://example.com/api/health'))
|
||||
const payload = await response.json()
|
||||
|
||||
expect(payload.status).toBe('ok')
|
||||
|
||||
10
frontends/nextjs/src/app/levels/levels-data.ts
Normal file
10
frontends/nextjs/src/app/levels/levels-data.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// TODO: Implement levels data
|
||||
export const PERMISSION_LEVELS = [
|
||||
{ level: 1, name: 'PUBLIC' },
|
||||
{ level: 2, name: 'USER' },
|
||||
{ level: 3, name: 'MODERATOR' },
|
||||
{ level: 4, name: 'ADMIN' },
|
||||
{ level: 5, name: 'GOD' },
|
||||
{ level: 6, name: 'SUPERGOD' }
|
||||
]
|
||||
export const levelsData = { PERMISSION_LEVELS }
|
||||
@@ -28,7 +28,7 @@ const knownIcons = [
|
||||
|
||||
describe('getComponentIcon', () => {
|
||||
it.each(knownIcons)('returns an icon for %s', iconName => {
|
||||
expect(getComponentIcon(iconName, { sx: { fontSize: 20 } })).not.toBeNull()
|
||||
expect(getComponentIcon(iconName, { fontSize: 20 })).not.toBeNull()
|
||||
})
|
||||
|
||||
it('returns null for unknown icons', () => {
|
||||
|
||||
6
frontends/nextjs/src/hooks/data/useLevelRouting.ts
Normal file
6
frontends/nextjs/src/hooks/data/useLevelRouting.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// TODO: Implement useLevelRouting
|
||||
export function useLevelRouting() {
|
||||
return { canAccess: () => true }
|
||||
}
|
||||
|
||||
export type LevelRouting = ReturnType<typeof useLevelRouting>
|
||||
6
frontends/nextjs/src/hooks/data/useResolvedUser.ts
Normal file
6
frontends/nextjs/src/hooks/data/useResolvedUser.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// TODO: Implement useResolvedUser
|
||||
export function useResolvedUser() {
|
||||
return { user: null, isLoading: false }
|
||||
}
|
||||
|
||||
export type ResolvedUserState = ReturnType<typeof useResolvedUser>
|
||||
20
frontends/nextjs/src/hooks/use-mobile.ts
Normal file
20
frontends/nextjs/src/hooks/use-mobile.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Hook for detecting mobile viewport
|
||||
*/
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
export function useIsMobile(): boolean {
|
||||
const [isMobile, setIsMobile] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth < 768)
|
||||
}
|
||||
|
||||
checkMobile()
|
||||
window.addEventListener('resize', checkMobile)
|
||||
return () => window.removeEventListener('resize', checkMobile)
|
||||
}, [])
|
||||
|
||||
return isMobile
|
||||
}
|
||||
13
frontends/nextjs/src/hooks/useAutoRefresh.ts
Normal file
13
frontends/nextjs/src/hooks/useAutoRefresh.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Hook for auto-refreshing data at intervals
|
||||
*/
|
||||
import { useEffect, useCallback } from 'react'
|
||||
|
||||
export function useAutoRefresh(callback: () => void, interval: number = 5000): void {
|
||||
const stableCallback = useCallback(callback, [callback])
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(stableCallback, interval)
|
||||
return () => clearInterval(id)
|
||||
}, [stableCallback, interval])
|
||||
}
|
||||
55
frontends/nextjs/src/hooks/useCodeEditor.ts
Normal file
55
frontends/nextjs/src/hooks/useCodeEditor.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Hook for managing code editor state
|
||||
*/
|
||||
import { useState } from 'react'
|
||||
|
||||
export interface EditorFile {
|
||||
path: string
|
||||
content: string
|
||||
language?: string
|
||||
}
|
||||
|
||||
export interface UseCodeEditorReturn {
|
||||
files: EditorFile[]
|
||||
currentFile: EditorFile | null
|
||||
setCurrentFile: (file: EditorFile | null) => void
|
||||
updateFile: (path: string, content: string) => void
|
||||
addFile: (file: EditorFile) => void
|
||||
removeFile: (path: string) => void
|
||||
}
|
||||
|
||||
export function useCodeEditor(initialFiles: EditorFile[] = []): UseCodeEditorReturn {
|
||||
const [files, setFiles] = useState<EditorFile[]>(initialFiles)
|
||||
const [currentFile, setCurrentFile] = useState<EditorFile | null>(
|
||||
initialFiles.length > 0 ? initialFiles[0] : null
|
||||
)
|
||||
|
||||
const updateFile = (path: string, content: string) => {
|
||||
setFiles(prev =>
|
||||
prev.map(f => (f.path === path ? { ...f, content } : f))
|
||||
)
|
||||
if (currentFile?.path === path) {
|
||||
setCurrentFile({ ...currentFile, content })
|
||||
}
|
||||
}
|
||||
|
||||
const addFile = (file: EditorFile) => {
|
||||
setFiles(prev => [...prev, file])
|
||||
}
|
||||
|
||||
const removeFile = (path: string) => {
|
||||
setFiles(prev => prev.filter(f => f.path !== path))
|
||||
if (currentFile?.path === path) {
|
||||
setCurrentFile(null)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
files,
|
||||
currentFile,
|
||||
setCurrentFile,
|
||||
updateFile,
|
||||
addFile,
|
||||
removeFile,
|
||||
}
|
||||
}
|
||||
114
frontends/nextjs/src/hooks/useDBAL.ts
Normal file
114
frontends/nextjs/src/hooks/useDBAL.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Hook for DBAL operations
|
||||
*/
|
||||
import { useState, useCallback } from 'react'
|
||||
|
||||
export interface UseDBALReturn {
|
||||
get: (entity: string, id: string) => Promise<unknown>
|
||||
list: (entity: string, filter?: Record<string, unknown>) => Promise<unknown[]>
|
||||
create: (entity: string, data: Record<string, unknown>) => Promise<unknown>
|
||||
update: (entity: string, id: string, data: Record<string, unknown>) => Promise<unknown>
|
||||
delete: (entity: string, id: string) => Promise<void>
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
}
|
||||
|
||||
export function useDBAL(): UseDBALReturn {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
const get = useCallback(async (entity: string, id: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/v1/${entity}/${id}`)
|
||||
if (!response.ok) throw new Error('Failed to fetch')
|
||||
return await response.json()
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const list = useCallback(async (entity: string, filter?: Record<string, unknown>) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const queryString = filter ? `?${new URLSearchParams(filter as Record<string, string>).toString()}` : ''
|
||||
const response = await fetch(`/api/v1/${entity}${queryString}`)
|
||||
if (!response.ok) throw new Error('Failed to fetch')
|
||||
return await response.json()
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const create = useCallback(async (entity: string, data: Record<string, unknown>) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/v1/${entity}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to create')
|
||||
return await response.json()
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const update = useCallback(async (entity: string, id: string, data: Record<string, unknown>) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/v1/${entity}/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to update')
|
||||
return await response.json()
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const deleteEntity = useCallback(async (entity: string, id: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/v1/${entity}/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to delete')
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
get,
|
||||
list,
|
||||
create,
|
||||
update,
|
||||
delete: deleteEntity,
|
||||
isLoading,
|
||||
error,
|
||||
}
|
||||
}
|
||||
52
frontends/nextjs/src/hooks/useFileTree.ts
Normal file
52
frontends/nextjs/src/hooks/useFileTree.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Hook for managing file tree state
|
||||
*/
|
||||
import { useState } from 'react'
|
||||
|
||||
export interface FileNode {
|
||||
path: string
|
||||
name: string
|
||||
type: 'file' | 'directory'
|
||||
children?: FileNode[]
|
||||
content?: string
|
||||
}
|
||||
|
||||
export interface UseFileTreeReturn {
|
||||
tree: FileNode[]
|
||||
expandedPaths: Set<string>
|
||||
selectedPath: string | null
|
||||
toggleExpanded: (path: string) => void
|
||||
selectPath: (path: string) => void
|
||||
setTree: (tree: FileNode[]) => void
|
||||
}
|
||||
|
||||
export function useFileTree(initialTree: FileNode[] = []): UseFileTreeReturn {
|
||||
const [tree, setTree] = useState<FileNode[]>(initialTree)
|
||||
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set())
|
||||
const [selectedPath, setSelectedPath] = useState<string | null>(null)
|
||||
|
||||
const toggleExpanded = (path: string) => {
|
||||
setExpandedPaths(prev => {
|
||||
const next = new Set(prev)
|
||||
if (next.has(path)) {
|
||||
next.delete(path)
|
||||
} else {
|
||||
next.add(path)
|
||||
}
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
const selectPath = (path: string) => {
|
||||
setSelectedPath(path)
|
||||
}
|
||||
|
||||
return {
|
||||
tree,
|
||||
expandedPaths,
|
||||
selectedPath,
|
||||
toggleExpanded,
|
||||
selectPath,
|
||||
setTree,
|
||||
}
|
||||
}
|
||||
66
frontends/nextjs/src/hooks/useGitHubFetcher.ts
Normal file
66
frontends/nextjs/src/hooks/useGitHubFetcher.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Hook for fetching GitHub Actions workflow data
|
||||
*/
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
export interface WorkflowRun {
|
||||
id: number
|
||||
name: string
|
||||
status: string
|
||||
conclusion: string | null
|
||||
created_at: string
|
||||
updated_at: string
|
||||
html_url: string
|
||||
}
|
||||
|
||||
export interface UseGitHubFetcherReturn {
|
||||
runs: WorkflowRun[]
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
refresh: () => Promise<void>
|
||||
}
|
||||
|
||||
export function useGitHubFetcher(
|
||||
owner?: string,
|
||||
repo?: string,
|
||||
autoRefresh = false
|
||||
): UseGitHubFetcherReturn {
|
||||
const [runs, setRuns] = useState<WorkflowRun[]>([])
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
const fetchRuns = async () => {
|
||||
if (!owner || !repo) return
|
||||
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/github/actions/runs?owner=${owner}&repo=${repo}`)
|
||||
if (!response.ok) throw new Error('Failed to fetch workflow runs')
|
||||
const data = await response.json()
|
||||
setRuns(data.workflow_runs || [])
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchRuns()
|
||||
}, [owner, repo])
|
||||
|
||||
useEffect(() => {
|
||||
if (autoRefresh) {
|
||||
const interval = setInterval(fetchRuns, 30000)
|
||||
return () => clearInterval(interval)
|
||||
}
|
||||
}, [autoRefresh, owner, repo])
|
||||
|
||||
return {
|
||||
runs,
|
||||
isLoading,
|
||||
error,
|
||||
refresh: fetchRuns,
|
||||
}
|
||||
}
|
||||
97
frontends/nextjs/src/hooks/useKV.ts
Normal file
97
frontends/nextjs/src/hooks/useKV.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Hook for key-value storage operations
|
||||
*/
|
||||
import { useState, useCallback } from 'react'
|
||||
|
||||
export interface UseKVReturn {
|
||||
get: (key: string) => Promise<string | null>
|
||||
set: (key: string, value: string) => Promise<void>
|
||||
delete: (key: string) => Promise<void>
|
||||
list: (prefix?: string) => Promise<string[]>
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
}
|
||||
|
||||
export function useKV(): UseKVReturn {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
const get = useCallback(async (key: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/kv/${key}`)
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) return null
|
||||
throw new Error('Failed to get key')
|
||||
}
|
||||
const data = await response.json()
|
||||
return data.value
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const set = useCallback(async (key: string, value: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/kv/${key}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ value }),
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to set key')
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const deleteKey = useCallback(async (key: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await fetch(`/api/kv/${key}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to delete key')
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const list = useCallback(async (prefix?: string) => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const queryString = prefix ? `?prefix=${encodeURIComponent(prefix)}` : ''
|
||||
const response = await fetch(`/api/kv${queryString}`)
|
||||
if (!response.ok) throw new Error('Failed to list keys')
|
||||
const data = await response.json()
|
||||
return data.keys || []
|
||||
} catch (err) {
|
||||
setError(err as Error)
|
||||
throw err
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
delete: deleteKey,
|
||||
list,
|
||||
isLoading,
|
||||
error,
|
||||
}
|
||||
}
|
||||
7
frontends/nextjs/src/lib/api/read-json.ts
Normal file
7
frontends/nextjs/src/lib/api/read-json.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// TODO: Implement JSON reading utility
|
||||
export const readJson = async <T = any>(request: any): Promise<T> => {
|
||||
if (!request || !request.body) return {} as T
|
||||
const body = request.body
|
||||
const text = await new Response(body).text()
|
||||
return JSON.parse(text)
|
||||
}
|
||||
27
frontends/nextjs/src/lib/auth/api/fetch-session.ts
Normal file
27
frontends/nextjs/src/lib/auth/api/fetch-session.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @file fetch-session.ts
|
||||
* @description Fetch current user session
|
||||
*/
|
||||
|
||||
import type { User } from '@/lib/level-types'
|
||||
|
||||
export async function fetchSession(): Promise<User | null> {
|
||||
try {
|
||||
const response = await fetch('/api/auth/session', {
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
return null
|
||||
}
|
||||
throw new Error('Failed to fetch session')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return data.user || null
|
||||
} catch (error) {
|
||||
console.error('Error fetching session:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
25
frontends/nextjs/src/lib/auth/api/login.ts
Normal file
25
frontends/nextjs/src/lib/auth/api/login.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file login.ts
|
||||
* @description User login API
|
||||
*/
|
||||
|
||||
import type { User } from '@/lib/level-types'
|
||||
|
||||
export async function login(identifier: string, password: string): Promise<User> {
|
||||
const response = await fetch('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ identifier, password }),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ message: 'Login failed' }))
|
||||
throw new Error(error.message || 'Login failed')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return data.user
|
||||
}
|
||||
15
frontends/nextjs/src/lib/auth/api/logout.ts
Normal file
15
frontends/nextjs/src/lib/auth/api/logout.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @file logout.ts
|
||||
* @description User logout API
|
||||
*/
|
||||
|
||||
export async function logout(): Promise<void> {
|
||||
const response = await fetch('/api/auth/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Logout failed')
|
||||
}
|
||||
}
|
||||
25
frontends/nextjs/src/lib/auth/api/register.ts
Normal file
25
frontends/nextjs/src/lib/auth/api/register.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file register.ts
|
||||
* @description User registration API
|
||||
*/
|
||||
|
||||
import type { User } from '@/lib/level-types'
|
||||
|
||||
export async function register(username: string, email: string, password: string): Promise<User> {
|
||||
const response = await fetch('/api/auth/register', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ username, email, password }),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ message: 'Registration failed' }))
|
||||
throw new Error(error.message || 'Registration failed')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return data.user
|
||||
}
|
||||
3
frontends/nextjs/src/lib/compiler.ts
Normal file
3
frontends/nextjs/src/lib/compiler.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// TODO: Implement compiler utilities
|
||||
export const compiler = {}
|
||||
export const loadAndInjectStyles = async (packageId: string) => []
|
||||
2
frontends/nextjs/src/lib/components/component-catalog.ts
Normal file
2
frontends/nextjs/src/lib/components/component-catalog.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// TODO: Implement component catalog
|
||||
export const componentCatalog = {}
|
||||
@@ -0,0 +1,2 @@
|
||||
// TODO: Implement component registry
|
||||
export const componentRegistry = {}
|
||||
8
frontends/nextjs/src/lib/config/prisma.ts
Normal file
8
frontends/nextjs/src/lib/config/prisma.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Prisma client configuration stub
|
||||
* TODO: Implement Prisma configuration
|
||||
*/
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
export const prisma = new PrismaClient()
|
||||
export const prismaConfig = { prisma }
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AppConfiguration } from '../../types/level-types'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
import { getAdapter } from '../core/dbal-client'
|
||||
|
||||
export async function getAppConfig(): Promise<AppConfiguration | null> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AppConfiguration } from '../../types/level-types'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
import { getAdapter } from '../core/dbal-client'
|
||||
|
||||
export async function setAppConfig(config: AppConfiguration): Promise<void> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import { verifyPassword } from '../../password/verify-password'
|
||||
import type { User } from '../../types/level-types'
|
||||
import type { User } from '@/lib/level-types'
|
||||
import { getUserFirstLoginFlag } from '../../users/getters/get-user-first-login-flag'
|
||||
import { mapUserRecord } from '../../users/map-user-record'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { User } from '../../types/level-types'
|
||||
import type { User } from '@/lib/level-types'
|
||||
import { mapUserRecord } from '../../users/map-user-record'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { User } from '../../types/level-types'
|
||||
import type { User } from '@/lib/level-types'
|
||||
import { mapUserRecord } from '../../users/map-user-record'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
const mockCreate = vi.fn()
|
||||
const mockAdapter = { create: mockCreate }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Add a single comment
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
type DBALCommentRecord = {
|
||||
id: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
type DBALCommentRecord = {
|
||||
id: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
const mockUpdate = vi.fn()
|
||||
const mockAdapter = { update: mockUpdate }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Comment } from '../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Update a comment by ID
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../../core/dbal-client'
|
||||
import type { ComponentConfig } from '../types'
|
||||
import type { ComponentConfig } from './types'
|
||||
|
||||
export async function addComponentConfig(config: ComponentConfig): Promise<void> {
|
||||
const adapter = getAdapter()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Component config types
|
||||
*/
|
||||
export type { ComponentConfig } from '../../../../core/types'
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../../core/dbal-client'
|
||||
import type { ComponentConfig } from '../types'
|
||||
import type { ComponentConfig } from './types'
|
||||
|
||||
export async function updateComponentConfig(
|
||||
configId: string,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { ComponentConfig } from '../types'
|
||||
import type { ComponentConfig } from './types'
|
||||
|
||||
type DBALComponentConfigRecord = {
|
||||
id: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { ComponentConfig } from '../types'
|
||||
import type { ComponentConfig } from './types'
|
||||
|
||||
type DBALComponentConfigRecord = {
|
||||
id: string
|
||||
|
||||
4
frontends/nextjs/src/lib/db/components/config/types.ts
Normal file
4
frontends/nextjs/src/lib/db/components/config/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Re-export component-related types from core/types
|
||||
*/
|
||||
export type { ComponentConfig, ComponentNode } from '../../core/types'
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { ComponentNode } from '../types'
|
||||
import type { ComponentNode } from './types'
|
||||
|
||||
type DBALComponentNodeRecord = {
|
||||
id: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { ComponentNode } from '../types'
|
||||
import type { ComponentNode } from './types'
|
||||
|
||||
type DBALComponentNodeRecord = {
|
||||
id: string
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Re-export component hierarchy types from core/types
|
||||
*/
|
||||
export type { ComponentNode } from '../../core/types'
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../core/dbal-client'
|
||||
import type { ComponentNode } from '../types'
|
||||
import type { ComponentNode } from './types'
|
||||
|
||||
export async function addComponentNode(node: ComponentNode): Promise<void> {
|
||||
const adapter = getAdapter()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Component node types
|
||||
*/
|
||||
export type { ComponentNode } from '../../../components/node/types'
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../core/dbal-client'
|
||||
import type { ComponentNode } from '../types'
|
||||
import type { ComponentNode } from './types'
|
||||
|
||||
export async function updateComponentNode(
|
||||
nodeId: string,
|
||||
|
||||
4
frontends/nextjs/src/lib/db/components/node/types.ts
Normal file
4
frontends/nextjs/src/lib/db/components/node/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Re-export component node types from core/types
|
||||
*/
|
||||
export type { ComponentNode } from '../../core/types'
|
||||
@@ -47,14 +47,14 @@ export interface ComponentConfig {
|
||||
* Full database schema type
|
||||
*/
|
||||
export interface DatabaseSchema {
|
||||
users: import('../types/level-types').User[]
|
||||
users: import('@/lib/level-types').User[]
|
||||
credentials: Record<string, string>
|
||||
workflows: import('../types/level-types').Workflow[]
|
||||
luaScripts: import('../types/level-types').LuaScript[]
|
||||
pages: import('../types/level-types').PageConfig[]
|
||||
workflows: import('@/lib/level-types').Workflow[]
|
||||
luaScripts: import('@/lib/level-types').LuaScript[]
|
||||
pages: import('@/lib/level-types').PageConfig[]
|
||||
schemas: import('../types/schema-types').ModelSchema[]
|
||||
appConfig: import('../types/level-types').AppConfiguration
|
||||
comments: import('../types/level-types').Comment[]
|
||||
appConfig: import('@/lib/level-types').AppConfiguration
|
||||
comments: import('@/lib/level-types').Comment[]
|
||||
componentHierarchy: Record<string, ComponentNode>
|
||||
componentConfigs: Record<string, ComponentConfig>
|
||||
godCredentialsExpiry: number
|
||||
@@ -63,9 +63,9 @@ export interface DatabaseSchema {
|
||||
godCredentialsExpiryDuration: number
|
||||
cssClasses: CssCategory[]
|
||||
dropdownConfigs: DropdownConfig[]
|
||||
tenants: import('../types/level-types').Tenant[]
|
||||
powerTransferRequests: import('../types/level-types').PowerTransferRequest[]
|
||||
smtpConfig: import('../password').SMTPConfig
|
||||
tenants: import('@/lib/level-types').Tenant[]
|
||||
powerTransferRequests: import('@/lib/level-types').PowerTransferRequest[]
|
||||
smtpConfig: import('@/lib/password').SMTPConfig
|
||||
passwordResetTokens: Record<string, string>
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export async function getCssClasses(): Promise<CssCategory[]> {
|
||||
const result = await adapter.list('CssCategory')
|
||||
const rows = result.data as Array<{ name: string; classes: string | string[] }>
|
||||
return rows.map(c => ({
|
||||
id: (c as any).id || c.name,
|
||||
name: c.name,
|
||||
classes: typeof c.classes === 'string' ? JSON.parse(c.classes) : c.classes,
|
||||
}))
|
||||
|
||||
8
frontends/nextjs/src/lib/db/css-classes/types.ts
Normal file
8
frontends/nextjs/src/lib/db/css-classes/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* CSS classes types
|
||||
*/
|
||||
export interface CssCategory {
|
||||
name: string
|
||||
classes: string[]
|
||||
id?: string
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { getComponentConfigs, getComponentHierarchy } from '../../components'
|
||||
import { getLuaScripts } from '../../lua-scripts'
|
||||
import { getPages } from '../../pages'
|
||||
import { getSchemas } from '../../schemas'
|
||||
import type { DatabaseSchema } from '../../types'
|
||||
import type { DatabaseSchema } from '../types'
|
||||
import { getUsers } from '../../users'
|
||||
import { getWorkflows } from '../../workflows'
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { setComponentConfigs, setComponentHierarchy } from '../../components'
|
||||
import { setLuaScripts } from '../../lua-scripts'
|
||||
import { setPages } from '../../pages'
|
||||
import { setSchemas } from '../../schemas'
|
||||
import type { DatabaseSchema } from '../../types'
|
||||
import type { DatabaseSchema } from '../types'
|
||||
import { setUsers } from '../../users'
|
||||
import { setWorkflows } from '../../workflows'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AppConfiguration } from '../../../types/level-types'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
|
||||
export const buildDefaultAppConfig = (): AppConfiguration => ({
|
||||
id: 'app_001',
|
||||
|
||||
6
frontends/nextjs/src/lib/db/database-admin/types.ts
Normal file
6
frontends/nextjs/src/lib/db/database-admin/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Database admin types
|
||||
*/
|
||||
export * from '@/lib/level-types'
|
||||
export * from '@/lib/schema-types'
|
||||
export type { DatabaseSchema } from '../core/types'
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* DBAL adapter close re-export
|
||||
*/
|
||||
export { closeAdapter } from '@/lib/dbal-client/adapter/close-adapter'
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* DBAL adapter get re-export
|
||||
*/
|
||||
export { getAdapter } from '@/lib/dbal-client/adapter/get-adapter'
|
||||
6
frontends/nextjs/src/lib/db/dbal-client/types.ts
Normal file
6
frontends/nextjs/src/lib/db/dbal-client/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* DBAL types re-export
|
||||
*/
|
||||
export * from '@/lib/dbal-client/types'
|
||||
export type ListResult<T> = { data: T[], total: number }
|
||||
export type ListOptions = { page?: number, limit?: number }
|
||||
9
frontends/nextjs/src/lib/db/dropdown-configs/types.ts
Normal file
9
frontends/nextjs/src/lib/db/dropdown-configs/types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Dropdown config types
|
||||
*/
|
||||
export interface DropdownConfig {
|
||||
id: string
|
||||
name: string
|
||||
label?: string
|
||||
options: any[]
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* Retrieves the application configuration from database
|
||||
*/
|
||||
|
||||
import type { AppConfiguration } from '../../../types/level-types'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Saves the application configuration to database
|
||||
*/
|
||||
|
||||
import type { AppConfiguration } from '../../../types/level-types'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Add comment function
|
||||
*/
|
||||
export function addComment(comment: any) {
|
||||
// TODO: Implement add comment
|
||||
return comment
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* Adds a new comment to database
|
||||
*/
|
||||
|
||||
import type { Comment } from '../../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Retrieves all comments from database
|
||||
*/
|
||||
|
||||
import type { Comment } from '../../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Replaces all comments in database
|
||||
*/
|
||||
|
||||
import type { Comment } from '../../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Updates an existing comment
|
||||
*/
|
||||
|
||||
import type { Comment } from '../../../types/level-types'
|
||||
import type { Comment } from '@/lib/level-types'
|
||||
import { prisma } from '../../prisma'
|
||||
|
||||
type CommentUpdateData = {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Delete comment function
|
||||
*/
|
||||
export function deleteComment(id: string) {
|
||||
// TODO: Implement delete comment
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Get comments function
|
||||
*/
|
||||
export function getComments(filter?: any) {
|
||||
// TODO: Implement get comments
|
||||
return []
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Set comments function
|
||||
*/
|
||||
export function setComments(comments: any[]) {
|
||||
// TODO: Implement set comments
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Update comment function
|
||||
*/
|
||||
export function updateComment(id: string, updates: any) {
|
||||
// TODO: Implement update comment
|
||||
return { ...updates, id }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Component types for functions
|
||||
*/
|
||||
export type { ComponentNode } from '../../../components/node/types'
|
||||
4
frontends/nextjs/src/lib/db/functions/prisma.ts
Normal file
4
frontends/nextjs/src/lib/db/functions/prisma.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Prisma client re-export for functions
|
||||
*/
|
||||
export { prisma } from '../../config/prisma'
|
||||
17
frontends/nextjs/src/lib/db/god-credentials/index.ts
Normal file
17
frontends/nextjs/src/lib/db/god-credentials/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* God credentials operations stub
|
||||
* TODO: Implement god credentials functionality
|
||||
*/
|
||||
|
||||
export const godCredentials = {
|
||||
// Stub exports
|
||||
}
|
||||
|
||||
export const getGodCredentialsExpiry = () => 0
|
||||
export const setGodCredentialsExpiry = (expiry: number) => {}
|
||||
export const getFirstLoginFlags = () => ({})
|
||||
export const setFirstLoginFlag = (userId: string, value: boolean) => {}
|
||||
export const getGodCredentialsExpiryDuration = () => 3600000
|
||||
export const setGodCredentialsExpiryDuration = (duration: number) => {}
|
||||
export const shouldShowGodCredentials = () => false
|
||||
export const resetGodCredentialsExpiry = () => {}
|
||||
14
frontends/nextjs/src/lib/db/lua-scripts/index.ts
Normal file
14
frontends/nextjs/src/lib/db/lua-scripts/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Lua scripts operations stub
|
||||
* TODO: Implement lua scripts functionality
|
||||
*/
|
||||
|
||||
export const luaScripts = {
|
||||
// Stub exports
|
||||
}
|
||||
|
||||
export const getLuaScripts = async () => []
|
||||
export const setLuaScripts = async (scripts: any[]) => {}
|
||||
export const addLuaScript = async (script: any) => {}
|
||||
export const updateLuaScript = async (id: string, updates: any) => {}
|
||||
export const deleteLuaScript = async (id: string) => {}
|
||||
15
frontends/nextjs/src/lib/db/packages/core/package-types.ts
Normal file
15
frontends/nextjs/src/lib/db/packages/core/package-types.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Package type definitions (core)
|
||||
*/
|
||||
export interface PackageMetadata {
|
||||
name: string
|
||||
version: string
|
||||
description?: string
|
||||
dependencies?: string[]
|
||||
exports?: Record<string, any>
|
||||
}
|
||||
|
||||
export interface PackageData {
|
||||
id: string
|
||||
data: any
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import { type PackageSeedData } from '../../packages/core/package-types'
|
||||
import { type PackageData } from '../../packages/core/package-types'
|
||||
|
||||
/**
|
||||
* Set package data (upsert)
|
||||
*/
|
||||
export async function setPackageData(
|
||||
packageId: string,
|
||||
data: PackageSeedData
|
||||
data: any
|
||||
): Promise<void> {
|
||||
const adapter = getAdapter()
|
||||
await adapter.upsert('PackageData', {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../core/dbal-client'
|
||||
import type { InstalledPackage } from '../../packages/package-types'
|
||||
import type { InstalledPackage } from '../../package-types'
|
||||
|
||||
/**
|
||||
* Install a package (creates record if not exists)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../core/dbal-client'
|
||||
import type { InstalledPackage } from '../../packages/package-types'
|
||||
import type { InstalledPackage } from '../../package-types'
|
||||
|
||||
type DBALInstalledPackageRecord = {
|
||||
packageId: string
|
||||
@@ -17,6 +17,7 @@ export async function getInstalledPackages(): Promise<InstalledPackage[]> {
|
||||
data: DBALInstalledPackageRecord[]
|
||||
}
|
||||
return result.data.map(p => ({
|
||||
id: (p as any).id || p.packageId,
|
||||
packageId: p.packageId,
|
||||
installedAt: Number(p.installedAt),
|
||||
version: p.version,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../../core/dbal-client'
|
||||
import type { InstalledPackage } from '../../packages/package-types'
|
||||
import type { InstalledPackage } from '../../package-types'
|
||||
|
||||
type DBALInstalledPackageRecord = {
|
||||
packageId: string
|
||||
|
||||
18
frontends/nextjs/src/lib/db/packages/package-types.ts
Normal file
18
frontends/nextjs/src/lib/db/packages/package-types.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Package type definitions
|
||||
*/
|
||||
export interface PackageMetadata {
|
||||
name: string
|
||||
version: string
|
||||
description?: string
|
||||
dependencies?: string[]
|
||||
exports?: Record<string, any>
|
||||
}
|
||||
|
||||
export interface InstalledPackage {
|
||||
id: string
|
||||
packageId: string
|
||||
version: string
|
||||
installedAt: number
|
||||
enabled?: boolean
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { PageConfig } from '../../types/level-types'
|
||||
import type { PageConfig } from '@/lib/level-types'
|
||||
|
||||
const mockCreate = vi.fn()
|
||||
const mockAdapter = { create: mockCreate }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { PageConfig } from '../../types/level-types'
|
||||
import type { PageConfig } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Add a page
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { PageConfig, UserRole } from '../../types/level-types'
|
||||
import type { PageConfig, UserRole } from '@/lib/level-types'
|
||||
|
||||
type DBALPageRecord = {
|
||||
id: string
|
||||
@@ -38,5 +38,7 @@ export async function getPages(): Promise<PageConfig[]> {
|
||||
componentTree: JSON.parse(p.componentTree) as PageConfig['componentTree'],
|
||||
requiresAuth: p.requiresAuth,
|
||||
requiredRole: p.requiredRole ? toUserRole(p.requiredRole) : undefined,
|
||||
sortOrder: Number((p as any).sortOrder || 0),
|
||||
isPublished: Boolean((p as any).isPublished !== false),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { PageConfig } from '../../types/level-types'
|
||||
import type { PageConfig } from '@/lib/level-types'
|
||||
|
||||
const mockList = vi.fn()
|
||||
const mockDelete = vi.fn()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { PageConfig } from '../../types/level-types'
|
||||
import type { PageConfig } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Set all pages (replaces existing)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { PageConfig } from '../../types/level-types'
|
||||
import type { PageConfig } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Update a page by ID
|
||||
|
||||
14
frontends/nextjs/src/lib/db/power-transfers/index.ts
Normal file
14
frontends/nextjs/src/lib/db/power-transfers/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Power transfers operations stub
|
||||
* TODO: Implement power transfers functionality
|
||||
*/
|
||||
|
||||
export const powerTransfers = {
|
||||
// Stub exports
|
||||
}
|
||||
|
||||
export const getPowerTransferRequests = async () => []
|
||||
export const setPowerTransferRequests = async (requests: any[]) => {}
|
||||
export const addPowerTransferRequest = async (request: any) => {}
|
||||
export const updatePowerTransferRequest = async (id: string, updates: any) => {}
|
||||
export const deletePowerTransferRequest = async (id: string) => {}
|
||||
4
frontends/nextjs/src/lib/db/prisma.ts
Normal file
4
frontends/nextjs/src/lib/db/prisma.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Prisma client re-export
|
||||
*/
|
||||
export { prisma } from '../config/prisma'
|
||||
@@ -20,6 +20,7 @@ export async function getSchemas(): Promise<ModelSchema[]> {
|
||||
const adapter = getAdapter()
|
||||
const result = (await adapter.list('ModelSchema')) as { data: DBALModelSchemaRecord[] }
|
||||
return result.data.map(s => ({
|
||||
id: (s as any).id || `schema-${s.name}`,
|
||||
name: s.name,
|
||||
label: s.label || undefined,
|
||||
labelPlural: s.labelPlural || undefined,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { ModelSchema } from '../../types/schema-types'
|
||||
import type { ModelSchema } from '@/lib/schema-types'
|
||||
|
||||
/**
|
||||
* Update a schema by name
|
||||
|
||||
35
frontends/nextjs/src/lib/db/sessions/crud/create/types.ts
Normal file
35
frontends/nextjs/src/lib/db/sessions/crud/create/types.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Session type definitions
|
||||
*/
|
||||
export interface Session {
|
||||
id: string
|
||||
userId: string
|
||||
token: string
|
||||
expiresAt: number
|
||||
createdAt: number
|
||||
updatedAt?: number
|
||||
lastActivity?: number
|
||||
}
|
||||
|
||||
export interface CreateSessionData {
|
||||
userId: string
|
||||
token: string
|
||||
expiresAt: number
|
||||
lastActivity?: number
|
||||
createdAt?: number
|
||||
id?: string
|
||||
}
|
||||
|
||||
export type CreateSessionInput = CreateSessionData
|
||||
|
||||
export interface UpdateSessionInput {
|
||||
token?: string
|
||||
expiresAt?: number
|
||||
lastActivity?: number
|
||||
}
|
||||
|
||||
export interface ListSessionsOptions {
|
||||
userId?: string
|
||||
limit?: number
|
||||
includeExpired?: boolean
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import { mapSessionRecord } from '../map-session-record'
|
||||
import type { Session, UpdateSessionInput } from './types'
|
||||
import type { Session, UpdateSessionInput } from '../getters/types'
|
||||
|
||||
export async function updateSession(
|
||||
sessionId: string,
|
||||
|
||||
24
frontends/nextjs/src/lib/db/sessions/getters/types.ts
Normal file
24
frontends/nextjs/src/lib/db/sessions/getters/types.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Session type definitions
|
||||
*/
|
||||
export interface Session {
|
||||
id: string
|
||||
userId: string
|
||||
token: string
|
||||
expiresAt: number
|
||||
createdAt: number
|
||||
updatedAt?: number
|
||||
lastActivity?: number
|
||||
}
|
||||
|
||||
export interface UpdateSessionInput {
|
||||
token?: string
|
||||
expiresAt?: number
|
||||
lastActivity?: number
|
||||
}
|
||||
|
||||
export interface ListSessionsOptions {
|
||||
userId?: string
|
||||
limit?: number
|
||||
includeExpired?: boolean
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export async function getSMTPConfig(): Promise<SMTPConfig | null> {
|
||||
if (!config) return null
|
||||
|
||||
return {
|
||||
id: config.id || 'default',
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
secure: config.secure,
|
||||
@@ -20,5 +21,7 @@ export async function getSMTPConfig(): Promise<SMTPConfig | null> {
|
||||
password: config.password,
|
||||
fromEmail: config.fromEmail,
|
||||
fromName: config.fromName,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Tenant } from '../../types/level-types'
|
||||
import type { Tenant } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Add a new tenant
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { JsonValue } from '@/types/utility-types'
|
||||
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Tenant } from '../../types/level-types'
|
||||
import type { Tenant } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Get all tenants from database
|
||||
@@ -19,6 +19,7 @@ export async function getTenants(): Promise<Tenant[]> {
|
||||
return rows.map(t => ({
|
||||
id: t.id,
|
||||
name: t.name,
|
||||
slug: (t as any).slug || t.id,
|
||||
ownerId: t.ownerId,
|
||||
createdAt: Number(t.createdAt),
|
||||
homepageConfig: t.homepageConfig
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Tenant } from '../../types/level-types'
|
||||
import type { Tenant } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Set all tenants (replaces existing)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAdapter } from '../../core/dbal-client'
|
||||
import type { Tenant } from '../../types/level-types'
|
||||
import type { Tenant } from '@/lib/level-types'
|
||||
|
||||
/**
|
||||
* Update an existing tenant
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user