Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .biomeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.git*
.vercel/
.trae/
dist/
node_modules/
temp/

bun.lock

*.db
*.wal
**/*.d.ts
32 changes: 0 additions & 32 deletions backend/eslint.config.ts

This file was deleted.

10 changes: 1 addition & 9 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,7 @@
"@types/bun": "catalog:",
"@types/node": "catalog:",
"@types/oauth": "^0.9.6",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"bun-types": "catalog:",
"eslint": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-plugin-no-relative-import-paths": "catalog:",
"eslint-plugin-prettier": "catalog:",
"prettier": "catalog:",
"typescript": "catalog:",
"typescript-eslint": "catalog:"
"typescript": "catalog:"
}
}
7 changes: 4 additions & 3 deletions backend/src/api/project/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
ColumnNameSchema,
GetProjectByIdResponse,
PaginationQuery,
type Project,
ProjectParams,
ProjectResponseSchema,
ReplaceOperationSchema,
type Project,
} from '@backend/api/project/schemas'
import { databasePlugin } from '@backend/plugins/database'
import { errorHandlerPlugin } from '@backend/plugins/error-handler'
Expand All @@ -17,7 +17,8 @@ import { TrimWhitespaceService } from '@backend/services/trim-whitespace.service
import { UppercaseConversionService } from '@backend/services/uppercase-conversion.service'
import { ApiErrorHandler } from '@backend/types/error-handler'
import { ApiErrors } from '@backend/types/error-schemas'
import { enhanceSchemaWithTypes, type DuckDBTablePragma } from '@backend/utils/duckdb-types'
import { type DuckDBTablePragma, enhanceSchemaWithTypes } from '@backend/utils/duckdb-types'
import type { DuckDBResultReader } from '@duckdb/node-api'
import cors from '@elysiajs/cors'
import { Elysia, t } from 'elysia'

Expand Down Expand Up @@ -407,7 +408,7 @@ export const projectRoutes = new Elysia({ prefix: '/api/project' })
// DuckDB's read_json_auto will handle the parsing

// Check if a table with the same project ID already exists
let tableExistsReader
let tableExistsReader: DuckDBResultReader
try {
tableExistsReader = await db().runAndReadAll(
`SELECT 1 FROM duckdb_tables() WHERE table_name = 'project_${projectId}'`,
Expand Down
4 changes: 2 additions & 2 deletions backend/src/plugins/database.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api'
import { Elysia } from 'elysia'
import path from 'node:path'
import { type DuckDBConnection, DuckDBInstance } from '@duckdb/node-api'
import { Elysia } from 'elysia'

let connection: DuckDBConnection | null = null
let instance: DuckDBInstance | null = null
Expand Down
2 changes: 1 addition & 1 deletion backend/src/services/commons-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class CommonsUploadService {
lastError = error as Error

if (attempt < retries) {
await this.sleep(this.retryDelay * Math.pow(2, attempt))
await this.sleep(this.retryDelay * 2 ** attempt)
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions backend/src/services/constraint-validation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export class ConstraintValidationService {
}

const numericValue = typeof value === 'number' ? value : parseFloat(value)
if (isNaN(numericValue)) {
if (Number.isNaN(numericValue)) {
return {
constraintType: 'range_constraint',
message: `Value "${value}" is not a valid number for range constraint`,
Expand Down Expand Up @@ -437,10 +437,11 @@ export class ConstraintValidationService {
}
break

case 'single value constraint':
case 'single value constraint': {
const violation = this.validateSingleValueConstraint(values, constraint, propertyId)
if (violation) violations.push(violation)
break
}

default:
// For unsupported constraint types, add a warning
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { basename } from 'node:path'
import { readFromFilepath, readFromUrl } from '@backend/services/file-processor/file-reader'
import type { FileInput } from '@backend/services/file-processor/types'
import { basename } from 'node:path'

export const extractFileBuffer = async (
uploadFile: FileInput,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/services/file-processor/metadata-builder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { extname } from 'node:path'
import { calculateFileHash } from '@backend/services/file-processor/hash-calculator'
import { extractImageMetadata } from '@backend/services/file-processor/image-extractor'
import { detectMimeType } from '@backend/services/file-processor/mime-detector'
import type { FileInput, FileMetadata } from '@backend/services/file-processor/types'
import { extname } from 'node:path'

export const buildFileMetadata = async (
buffer: ArrayBuffer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { basename } from 'node:path'
import { processFile } from '@backend/services/file-processor/processor'
import type {
FileInput,
FileValidationOptions,
ProcessedFile,
} from '@backend/services/file-processor/types'
import { basename } from 'node:path'

export const processMultipleFiles = async (
uploadFiles: FileInput[],
Expand Down
2 changes: 1 addition & 1 deletion backend/src/services/wikibase-clients.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type CSRFTokenResponse, InstanceId, OAuthCredentials } from '@backend/api/wikibase/schemas'
import type { CSRFTokenResponse, InstanceId, OAuthCredentials } from '@backend/api/wikibase/schemas'
import { MediaWikiApiService } from '@backend/services/mediawiki-api.service'
import OAuth from 'oauth'

Expand Down
38 changes: 19 additions & 19 deletions backend/src/types/error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class ApiErrorHandler {
message: string = 'Validation failed',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('VALIDATION', message, details)
return ApiErrorHandler.createErrorWithData('VALIDATION', message, details)
}

/**
Expand All @@ -21,7 +21,7 @@ export class ApiErrorHandler {
message: string = 'Validation failed',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('VALIDATION', message, details)
return ApiErrorHandler.createErrorWithData('VALIDATION', message, details)
}

/**
Expand All @@ -31,7 +31,7 @@ export class ApiErrorHandler {
const message = identifier
? `${resource} with identifier '${identifier}' not found`
: `${resource} not found`
return this.createErrorWithData('NOT_FOUND', message)
return ApiErrorHandler.createErrorWithData('NOT_FOUND', message)
}

/**
Expand All @@ -41,14 +41,14 @@ export class ApiErrorHandler {
const message = identifier
? `${resource} with identifier '${identifier}' not found`
: `${resource} not found`
return this.createErrorWithData('NOT_FOUND', message, [])
return ApiErrorHandler.createErrorWithData('NOT_FOUND', message, [])
}

/**
* Create a missing file path error response with data array
*/
static missingFilePathError(message: string = 'File path is required'): ApiErrors {
return this.createErrorWithData('MISSING_FILE_PATH', message, [])
return ApiErrorHandler.createErrorWithData('MISSING_FILE_PATH', message, [])
}

