diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..521a9f7c0 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true diff --git a/dbal/development/src/adapters/acl-adapter/types.ts b/dbal/development/src/adapters/acl-adapter/types.ts index ea4cf1857..b87805ffd 100644 --- a/dbal/development/src/adapters/acl-adapter/types.ts +++ b/dbal/development/src/adapters/acl-adapter/types.ts @@ -3,7 +3,7 @@ import type { DBALAdapter } from '../adapter' export interface User { id: string username: string - role: 'user' | 'admin' | 'god' | 'supergod' + role: 'user' | 'admin' | 'god' | 'supergod' | 'public' | 'moderator' } export interface ACLRule { diff --git a/dbal/development/src/adapters/memory/index.ts b/dbal/development/src/adapters/memory/index.ts index 3595f87ed..3c5c9b91b 100644 --- a/dbal/development/src/adapters/memory/index.ts +++ b/dbal/development/src/adapters/memory/index.ts @@ -48,7 +48,11 @@ const applySort = ( if (!sort || Object.keys(sort).length === 0) { return records } - const [key, direction] = Object.entries(sort)[0] + const sortEntries = Object.entries(sort)[0] + if (sortEntries === undefined) { + return records + } + const [key, direction] = sortEntries return [...records].sort((left, right) => { const a = left[key] const b = right[key] diff --git a/dbal/development/src/core/foundation/types/auth/index.ts b/dbal/development/src/core/foundation/types/auth/index.ts index b3a1bf2d0..15d145153 100644 --- a/dbal/development/src/core/foundation/types/auth/index.ts +++ b/dbal/development/src/core/foundation/types/auth/index.ts @@ -15,6 +15,7 @@ export interface CreateSessionInput { } export interface UpdateSessionInput { + [key: string]: unknown userId?: string token?: string expiresAt?: bigint diff --git a/dbal/development/src/core/foundation/types/automation/index.ts b/dbal/development/src/core/foundation/types/automation/index.ts index bf7eeb55a..0ef3fe4d8 100644 --- a/dbal/development/src/core/foundation/types/automation/index.ts +++ b/dbal/development/src/core/foundation/types/automation/index.ts @@ -17,6 +17,7 @@ export interface CreateWorkflowInput { } export interface UpdateWorkflowInput { + [key: string]: unknown name?: string description?: string nodes?: string diff --git a/dbal/development/src/core/foundation/types/content/index.ts b/dbal/development/src/core/foundation/types/content/index.ts index d4849b414..dfc80eafa 100644 --- a/dbal/development/src/core/foundation/types/content/index.ts +++ b/dbal/development/src/core/foundation/types/content/index.ts @@ -25,6 +25,7 @@ export interface CreatePageInput { } export interface UpdatePageInput { + [key: string]: unknown tenantId?: string | null packageId?: string | null path?: string @@ -57,6 +58,7 @@ export interface CreateComponentNodeInput { } export interface UpdateComponentNodeInput { + [key: string]: unknown type?: string parentId?: string | null childIds?: string diff --git a/dbal/development/src/core/foundation/types/packages/index.ts b/dbal/development/src/core/foundation/types/packages/index.ts index 39d26015a..e3edcc4db 100644 --- a/dbal/development/src/core/foundation/types/packages/index.ts +++ b/dbal/development/src/core/foundation/types/packages/index.ts @@ -25,10 +25,12 @@ export interface PackageData { } export interface CreatePackageDataInput { + [key: string]: unknown packageId: string data: string } export interface UpdatePackageDataInput { + [key: string]: unknown data?: string } diff --git a/dbal/development/src/core/foundation/types/users/index.ts b/dbal/development/src/core/foundation/types/users/index.ts index 3a095e16b..fc32b1738 100644 --- a/dbal/development/src/core/foundation/types/users/index.ts +++ b/dbal/development/src/core/foundation/types/users/index.ts @@ -19,6 +19,7 @@ export interface CreateUserInput { } export interface UpdateUserInput { + [key: string]: unknown username?: string email?: string role?: UserRole diff --git a/frontends/nextjs/package.json b/frontends/nextjs/package.json index 501b8e7d7..f49f330cb 100644 --- a/frontends/nextjs/package.json +++ b/frontends/nextjs/package.json @@ -39,6 +39,7 @@ "@eslint/js": "^9.39.2", "@tanstack/react-query": "^5.90.16", "@testing-library/react": "^16.3.1", + "@types/better-sqlite3": "^7.6.12", "@types/node": "^25.0.3", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", diff --git a/frontends/nextjs/src/app/api/v1/[...slug]/route.ts b/frontends/nextjs/src/app/api/v1/[...slug]/route.ts index 58fa71e01..48853e2b2 100644 --- a/frontends/nextjs/src/app/api/v1/[...slug]/route.ts +++ b/frontends/nextjs/src/app/api/v1/[...slug]/route.ts @@ -54,7 +54,14 @@ async function handleRequest( const { route, operation, dbalOp } = context // 2. Get current user session (may be null for public routes) - const { user } = await getSessionUser() + const { user: rawUser } = await getSessionUser() + + // Type-safe user with required fields + const user = rawUser !== null ? { + id: String(rawUser.id ?? ''), + role: String(rawUser.role ?? 'public'), + tenantId: rawUser.tenantId !== undefined && rawUser.tenantId !== null ? String(rawUser.tenantId) : null, + } : null // 3. Validate package exists and user has required level const packageResult = validatePackageRoute(route.package, route.entity, user) diff --git a/frontends/nextjs/src/components/ErrorBoundary.tsx b/frontends/nextjs/src/components/ErrorBoundary.tsx index 9c5249d54..53e164ff5 100644 --- a/frontends/nextjs/src/components/ErrorBoundary.tsx +++ b/frontends/nextjs/src/components/ErrorBoundary.tsx @@ -32,7 +32,7 @@ export class ErrorBoundary extends Component { const route = LEVEL_ROUTES[targetLevel] ?? LEVEL_ROUTES[0] - router.push(route) + if (route !== undefined) { + router.push(route) + } } return { diff --git a/frontends/nextjs/src/hooks/index.ts b/frontends/nextjs/src/hooks/index.ts index 24417371c..5eab894e2 100644 --- a/frontends/nextjs/src/hooks/index.ts +++ b/frontends/nextjs/src/hooks/index.ts @@ -10,5 +10,5 @@ export { useFileTree } from './useFileTree' export type { WorkflowRun } from './useGitHubFetcher' export { useGitHubFetcher } from './useGitHubFetcher' export { useKV } from './useKV' -export { useLevelRouting } from './useLevelRouting' -export { useResolvedUser } from './useResolvedUser' +export { useLevelRouting } from './data/useLevelRouting' +export { useResolvedUser } from './data/useResolvedUser' diff --git a/frontends/nextjs/src/hooks/useGitHubFetcher.ts b/frontends/nextjs/src/hooks/useGitHubFetcher.ts index 4b5e687b4..f31f58eab 100644 --- a/frontends/nextjs/src/hooks/useGitHubFetcher.ts +++ b/frontends/nextjs/src/hooks/useGitHubFetcher.ts @@ -22,7 +22,8 @@ export function useGitHubFetcher() { setError(null) try { const { listWorkflowRuns } = await import('@/lib/github/workflows/listing/list-workflow-runs') - const workflowRuns = await listWorkflowRuns() + // TODO: Get owner/repo from environment or context + const workflowRuns = await listWorkflowRuns({ owner: 'owner', repo: 'repo' }) setRuns(workflowRuns) } catch (err) { setError(err as Error) diff --git a/frontends/nextjs/src/lib/config/prisma.ts b/frontends/nextjs/src/lib/config/prisma.ts index 3ae9ee0a3..de7c0a3c9 100644 --- a/frontends/nextjs/src/lib/config/prisma.ts +++ b/frontends/nextjs/src/lib/config/prisma.ts @@ -8,7 +8,7 @@ // Prisma client types are generated; when they resolve as error types in linting, // these assignments/calls are safe for runtime but look unsafe to the linter. import { PrismaClient } from '@prisma/client' -import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3' +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3' import Database from 'better-sqlite3' const globalForPrisma = globalThis as unknown as { @@ -40,7 +40,7 @@ const createIntegrationPrisma = (): PrismaClient => { if (globalForPrisma.prismaTestDb === undefined) { globalForPrisma.prismaTestDb = new Database(':memory:') } - const adapter = new PrismaBetterSQLite3(globalForPrisma.prismaTestDb) + const adapter = new PrismaBetterSqlite3(globalForPrisma.prismaTestDb) return new PrismaClient({ adapter }) } diff --git a/frontends/nextjs/src/lib/db/error-logs/crud/get-error-logs.ts b/frontends/nextjs/src/lib/db/error-logs/crud/get-error-logs.ts index 98ad8fbfe..58137c4c8 100644 --- a/frontends/nextjs/src/lib/db/error-logs/crud/get-error-logs.ts +++ b/frontends/nextjs/src/lib/db/error-logs/crud/get-error-logs.ts @@ -27,7 +27,7 @@ export async function getErrorLogs(options?: { const result = await adapter.list('ErrorLog', { filter: Object.keys(filter).length > 0 ? filter : undefined, - orderBy: { timestamp: 'desc' }, + orderBy: [{ timestamp: 'desc' }], take: options?.limit, }) diff --git a/frontends/nextjs/src/lib/db/error-logs/tests/get-error-logs.test.ts b/frontends/nextjs/src/lib/db/error-logs/tests/get-error-logs.test.ts index 51d66e9ba..117e753e2 100644 --- a/frontends/nextjs/src/lib/db/error-logs/tests/get-error-logs.test.ts +++ b/frontends/nextjs/src/lib/db/error-logs/tests/get-error-logs.test.ts @@ -96,7 +96,7 @@ describe('getErrorLogs', () => { expect(mockList).toHaveBeenCalledWith('ErrorLog', { filter: expectedFilter, orderBy: { timestamp: 'desc' }, - take: options?.limit, + take: options?.limit ?? undefined, }) expect(result).toHaveLength(dbData.length) diff --git a/frontends/nextjs/src/lib/db/functions/comments/crud/get-comments.ts b/frontends/nextjs/src/lib/db/functions/comments/crud/get-comments.ts index 3d558916c..bb4e0bfe1 100644 --- a/frontends/nextjs/src/lib/db/functions/comments/crud/get-comments.ts +++ b/frontends/nextjs/src/lib/db/functions/comments/crud/get-comments.ts @@ -12,7 +12,7 @@ import { prisma } from '@/lib/config/prisma' */ export const getComments = async (): Promise => { const comments = await prisma.comment.findMany() - return comments.map(c => ({ + return comments.map((c: Record) => ({ id: c.id, userId: c.userId, entityType: c.entityType, diff --git a/frontends/nextjs/src/lib/github/resolve-github-repo.ts b/frontends/nextjs/src/lib/github/resolve-github-repo.ts index 746a57051..896464500 100644 --- a/frontends/nextjs/src/lib/github/resolve-github-repo.ts +++ b/frontends/nextjs/src/lib/github/resolve-github-repo.ts @@ -11,15 +11,15 @@ export function resolveGitHubRepo(params: URLSearchParams | string): GitHubRepo if (typeof params === 'string') { const [owner, repo] = params.split('/') return { - owner: owner !== '' ? owner : '', - repo: repo !== undefined && repo !== '' ? repo : '' + owner: owner ?? '', + repo: repo ?? '' } } const ownerParam = params.get('owner') const repoParam = params.get('repo') return { - owner: ownerParam !== null && ownerParam !== '' ? ownerParam : '', - repo: repoParam !== null && repoParam !== '' ? repoParam : '', + owner: ownerParam ?? '', + repo: repoParam ?? '', } } diff --git a/frontends/nextjs/src/lib/packages/json/render-json-component.tsx b/frontends/nextjs/src/lib/packages/json/render-json-component.tsx index 319541c81..d37ea82fd 100644 --- a/frontends/nextjs/src/lib/packages/json/render-json-component.tsx +++ b/frontends/nextjs/src/lib/packages/json/render-json-component.tsx @@ -258,11 +258,11 @@ function evaluateSimpleExpression(expr: string, context: RenderContext): JsonVal // Handle ternary operator if (part.includes('?')) { const [condition, branches] = part.split('?') - if (condition.length === 0 || branches === undefined || branches.length === 0) { + if (condition === undefined || condition.length === 0 || branches === undefined || branches.length === 0) { return value } const [trueBranch, falseBranch] = branches.split(':') - if (trueBranch.length === 0 || falseBranch === undefined || falseBranch.length === 0) { + if (trueBranch === undefined || trueBranch.length === 0 || falseBranch === undefined || falseBranch.length === 0) { return value } const conditionValue = evaluateSimpleExpression(condition.trim(), context) diff --git a/frontends/nextjs/src/lib/ui-pages/load-page-from-db.ts b/frontends/nextjs/src/lib/ui-pages/load-page-from-db.ts index bd15cf41f..636fa3f5a 100644 --- a/frontends/nextjs/src/lib/ui-pages/load-page-from-db.ts +++ b/frontends/nextjs/src/lib/ui-pages/load-page-from-db.ts @@ -29,7 +29,7 @@ export async function loadPageFromDb(path: string, tenantId?: string): Promise