mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-01 17:24:57 +00:00
Merge pull request #118 from johndoe6345789/codex/refactor-typescript-files-into-modular-structure
Refactor modular TypeScript files over threshold
This commit is contained in:
@@ -2,27 +2,11 @@
|
||||
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
Container,
|
||||
Divider,
|
||||
Grid,
|
||||
LinearProgress,
|
||||
Paper,
|
||||
Stack,
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import { Container, Stack, Typography } from '@mui/material'
|
||||
|
||||
import { PERMISSION_LEVELS, type PermissionLevel } from './levels-data'
|
||||
|
||||
const highlightColor = (level: PermissionLevel) => {
|
||||
if (level.id === 6) return 'warning.main'
|
||||
if (level.id === 5) return 'primary.main'
|
||||
return 'divider'
|
||||
}
|
||||
import { LevelDetails } from './components/LevelDetails'
|
||||
import { LevelsGrid } from './components/LevelsGrid'
|
||||
import { PERMISSION_LEVELS } from './levels-data'
|
||||
|
||||
export default function LevelsClient() {
|
||||
const [selectedLevelId, setSelectedLevelId] = useState(PERMISSION_LEVELS[0].id)
|
||||
@@ -70,94 +54,19 @@ export default function LevelsClient() {
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
{PERMISSION_LEVELS.map((level) => (
|
||||
<Grid item xs={12} md={6} lg={4} key={level.id} component="div">
|
||||
<Paper
|
||||
onClick={() => handleSelect(level.id)}
|
||||
sx={{
|
||||
border: (theme) => `2px solid ${selectedLevel.id === level.id ? theme.palette.primary.main : theme.palette.divider}`,
|
||||
p: 3,
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
},
|
||||
}}
|
||||
elevation={selectedLevel.id === level.id ? 6 : 1}
|
||||
>
|
||||
<Box sx={{ position: 'absolute', top: 16, right: 16 }}>
|
||||
<Chip label={level.badge} />
|
||||
</Box>
|
||||
<Typography variant="h6">Level {level.id} · {level.title}</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
||||
{level.tagline}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ mb: 2 }}>
|
||||
{level.description}
|
||||
</Typography>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap">
|
||||
{level.capabilities.slice(0, 3).map((capability) => (
|
||||
<Chip key={capability} label={capability} size="small" variant="outlined" />
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
<LevelsGrid
|
||||
levels={PERMISSION_LEVELS}
|
||||
onSelect={handleSelect}
|
||||
selectedLevelId={selectedLevelId}
|
||||
/>
|
||||
|
||||
<Paper sx={{ p: 4, border: (theme) => `1px dashed ${theme.palette.divider}`, bgcolor: 'background.paper' }}>
|
||||
<Stack spacing={2}>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<Typography variant="h5">Selected level details</Typography>
|
||||
<Chip label={selectedLevel.badge} size="small" color="secondary" />
|
||||
</Stack>
|
||||
<Typography variant="body1" color="text.secondary">
|
||||
{selectedLevel.description}
|
||||
</Typography>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap">
|
||||
{selectedLevel.capabilities.map((capability) => (
|
||||
<Chip
|
||||
key={capability}
|
||||
label={capability}
|
||||
size="small"
|
||||
sx={{ borderColor: highlightColor(selectedLevel) }}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<Stack spacing={1}>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={(selectedLevel.capabilities.length / maxCapabilityCount) * 100}
|
||||
sx={{ height: 10, borderRadius: 2 }}
|
||||
/>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{selectedLevel.capabilities.length} of {maxCapabilityCount} capability tiers unlocked
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Divider />
|
||||
<Box>
|
||||
<Typography variant="subtitle2" gutterBottom>
|
||||
Next move
|
||||
</Typography>
|
||||
{nextLevel ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Promote into <strong>{nextLevel.title}</strong> to unlock {nextLevel.capabilities.length} controls.
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Super God reigns supreme. You already own every privilege.
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<Box>
|
||||
<Button variant="contained" onClick={handlePromote}>
|
||||
{nextLevel ? `Promote to ${nextLevel.title}` : 'Hold the crown'}
|
||||
</Button>
|
||||
</Box>
|
||||
{note && <Alert severity="info">{note}</Alert>}
|
||||
</Stack>
|
||||
</Paper>
|
||||
<LevelDetails
|
||||
selectedLevel={selectedLevel}
|
||||
nextLevel={nextLevel}
|
||||
maxCapabilityCount={maxCapabilityCount}
|
||||
note={note}
|
||||
onPromote={handlePromote}
|
||||
/>
|
||||
</Stack>
|
||||
</Container>
|
||||
)
|
||||
|
||||
67
frontends/nextjs/src/app/levels/components/LevelDetails.tsx
Normal file
67
frontends/nextjs/src/app/levels/components/LevelDetails.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Alert, Box, Button, Chip, Divider, LinearProgress, Paper, Stack, Typography } from '@mui/material'
|
||||
|
||||
import type { PermissionLevel } from '../levels-data'
|
||||
import { highlightColor } from '../utils/highlightColor'
|
||||
|
||||
type LevelDetailsProps = {
|
||||
selectedLevel: PermissionLevel
|
||||
nextLevel: PermissionLevel | null
|
||||
maxCapabilityCount: number
|
||||
note: string
|
||||
onPromote: () => void
|
||||
}
|
||||
|
||||
export const LevelDetails = ({ selectedLevel, nextLevel, maxCapabilityCount, note, onPromote }: LevelDetailsProps) => (
|
||||
<Paper sx={{ p: 4, border: (theme) => `1px dashed ${theme.palette.divider}`, bgcolor: 'background.paper' }}>
|
||||
<Stack spacing={2}>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<Typography variant="h5">Selected level details</Typography>
|
||||
<Chip label={selectedLevel.badge} size="small" color="secondary" />
|
||||
</Stack>
|
||||
<Typography variant="body1" color="text.secondary">
|
||||
{selectedLevel.description}
|
||||
</Typography>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap">
|
||||
{selectedLevel.capabilities.map((capability) => (
|
||||
<Chip
|
||||
key={capability}
|
||||
label={capability}
|
||||
size="small"
|
||||
sx={{ borderColor: highlightColor(selectedLevel) }}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<Stack spacing={1}>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={(selectedLevel.capabilities.length / maxCapabilityCount) * 100}
|
||||
sx={{ height: 10, borderRadius: 2 }}
|
||||
/>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{selectedLevel.capabilities.length} of {maxCapabilityCount} capability tiers unlocked
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Divider />
|
||||
<Box>
|
||||
<Typography variant="subtitle2" gutterBottom>
|
||||
Next move
|
||||
</Typography>
|
||||
{nextLevel ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Promote into <strong>{nextLevel.title}</strong> to unlock {nextLevel.capabilities.length} controls.
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Super God reigns supreme. You already own every privilege.
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<Box>
|
||||
<Button variant="contained" onClick={onPromote}>
|
||||
{nextLevel ? `Promote to ${nextLevel.title}` : 'Hold the crown'}
|
||||
</Button>
|
||||
</Box>
|
||||
{note && <Alert severity="info">{note}</Alert>}
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
47
frontends/nextjs/src/app/levels/components/LevelsGrid.tsx
Normal file
47
frontends/nextjs/src/app/levels/components/LevelsGrid.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Box, Chip, Grid, Paper, Stack, Typography } from '@mui/material'
|
||||
|
||||
import type { PermissionLevel } from '../levels-data'
|
||||
|
||||
type LevelsGridProps = {
|
||||
levels: PermissionLevel[]
|
||||
selectedLevelId: number
|
||||
onSelect: (levelId: number) => void
|
||||
}
|
||||
|
||||
export const LevelsGrid = ({ levels, selectedLevelId, onSelect }: LevelsGridProps) => (
|
||||
<Grid container spacing={3}>
|
||||
{levels.map((level) => (
|
||||
<Grid item xs={12} md={6} lg={4} key={level.id} component="div">
|
||||
<Paper
|
||||
onClick={() => onSelect(level.id)}
|
||||
sx={{
|
||||
border: (theme) => `2px solid ${selectedLevelId === level.id ? theme.palette.primary.main : theme.palette.divider}`,
|
||||
p: 3,
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
},
|
||||
}}
|
||||
elevation={selectedLevelId === level.id ? 6 : 1}
|
||||
>
|
||||
<Box sx={{ position: 'absolute', top: 16, right: 16 }}>
|
||||
<Chip label={level.badge} />
|
||||
</Box>
|
||||
<Typography variant="h6">Level {level.id} · {level.title}</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
||||
{level.tagline}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ mb: 2 }}>
|
||||
{level.description}
|
||||
</Typography>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap">
|
||||
{level.capabilities.slice(0, 3).map((capability) => (
|
||||
<Chip key={capability} label={capability} size="small" variant="outlined" />
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
7
frontends/nextjs/src/app/levels/utils/highlightColor.ts
Normal file
7
frontends/nextjs/src/app/levels/utils/highlightColor.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { PermissionLevel } from '../levels-data'
|
||||
|
||||
export const highlightColor = (level: PermissionLevel) => {
|
||||
if (level.id === 6) return 'warning.main'
|
||||
if (level.id === 5) return 'primary.main'
|
||||
return 'divider'
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { Level4Header } from '../../level4/Level4Header'
|
||||
import { Level4Tabs } from '../../level4/Level4Tabs'
|
||||
import { Level4Summary } from '../../level4/Level4Summary'
|
||||
import { NerdModeIDE } from '../../misc/NerdModeIDE'
|
||||
import { Database } from '@/lib/database'
|
||||
import { seedDatabase } from '@/lib/seed-data'
|
||||
import type { User as UserType, AppConfiguration } from '@/lib/level-types'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import type { User as UserType } from '@/lib/level-types'
|
||||
import { useLevel4AppState } from './hooks/useLevel4AppState'
|
||||
|
||||
interface Level4Props {
|
||||
user: UserType
|
||||
@@ -19,94 +15,29 @@ interface Level4Props {
|
||||
}
|
||||
|
||||
export function Level4({ user, onLogout, onNavigate, onPreview }: Level4Props) {
|
||||
const [appConfig, setAppConfig] = useState<AppConfiguration | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [nerdMode, setNerdMode] = useKV<boolean>('level4-nerd-mode', false)
|
||||
|
||||
useEffect(() => {
|
||||
const loadConfig = async () => {
|
||||
await seedDatabase()
|
||||
|
||||
const config = await Database.getAppConfig()
|
||||
if (config) {
|
||||
setAppConfig(config)
|
||||
} else {
|
||||
const defaultConfig: AppConfiguration = {
|
||||
id: 'app_001',
|
||||
name: 'MetaBuilder App',
|
||||
schemas: [],
|
||||
workflows: [],
|
||||
luaScripts: [],
|
||||
pages: [],
|
||||
theme: {
|
||||
colors: {},
|
||||
fonts: {},
|
||||
},
|
||||
}
|
||||
await Database.setAppConfig(defaultConfig)
|
||||
setAppConfig(defaultConfig)
|
||||
}
|
||||
setIsLoading(false)
|
||||
}
|
||||
loadConfig()
|
||||
}, [])
|
||||
const {
|
||||
appConfig,
|
||||
handleExportConfig,
|
||||
handleImportConfig,
|
||||
handleLuaScriptsChange,
|
||||
handleSchemasChange,
|
||||
handleWorkflowsChange,
|
||||
isLoading,
|
||||
nerdMode,
|
||||
toggleNerdMode,
|
||||
} = useLevel4AppState()
|
||||
|
||||
if (isLoading || !appConfig) return null
|
||||
|
||||
const updateAppConfig = async (updates: Partial<AppConfiguration>) => {
|
||||
const newConfig = { ...appConfig, ...updates }
|
||||
setAppConfig(newConfig)
|
||||
await Database.setAppConfig(newConfig)
|
||||
}
|
||||
|
||||
const handleExportConfig = async () => {
|
||||
const dataStr = await Database.exportDatabase()
|
||||
const dataBlob = new Blob([dataStr], { type: 'application/json' })
|
||||
const url = URL.createObjectURL(dataBlob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = 'database-export.json'
|
||||
link.click()
|
||||
toast.success('Database exported')
|
||||
}
|
||||
|
||||
const handleImportConfig = () => {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'application/json'
|
||||
input.onchange = async (e) => {
|
||||
const file = (e.target as HTMLInputElement).files?.[0]
|
||||
if (!file) return
|
||||
|
||||
const text = await file.text()
|
||||
try {
|
||||
await Database.importDatabase(text)
|
||||
const newConfig = await Database.getAppConfig()
|
||||
if (newConfig) {
|
||||
setAppConfig(newConfig)
|
||||
}
|
||||
toast.success('Database imported successfully')
|
||||
} catch (error) {
|
||||
toast.error('Invalid database file')
|
||||
}
|
||||
}
|
||||
input.click()
|
||||
}
|
||||
|
||||
const handleToggleNerdMode = () => {
|
||||
setNerdMode(!nerdMode)
|
||||
toast.info(nerdMode ? 'Nerd Mode disabled' : 'Nerd Mode enabled')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-canvas">
|
||||
<Level4Header
|
||||
username={user.username}
|
||||
nerdMode={nerdMode || false}
|
||||
nerdMode={nerdMode}
|
||||
onNavigate={onNavigate}
|
||||
onPreview={onPreview}
|
||||
onLogout={onLogout}
|
||||
onToggleNerdMode={handleToggleNerdMode}
|
||||
onToggleNerdMode={toggleNerdMode}
|
||||
onExportConfig={handleExportConfig}
|
||||
onImportConfig={handleImportConfig}
|
||||
/>
|
||||
@@ -115,7 +46,7 @@ export function Level4({ user, onLogout, onNavigate, onPreview }: Level4Props) {
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold mb-2">Application Builder</h1>
|
||||
<p className="text-muted-foreground">
|
||||
{nerdMode
|
||||
{nerdMode
|
||||
? "Design your application declaratively. Define schemas, create workflows, and write Lua scripts."
|
||||
: "Build your application visually. Configure pages, users, and data models with simple forms."
|
||||
}
|
||||
@@ -124,25 +55,13 @@ export function Level4({ user, onLogout, onNavigate, onPreview }: Level4Props) {
|
||||
|
||||
<Level4Tabs
|
||||
appConfig={appConfig}
|
||||
nerdMode={nerdMode || false}
|
||||
onSchemasChange={async (schemas) => {
|
||||
const newConfig = { ...appConfig, schemas }
|
||||
setAppConfig(newConfig)
|
||||
await Database.setAppConfig(newConfig)
|
||||
}}
|
||||
onWorkflowsChange={async (workflows) => {
|
||||
const newConfig = { ...appConfig, workflows }
|
||||
setAppConfig(newConfig)
|
||||
await Database.setAppConfig(newConfig)
|
||||
}}
|
||||
onLuaScriptsChange={async (scripts) => {
|
||||
const newConfig = { ...appConfig, luaScripts: scripts }
|
||||
setAppConfig(newConfig)
|
||||
await Database.setAppConfig(newConfig)
|
||||
}}
|
||||
nerdMode={nerdMode}
|
||||
onSchemasChange={handleSchemasChange}
|
||||
onWorkflowsChange={handleWorkflowsChange}
|
||||
onLuaScriptsChange={handleLuaScriptsChange}
|
||||
/>
|
||||
|
||||
<Level4Summary appConfig={appConfig} nerdMode={nerdMode || false} />
|
||||
<Level4Summary appConfig={appConfig} nerdMode={nerdMode} />
|
||||
|
||||
{nerdMode && (
|
||||
<div className="fixed bottom-4 right-4 w-[calc(100%-2rem)] max-w-[1400px] h-[600px] z-50 shadow-2xl">
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
|
||||
import { Database } from '@/lib/database'
|
||||
import type { AppConfiguration } from '@/lib/level-types'
|
||||
import { seedDatabase } from '@/lib/seed-data'
|
||||
|
||||
type ConfigUpdater = (config: AppConfiguration) => AppConfiguration
|
||||
|
||||
const createDefaultConfig = (): AppConfiguration => ({
|
||||
id: 'app_001',
|
||||
name: 'MetaBuilder App',
|
||||
schemas: [],
|
||||
workflows: [],
|
||||
luaScripts: [],
|
||||
pages: [],
|
||||
theme: {
|
||||
colors: {},
|
||||
fonts: {},
|
||||
},
|
||||
})
|
||||
|
||||
const persistConfig = async (config: AppConfiguration, setConfig: (value: AppConfiguration) => void) => {
|
||||
setConfig(config)
|
||||
await Database.setAppConfig(config)
|
||||
}
|
||||
|
||||
export const useLevel4AppState = () => {
|
||||
const [appConfig, setAppConfig] = useState<AppConfiguration | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [nerdMode, setNerdMode] = useKV<boolean>('level4-nerd-mode', false)
|
||||
|
||||
useEffect(() => {
|
||||
const loadConfig = async () => {
|
||||
await seedDatabase()
|
||||
|
||||
const config = await Database.getAppConfig()
|
||||
if (config) {
|
||||
setAppConfig(config)
|
||||
} else {
|
||||
const defaultConfig = createDefaultConfig()
|
||||
await persistConfig(defaultConfig, setAppConfig)
|
||||
}
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
void loadConfig()
|
||||
}, [])
|
||||
|
||||
const updateConfig = useCallback(
|
||||
async (updater: ConfigUpdater) => {
|
||||
if (!appConfig) return
|
||||
|
||||
const updatedConfig = updater(appConfig)
|
||||
await persistConfig(updatedConfig, setAppConfig)
|
||||
},
|
||||
[appConfig]
|
||||
)
|
||||
|
||||
const handleExportConfig = useCallback(async () => {
|
||||
const dataStr = await Database.exportDatabase()
|
||||
const dataBlob = new Blob([dataStr], { type: 'application/json' })
|
||||
const url = URL.createObjectURL(dataBlob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = 'database-export.json'
|
||||
link.click()
|
||||
toast.success('Database exported')
|
||||
}, [])
|
||||
|
||||
const handleImportConfig = useCallback(() => {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'application/json'
|
||||
input.onchange = async (e) => {
|
||||
const file = (e.target as HTMLInputElement).files?.[0]
|
||||
if (!file) return
|
||||
|
||||
const text = await file.text()
|
||||
try {
|
||||
await Database.importDatabase(text)
|
||||
const newConfig = await Database.getAppConfig()
|
||||
if (newConfig) {
|
||||
await persistConfig(newConfig, setAppConfig)
|
||||
}
|
||||
toast.success('Database imported successfully')
|
||||
} catch (error) {
|
||||
toast.error('Invalid database file')
|
||||
}
|
||||
}
|
||||
input.click()
|
||||
}, [])
|
||||
|
||||
const toggleNerdMode = useCallback(() => {
|
||||
const nextValue = !nerdMode
|
||||
setNerdMode(nextValue)
|
||||
toast.info(nextValue ? 'Nerd Mode enabled' : 'Nerd Mode disabled')
|
||||
}, [nerdMode, setNerdMode])
|
||||
|
||||
const handleSchemasChange = useCallback(
|
||||
async (schemas: AppConfiguration['schemas']) => updateConfig((config) => ({ ...config, schemas })),
|
||||
[updateConfig]
|
||||
)
|
||||
|
||||
const handleWorkflowsChange = useCallback(
|
||||
async (workflows: AppConfiguration['workflows']) => updateConfig((config) => ({ ...config, workflows })),
|
||||
[updateConfig]
|
||||
)
|
||||
|
||||
const handleLuaScriptsChange = useCallback(
|
||||
async (luaScripts: AppConfiguration['luaScripts']) => updateConfig((config) => ({ ...config, luaScripts })),
|
||||
[updateConfig]
|
||||
)
|
||||
|
||||
return {
|
||||
appConfig,
|
||||
isLoading,
|
||||
nerdMode: nerdMode || false,
|
||||
handleExportConfig,
|
||||
handleImportConfig,
|
||||
toggleNerdMode,
|
||||
handleSchemasChange,
|
||||
handleWorkflowsChange,
|
||||
handleLuaScriptsChange,
|
||||
}
|
||||
}
|
||||
157
frontends/nextjs/src/types/dbal.d.ts
vendored
157
frontends/nextjs/src/types/dbal.d.ts
vendored
@@ -2,153 +2,14 @@
|
||||
* DBAL type stubs
|
||||
* These types are used when the full DBAL module is not available
|
||||
* The actual implementation lives in ../../dbal/development/src
|
||||
*
|
||||
* The declarations are split into focused modules to keep each file
|
||||
* under the large-file threshold and easier to maintain.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src' {
|
||||
export interface DBALConfig {
|
||||
mode?: 'development' | 'production'
|
||||
adapter?: string
|
||||
auth?: any
|
||||
database?: {
|
||||
url?: string
|
||||
}
|
||||
security?: {
|
||||
sandbox?: 'strict' | 'permissive' | 'disabled'
|
||||
enableAuditLog?: boolean
|
||||
}
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface DBALUser {
|
||||
id: string
|
||||
email: string
|
||||
name?: string
|
||||
username?: string
|
||||
level?: number
|
||||
role?: string
|
||||
tenantId?: string
|
||||
createdAt?: number | string | Date
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface ListResult<T> {
|
||||
data: T[]
|
||||
total?: number
|
||||
}
|
||||
|
||||
export interface UsersAPI {
|
||||
list(): Promise<ListResult<DBALUser>>
|
||||
create(data: Partial<DBALUser>): Promise<DBALUser>
|
||||
update(id: string, data: Partial<DBALUser>): Promise<DBALUser>
|
||||
delete(id: string): Promise<boolean>
|
||||
}
|
||||
|
||||
export class DBALClient {
|
||||
users: UsersAPI
|
||||
constructor(config: DBALConfig)
|
||||
query<T>(sql: string, params?: unknown[]): Promise<T[]>
|
||||
execute(sql: string, params?: unknown[]): Promise<void>
|
||||
capabilities(): Promise<Record<string, boolean>>
|
||||
}
|
||||
|
||||
export class DBALError extends Error {
|
||||
code: DBALErrorCode
|
||||
message: string
|
||||
constructor(message: string, code: DBALErrorCode)
|
||||
}
|
||||
|
||||
export enum DBALErrorCode {
|
||||
UNKNOWN = 'UNKNOWN',
|
||||
CONNECTION_ERROR = 'CONNECTION_ERROR',
|
||||
QUERY_ERROR = 'QUERY_ERROR',
|
||||
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@/dbal/development/src/core/types' {
|
||||
export interface User {
|
||||
id: string
|
||||
email: string
|
||||
name?: string
|
||||
level: number
|
||||
tenantId: string
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@/dbal/development/src/core/tenant-context' {
|
||||
export interface TenantContext {
|
||||
tenantId: string
|
||||
userId?: string
|
||||
}
|
||||
|
||||
export class InMemoryTenantManager {
|
||||
setCurrentTenant(tenantId: string): void
|
||||
getCurrentTenant(): string | null
|
||||
createTenant(id: string, metadata: Record<string, any>, ...args: any[]): Promise<void>
|
||||
getTenantContext(tenantId: string, userId?: string): Promise<TenantContext>
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@/dbal/development/src/core/kv-store' {
|
||||
import type { TenantContext } from '@/dbal/development/src/core/tenant-context'
|
||||
|
||||
export class InMemoryKVStore {
|
||||
get<T>(key: string, context?: TenantContext): Promise<T | null>
|
||||
set<T>(key: string, value: T, context?: TenantContext, ttl?: number): Promise<void>
|
||||
delete(key: string, context?: TenantContext): Promise<boolean>
|
||||
listAdd(key: string, items: any[], context?: TenantContext): Promise<void>
|
||||
listGet(key: string, context?: TenantContext, start?: number, end?: number): Promise<any[]>
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@/dbal/development/src/blob' {
|
||||
export interface BlobStorageConfig {
|
||||
type: 'filesystem' | 'memory' | 's3'
|
||||
basePath?: string
|
||||
}
|
||||
|
||||
export interface BlobMetadata {
|
||||
contentType?: string
|
||||
size?: number
|
||||
lastModified?: Date
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobListItem {
|
||||
key: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobListResult {
|
||||
items: BlobListItem[]
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobStorage {
|
||||
upload(key: string, data: Buffer | string, metadata?: BlobMetadata): Promise<string>
|
||||
download(key: string): Promise<Buffer>
|
||||
delete(key: string): Promise<void>
|
||||
exists(key: string): Promise<boolean>
|
||||
list(options?: { prefix?: string }): Promise<BlobListResult>
|
||||
getMetadata(key: string): Promise<BlobMetadata | null>
|
||||
}
|
||||
|
||||
export function createBlobStorage(config: BlobStorageConfig): BlobStorage
|
||||
}
|
||||
|
||||
declare module '@/dbal/development/src/blob/tenant-aware-storage' {
|
||||
import type { BlobStorage, BlobMetadata, BlobListResult } from '@/dbal/development/src/blob'
|
||||
import type { InMemoryTenantManager } from '@/dbal/development/src/core/tenant-context'
|
||||
|
||||
export class TenantAwareBlobStorage implements BlobStorage {
|
||||
constructor(storage: BlobStorage, tenantManager: InMemoryTenantManager, ...args: any[])
|
||||
upload(key: string, data: Buffer | string, metadata?: BlobMetadata): Promise<string>
|
||||
download(key: string): Promise<Buffer>
|
||||
delete(key: string): Promise<void>
|
||||
exists(key: string): Promise<boolean>
|
||||
list(options?: { prefix?: string }): Promise<BlobListResult>
|
||||
getMetadata(key: string): Promise<BlobMetadata | null>
|
||||
}
|
||||
}
|
||||
/// <reference path="./dbal/core-config.d.ts" />
|
||||
/// <reference path="./dbal/core-types.d.ts" />
|
||||
/// <reference path="./dbal/tenant-context.d.ts" />
|
||||
/// <reference path="./dbal/kv-store.d.ts" />
|
||||
/// <reference path="./dbal/blob.d.ts" />
|
||||
/// <reference path="./dbal/tenant-aware-blob.d.ts" />
|
||||
|
||||
36
frontends/nextjs/src/types/dbal/blob.d.ts
vendored
Normal file
36
frontends/nextjs/src/types/dbal/blob.d.ts
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src/blob' {
|
||||
export interface BlobStorageConfig {
|
||||
type: 'filesystem' | 'memory' | 's3'
|
||||
basePath?: string
|
||||
}
|
||||
|
||||
export interface BlobMetadata {
|
||||
contentType?: string
|
||||
size?: number
|
||||
lastModified?: Date
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobListItem {
|
||||
key: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobListResult {
|
||||
items: BlobListItem[]
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface BlobStorage {
|
||||
upload(key: string, data: Buffer | string, metadata?: BlobMetadata): Promise<string>
|
||||
download(key: string): Promise<Buffer>
|
||||
delete(key: string): Promise<void>
|
||||
exists(key: string): Promise<boolean>
|
||||
list(options?: { prefix?: string }): Promise<BlobListResult>
|
||||
getMetadata(key: string): Promise<BlobMetadata | null>
|
||||
}
|
||||
|
||||
export function createBlobStorage(config: BlobStorageConfig): BlobStorage
|
||||
}
|
||||
66
frontends/nextjs/src/types/dbal/core-config.d.ts
vendored
Normal file
66
frontends/nextjs/src/types/dbal/core-config.d.ts
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
/**
|
||||
* Root DBAL module declarations.
|
||||
* Split from the monolithic dbal.d.ts to keep each set of exports contained.
|
||||
*/
|
||||
declare module '@/dbal/development/src' {
|
||||
export interface DBALConfig {
|
||||
mode?: 'development' | 'production'
|
||||
adapter?: string
|
||||
auth?: any
|
||||
database?: {
|
||||
url?: string
|
||||
}
|
||||
security?: {
|
||||
sandbox?: 'strict' | 'permissive' | 'disabled'
|
||||
enableAuditLog?: boolean
|
||||
}
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface DBALUser {
|
||||
id: string
|
||||
email: string
|
||||
name?: string
|
||||
username?: string
|
||||
level?: number
|
||||
role?: string
|
||||
tenantId?: string
|
||||
createdAt?: number | string | Date
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface ListResult<T> {
|
||||
data: T[]
|
||||
total?: number
|
||||
}
|
||||
|
||||
export interface UsersAPI {
|
||||
list(): Promise<ListResult<DBALUser>>
|
||||
create(data: Partial<DBALUser>): Promise<DBALUser>
|
||||
update(id: string, data: Partial<DBALUser>): Promise<DBALUser>
|
||||
delete(id: string): Promise<boolean>
|
||||
}
|
||||
|
||||
export class DBALClient {
|
||||
users: UsersAPI
|
||||
constructor(config: DBALConfig)
|
||||
query<T>(sql: string, params?: unknown[]): Promise<T[]>
|
||||
execute(sql: string, params?: unknown[]): Promise<void>
|
||||
capabilities(): Promise<Record<string, boolean>>
|
||||
}
|
||||
|
||||
export class DBALError extends Error {
|
||||
code: DBALErrorCode
|
||||
message: string
|
||||
constructor(message: string, code: DBALErrorCode)
|
||||
}
|
||||
|
||||
export enum DBALErrorCode {
|
||||
UNKNOWN = 'UNKNOWN',
|
||||
CONNECTION_ERROR = 'CONNECTION_ERROR',
|
||||
QUERY_ERROR = 'QUERY_ERROR',
|
||||
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
||||
}
|
||||
}
|
||||
11
frontends/nextjs/src/types/dbal/core-types.d.ts
vendored
Normal file
11
frontends/nextjs/src/types/dbal/core-types.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src/core/types' {
|
||||
export interface User {
|
||||
id: string
|
||||
email: string
|
||||
name?: string
|
||||
level: number
|
||||
tenantId: string
|
||||
}
|
||||
}
|
||||
13
frontends/nextjs/src/types/dbal/kv-store.d.ts
vendored
Normal file
13
frontends/nextjs/src/types/dbal/kv-store.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src/core/kv-store' {
|
||||
import type { TenantContext } from '@/dbal/development/src/core/tenant-context'
|
||||
|
||||
export class InMemoryKVStore {
|
||||
get<T>(key: string, context?: TenantContext): Promise<T | null>
|
||||
set<T>(key: string, value: T, context?: TenantContext, ttl?: number): Promise<void>
|
||||
delete(key: string, context?: TenantContext): Promise<boolean>
|
||||
listAdd(key: string, items: any[], context?: TenantContext): Promise<void>
|
||||
listGet(key: string, context?: TenantContext, start?: number, end?: number): Promise<any[]>
|
||||
}
|
||||
}
|
||||
16
frontends/nextjs/src/types/dbal/tenant-aware-blob.d.ts
vendored
Normal file
16
frontends/nextjs/src/types/dbal/tenant-aware-blob.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src/blob/tenant-aware-storage' {
|
||||
import type { BlobStorage, BlobMetadata, BlobListResult } from '@/dbal/development/src/blob'
|
||||
import type { InMemoryTenantManager } from '@/dbal/development/src/core/tenant-context'
|
||||
|
||||
export class TenantAwareBlobStorage implements BlobStorage {
|
||||
constructor(storage: BlobStorage, tenantManager: InMemoryTenantManager, ...args: any[])
|
||||
upload(key: string, data: Buffer | string, metadata?: BlobMetadata): Promise<string>
|
||||
download(key: string): Promise<Buffer>
|
||||
delete(key: string): Promise<void>
|
||||
exists(key: string): Promise<boolean>
|
||||
list(options?: { prefix?: string }): Promise<BlobListResult>
|
||||
getMetadata(key: string): Promise<BlobMetadata | null>
|
||||
}
|
||||
}
|
||||
15
frontends/nextjs/src/types/dbal/tenant-context.d.ts
vendored
Normal file
15
frontends/nextjs/src/types/dbal/tenant-context.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
declare module '@/dbal/development/src/core/tenant-context' {
|
||||
export interface TenantContext {
|
||||
tenantId: string
|
||||
userId?: string
|
||||
}
|
||||
|
||||
export class InMemoryTenantManager {
|
||||
setCurrentTenant(tenantId: string): void
|
||||
getCurrentTenant(): string | null
|
||||
createTenant(id: string, metadata: Record<string, any>, ...args: any[]): Promise<void>
|
||||
getTenantContext(tenantId: string, userId?: string): Promise<TenantContext>
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,9 @@
|
||||
"out",
|
||||
"tmp"
|
||||
],
|
||||
"scanned": 1381,
|
||||
"overLimit": 106,
|
||||
"timestamp": "2025-12-27T15:33:16.258Z",
|
||||
"scanned": 1407,
|
||||
"overLimit": 100,
|
||||
"timestamp": "2025-12-27T15:45:04.923Z",
|
||||
"files": [
|
||||
{
|
||||
"path": "frontends/nextjs/src/lib/packages/core/package-catalog.ts",
|
||||
@@ -511,40 +511,11 @@
|
||||
"lines": 165,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "frontends/nextjs/src/app/levels/LevelsClient.tsx",
|
||||
"lines": 165,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "frontends/nextjs/src/components/rendering/Builder.tsx",
|
||||
"lines": 164,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "frontends/nextjs/src/components/molecules/form/Select.tsx",
|
||||
"lines": 161,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "tools/generation/generate-quality-summary.ts",
|
||||
"lines": 160,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "tools/analysis/code/list-large-typescript-files.ts",
|
||||
"lines": 159,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "frontends/nextjs/src/components/level/levels/Level4.tsx",
|
||||
"lines": 156,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
},
|
||||
{
|
||||
"path": "frontends/nextjs/src/types/dbal.d.ts",
|
||||
"lines": 155,
|
||||
"recommendation": "Split into focused modules; keep one primary lambda per file and extract helpers."
|
||||
}
|
||||
]
|
||||
],
|
||||
"outFile": "tools/analysis/code/reports/large-ts-files.json"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user