/**
Expand All @@ -57,14 +57,14 @@ export class ApiErrorHandler {
static fileNotFoundError(filePath?: string): ApiErrors {
const message = 'File not found'
const details = filePath ? [filePath] : []
return this.createErrorWithData('FILE_NOT_FOUND', message, details)
return ApiErrorHandler.createErrorWithData('FILE_NOT_FOUND', message, details)
}

/**
* Create a table already exists error response with data array
*/
static tableExistsErrorWithData(tableName: string): ApiErrors {
return this.createErrorWithData(
return ApiErrorHandler.createErrorWithData(
'TABLE_ALREADY_EXISTS',
`Table with name '${tableName}' already exists`,
)
Expand All @@ -77,7 +77,7 @@ export class ApiErrorHandler {
message: string = 'An error occurred while processing the request',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('INTERNAL_SERVER_ERROR', message, details)
return ApiErrorHandler.createErrorWithData('INTERNAL_SERVER_ERROR', message, details)
}

/**
Expand All @@ -87,7 +87,7 @@ export class ApiErrorHandler {
message: string = 'Database error occurred',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('DATABASE_ERROR', message, details)
return ApiErrorHandler.createErrorWithData('DATABASE_ERROR', message, details)
}

/**
Expand All @@ -97,7 +97,7 @@ export class ApiErrorHandler {
message: string = 'Database error occurred',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('DATABASE_ERROR', message, details)
return ApiErrorHandler.createErrorWithData('DATABASE_ERROR', message, details)
}

/**
Expand All @@ -108,7 +108,7 @@ export class ApiErrorHandler {
message: string,
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData(type, message, details)
return ApiErrorHandler.createErrorWithData(type, message, details)
}

/**
Expand All @@ -118,7 +118,7 @@ export class ApiErrorHandler {
message: string = 'Failed to create project',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('PROJECT_CREATION_FAILED', message, details)
return ApiErrorHandler.createErrorWithData('PROJECT_CREATION_FAILED', message, details)
}

/**
Expand All @@ -128,7 +128,7 @@ export class ApiErrorHandler {
message: string = 'Failed to create project',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('PROJECT_CREATION_FAILED', message, details)
return ApiErrorHandler.createErrorWithData('PROJECT_CREATION_FAILED', message, details)
}

/**
Expand All @@ -138,7 +138,7 @@ export class ApiErrorHandler {
message: string = 'Failed to import data',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('DATA_IMPORT_FAILED', message, details)
return ApiErrorHandler.createErrorWithData('DATA_IMPORT_FAILED', message, details)
}

/**
Expand All @@ -148,7 +148,7 @@ export class ApiErrorHandler {
message: string = 'Failed to import data',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('DATA_IMPORT_FAILED', message, details)
return ApiErrorHandler.createErrorWithData('DATA_IMPORT_FAILED', message, details)
}

/**
Expand All @@ -158,7 +158,7 @@ export class ApiErrorHandler {
message: string = 'Invalid JSON format',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('INVALID_JSON', message, details)
return ApiErrorHandler.createErrorWithData('INVALID_JSON', message, details)
}

/**
Expand All @@ -168,7 +168,7 @@ export class ApiErrorHandler {
message: string = 'Invalid JSON format',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('INVALID_JSON', message, details)
return ApiErrorHandler.createErrorWithData('INVALID_JSON', message, details)
}

/**
Expand All @@ -178,14 +178,14 @@ export class ApiErrorHandler {
message: string = 'Internal server error',
details: unknown[] = [],
): ApiErrors {
return this.createErrorWithData('INTERNAL_SERVER_ERROR', message, details)
return ApiErrorHandler.createErrorWithData('INTERNAL_SERVER_ERROR', message, details)
}

/**
* Create a table already exists error response
*/
static tableExistsError(tableName: string): ApiErrors {
return this.createErrorWithData(
return ApiErrorHandler.createErrorWithData(
'TABLE_ALREADY_EXISTS',
`Table with name '${tableName}' already exists`,
)
Expand Down
2 changes: 1 addition & 1 deletion backend/src/utils/wikibase-error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export class WikibaseErrorHandler {

// Calculate delay for next attempt
const delay = Math.min(
this.retryConfig.baseDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt - 1),
this.retryConfig.baseDelay * this.retryConfig.backoffMultiplier ** (attempt - 1),
this.retryConfig.maxDelay,
)

Expand Down
2 changes: 1 addition & 1 deletion backend/tests/api/_meta_projects.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { metaProjectsRoutes } from '@backend/api/_meta_projects'
import { closeDb, databasePlugin, getDb, initializeDb } from '@backend/plugins/database'
import { treaty } from '@elysiajs/eden'
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { Elysia } from 'elysia'

const TEST_PROJECT_ID = Bun.randomUUIDv7()
Expand Down
4 changes: 2 additions & 2 deletions backend/tests/api/project/import-file.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { readdir } from 'node:fs/promises'
import { projectRoutes } from '@backend/api/project'
import { closeDb, getDb, initializeDb } from '@backend/plugins/database'
import { treaty } from '@elysiajs/eden'
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { Elysia } from 'elysia'
import { readdir } from 'node:fs/promises'

const createTestApi = () => {
return treaty(new Elysia().use(projectRoutes)).api
Expand Down
6 changes: 4 additions & 2 deletions backend/tests/api/project/import.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { projectRoutes } from '@backend/api/project'
import { closeDb, getDb, initializeDb } from '@backend/plugins/database'
import { treaty } from '@elysiajs/eden'
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { Elysia } from 'elysia'

const createTestApi = () => {
Expand Down Expand Up @@ -82,7 +82,9 @@ describe('POST /project/:projectId/import', () => {
code: 'INTERNAL_SERVER_ERROR',
message: 'An error occurred while importing the project',
details: [
expect.stringContaining('Invalid Input Error: Malformed JSON in file "./temp-invalid-json-file.json", at byte 1 in record/value 2: invalid literal.'),
expect.stringContaining(
'Invalid Input Error: Malformed JSON in file "./temp-invalid-json-file.json", at byte 1 in record/value 2: invalid literal.',
),
],
},
])
Expand Down
4 changes: 2 additions & 2 deletions backend/tests/api/project/lowercase.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { tmpdir } from 'node:os'
import { projectRoutes } from '@backend/api/project'
import { closeDb, initializeDb } from '@backend/plugins/database'
import { treaty } from '@elysiajs/eden'
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { Elysia } from 'elysia'
import { tmpdir } from 'node:os'

interface TestData {
name: string
Expand Down
Loading