Skip to content

Conversation

@DaxServer
Copy link
Owner

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Sep 13, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added endpoint to fetch and cache Wikibase properties.
    • API docs now powered by OpenAPI and available at /docs.
  • Changes
    • Error/validation responses simplified: no data field; returned as arrays of errors.
    • Project API: default pagination limit set to 25.
    • Wikibase property search: simplified response; removed datatype filter.
    • Removed real-time property validation endpoint.
  • Refactor
    • Migrated validation to Zod; unified project schemas.
  • Documentation
    • Updated references to schema file names.
  • Chores
    • Upgraded dependencies and engine versions.

Walkthrough

Migrates backend validation from Elysia t to Zod, consolidates project schemas into a new module, revises error payload shapes, introduces a Wikibase client/registry and a new properties fetch endpoint, adjusts MediaWiki types and requests, adds a DB table, updates API docs plugin, aligns tests and frontend imports with new schemas, and bumps several dependencies.

Changes

Cohort / File(s) Summary
Docs path updates
/.kiro/steering/code-conventions.md, /.kiro/steering/structure.md, /guidelines/reference/TESTING.md
Update references from _schemas.ts to schemas.ts.
Backend dependency/config updates
/backend/package.json, /backend/src/index.ts, /package.json
Switch to catalog: deps; replace Swagger with OpenAPI plugin; upgrade Elysia/eden, add cors/openapi/zod; bump Bun/ESLint.
Project API schema consolidation (Zod)
/backend/src/api/project/schemas.ts, /backend/src/api/project/_schemas.ts, /backend/src/api/project/project.create.ts, /backend/src/api/project/project.delete.ts, /backend/src/api/project/project.get-all.ts, /backend/src/api/project/project.get.ts, /backend/src/api/project/index.ts, /backend/src/api/project/project.import-file.ts, /backend/src/api/project/import.ts
Add centralized Zod schemas module; remove legacy t-based per-endpoint schemas; update routes to use new types; minor param/default changes; adjust import-file schemas; delete legacy files.
Meta projects Zod migration
/backend/src/api/_meta_projects.ts
Convert runtime schemas and types from t to z; update response typing and data assembly.
Wikibase API: schemas, routes, services
/backend/src/api/wikibase/schemas.ts, /backend/src/api/wikibase/entities.ts, /backend/src/services/wikibase.service.ts, /backend/src/services/wikibase-clients.ts (new), /backend/src/services/mediawiki-api.service.ts, /backend/src/types/mediawiki-api.ts, /backend/src/types/wikibase-api.ts, /backend/src/types/wikibase-schema.ts
Migrate to Zod; expand result shapes; standardize params; add Wikibase client registry; add POST /:instanceId/properties/fetch; adjust search signatures and results; update MediaWiki types and request method.
Database init
/backend/src/plugins/database.ts
Add wikibase_properties table creation.
Error shape changes (Zod and handlers)
/backend/src/plugins/error-handler.ts, /backend/src/types/error-handler.ts, /backend/src/types/error-schemas.ts
Remove top-level data field; simplify validation error payloads to arrays; migrate error schemas to Zod.
Backend utils import fix
/backend/src/utils/duckdb-types.ts
Update import path to new project schemas module.
Backend tests alignment
/backend/tests/api/project/*, /backend/tests/api/wikibase/entities.test.ts, /backend/tests/error-handler.test.ts
Update imports to schemas.ts; adjust assertions for new error shapes; minor expectation tweaks.
Frontend deps and type/import updates
/frontend/package.json, /frontend/src/features/data-processing/composables/.../useColumnGeneration.test.ts, /frontend/src/features/data-processing/composables/useColumnGeneration.ts, /frontend/src/features/project-management/stores/project-list.store.ts, /frontend/src/features/project-management/stores/project.store.ts, /frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts
Bump dev deps; switch imports to new backend schemas; remove unused type imports.
Frontend logic tweaks for new errors
/frontend/src/features/project-management/composables/useProjectCreationComposable.ts, /frontend/src/features/wikibase-schema/composables/useSchemaApi.ts, /frontend/src/features/wikibase-schema/stores/schema.store.ts, /frontend/src/shared/types/client-errors.ts
Remove data field from client error shape; adjust error handling; remove NOT_FOUND guard in createSchema; clean up type imports.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant API as API Route<br/>POST /wikibase/:instanceId/properties/fetch
  participant S as WikibaseService
  participant R as WikibaseClient Registry
  participant MW as MediaWiki API
  participant DB as DuckDB

  rect rgba(230,245,255,0.6)
    note over API,S: New properties fetch flow
    C->>API: Request
    API->>S: fetchAllProperties(instanceId, DB)
    S->>R: getClient(instanceId)
    alt client exists
      R-->>S: MediaWikiApiService
    else no client
      R-->>S: Error (no client)
      S-->>API: Throw
      API-->>C: 500/404 error
    end
    loop Pages until no apcontinue
      S->>MW: allpages query (namespace=120, continue token)
      MW-->>S: Batch of properties
      S->>DB: INSERT ... ON CONFLICT DO NOTHING
    end
    S-->>API: { total, inserted }
    API-->>C: 200 { data: { total, inserted } }
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive I cannot evaluate the PR description because no pull request body text was provided in the supplied context, so it is impossible to determine whether the description is related or sufficiently informative about the changeset. Without the PR description I cannot judge whether it documents key goals, breaking changes, or migration guidance. Please provide or paste the PR description so I can complete this check. Add the PR description summarizing objectives and notable changes (e.g., upgrade to Elysia 1.4, migrate runtime schemas to Zod, API error-shape changes, and test updates) and I will re-run the description check to give a definitive pass/fail result.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feat: update Elysia 1.4" succinctly states the primary intent—upgrading to Elysia 1.4—which is reflected in package and config changes in the diff. The changeset also includes large schema migrations to Zod and API surface alterations that the title does not enumerate. As a short, conventional-commit style title it is relevant, clear, and acceptable for quick history scanning.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elysia-1.4

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 22

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
frontend/src/features/project-management/stores/project-list.store.ts (1)

17-21: Fix type error: pass the full error to showError instead of error.value.
showError expects ExtendedError, but apiError.value is now a union and not assignable. Pass apiError directly in both places.

Apply this diff:

-    if (apiError) {
-      showError(apiError.value)
+    if (apiError) {
+      showError(apiError)
       ...
-    if (apiError?.value) {
-      showError(apiError.value)
+    if (apiError?.value) {
+      showError(apiError)
       isLoading.value = false
       return
     }

Also applies to: 31-34

backend/src/api/project/index.ts (2)

94-104: Ensure temp directory exists before writing

Bun.write may fail if ./temp is missing. Create it once before writing.

-      const fileBuffer = await file.arrayBuffer()
+      // Ensure temp directory exists
+      await Bun.$`mkdir -p ./temp`
+      const fileBuffer = await file.arrayBuffer()

127-141: Leak risk on “table already exists” branch

cleanupProject is commented out here; on conflict you leave a project row and temp file behind.

-      if (tableExistsReader.getRows().length > 0) {
-        // await cleanupProject(db, project.id, tempFilePath)
+      if (tableExistsReader.getRows().length > 0) {
+        await cleanupProject(db, project.id, tempFilePath)
         return status(
           500,
           ApiErrorHandler.dataImportErrorWithData(
             `Table with name 'project_${project.id}' already exists`,
           ),
         )
backend/src/api/project/project.wikibase.ts (1)

217-223: Harden schema parsing with Zod validation

Gracefully validate persisted JSON and fall back to blank only on failure.

-const parseSchemaField = (schema: unknown) => {
-  try {
-    return JSON.parse(schema as string) as ItemSchema
-  } catch {
-    return blankSchema
-  }
-}
+const parseSchemaField = (schema: unknown): ItemSchema => {
+  try {
+    const raw = typeof schema === 'string' ? JSON.parse(schema) : schema
+    const parsed = ItemSchemaMapping.safeParse(raw)
+    return parsed.success ? parsed.data : blankSchema
+  } catch {
+    return blankSchema
+  }
+}
🧹 Nitpick comments (37)
.kiro/steering/code-conventions.md (1)

156-156: Clarify schema tooling and import path.

Specify Zod and the alias to remove ambiguity.

- Define schemas in `schemas.ts` files
+ Define Zod schemas in `schemas.ts` files; import via `@backend/api/<domain>/schemas`.
.kiro/steering/structure.md (1)

51-51: Name the validator to match the codebase.

Call out Zod explicitly for consistency with the migration.

- Schema definitions in `schemas.ts` files
+ Zod schema definitions in `schemas.ts` files
backend/src/plugins/database.ts (1)

43-50: Add uniqueness/indexes for queryability and integrity.

id is PK (good). Consider enforcing uniqueness on pageid and indexing title to speed lookups.

     CREATE TABLE IF NOT EXISTS wikibase_properties (
       id TEXT PRIMARY KEY,
       title TEXT NOT NULL,
       pageid INTEGER NOT NULL,
       namespace INTEGER NOT NULL DEFAULT 120,
       created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
       updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
     );
+    CREATE UNIQUE INDEX IF NOT EXISTS wikibase_properties_pageid_uq
+      ON wikibase_properties(pageid);
+    CREATE INDEX IF NOT EXISTS wikibase_properties_title_idx
+      ON wikibase_properties(title);
package.json (1)

23-25: Deps bump looks good; verify Zod v4 and Bun engine compatibility across the repo.

  • Zod 4 introduces a default export in many setups; ensure all imports consistently use either import z from 'zod' or import { z } from 'zod' project-wide.
  • Confirm Bun >=1.2.21 in CI and containers.
  • Minor: scripts already use bun run, good. Consider removing duplicate tsc alias to avoid drift.

Would you like me to scan the repo for mixed Zod import styles and generate a patch?

Also applies to: 31-32, 34-34, 40-40, 53-53

backend/tests/api/project/project.get.test.ts (1)

156-166: Make the 422 assertion resilient; avoid hard-coding the UUID regex string.

Matching the entire pattern string is brittle across validator updates. Assert key fields and use partial matching.

Apply:

-    expect(error).toHaveProperty('value', [
-      {
-        code: 'invalid_format',
-        format: 'uuid',
-        message: 'Invalid UUID',
-        origin: 'string',
-        path: ['projectId'],
-        pattern:
-          '/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/',
-      },
-    ])
+    expect(error?.value).toEqual(
+      expect.arrayContaining([
+        expect.objectContaining({
+          code: 'invalid_format',
+          format: 'uuid',
+          message: expect.stringContaining('Invalid'),
+          origin: 'string',
+          path: ['projectId'],
+        }),
+      ]),
+    )

Also, consider normalizing error envelopes so 404 and 422 share the same outer shape.

backend/tests/api/project/project.delete.test.ts (1)

74-84: Relax the 422 UUID assertion; don’t assert full regex literal.

Mirror the approach from the GET test to reduce brittleness.

Apply:

-    expect(error).toHaveProperty('value', [
-      {
-        message: 'Invalid UUID',
-        code: 'invalid_format',
-        origin: 'string',
-        format: 'uuid',
-        path: ['projectId'],
-        pattern:
-          '/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/',
-      },
-    ])
+    expect(error?.value).toEqual(
+      expect.arrayContaining([
+        expect.objectContaining({
+          code: 'invalid_format',
+          format: 'uuid',
+          origin: 'string',
+          path: ['projectId'],
+          message: expect.stringContaining('Invalid'),
+        }),
+      ]),
+    )
backend/src/api/_meta_projects.ts (3)

8-25: Name the schema and type distinctly to avoid shadowing.

Use MetaProjectSchema for the Zod object and MetaProject for the inferred type to improve clarity.

Apply:

-const MetaProject = z.object({
+const MetaProjectSchema = z.object({
   id: z.string(),
   name: z.string(),
   schema_for: z.union([z.string(), z.null()]),
   schema: z.any(),
   created_at: z.string(),
   updated_at: z.string(),
   wikibase_schema: z.array(
     z.object({
       id: z.string(),
       wikibase: z.string(),
       name: z.string(),
       created_at: z.string(),
       updated_at: z.string(),
     }),
   ),
 })
-type MetaProject = z.infer<typeof MetaProject>
+type MetaProject = z.infer<typeof MetaProjectSchema>

67-75: Safeguard JSON.parse to prevent 500s on malformed rows.

A single bad row will throw. Wrap parse in try/catch.

Apply:

-      const data = reader.getRowObjectsJson().map((row) => {
+      const data = reader.getRowObjectsJson().map((row) => {
         const newRow: Record<string, unknown> = { ...row }
         jsonColumns.forEach((column) => {
           if (newRow[column] && typeof newRow[column] === 'string') {
-            newRow[column] = JSON.parse(newRow[column] as string)
+            try {
+              newRow[column] = JSON.parse(newRow[column] as string)
+            } catch {
+              // keep original string if not valid JSON
+            }
           }
         })
-        return newRow as MetaProject
+        return newRow as MetaProject
       })

If you adopt the naming change above, also replace the cast with as MetaProject accordingly.


81-83: Response schema uses Zod — ensure OpenAPI generation supports it.

If @elysiajs/openapi isn’t configured for Zod, switch to the project-standard adapter or generate OpenAPI via the Zod plugin.

Optionally export MetaProjectSchema and reuse it in consumers to avoid drift.

backend/src/types/wikibase-schema.ts (2)

9-14: Prefer z.enum for ranks (clearer and marginally faster).

Functionally equivalent but terser and intent-revealing.

-export const StatementRank = z.union([
-  z.literal('preferred'),
-  z.literal('normal'),
-  z.literal('deprecated'),
-])
+export const StatementRank = z.enum(['preferred', 'normal', 'deprecated'])

16-28: Consider z.enum (and verify completeness of data types you intend to support).

z.enum improves readability. Also, confirm whether you need additional Wikibase types (e.g., geo-shape, tabular-data, math, musical-notation, lexeme variants). If you only support a subset, add a comment stating so.

-export const WikibaseDataType = z.union([
-  z.literal('string'),
-  z.literal('wikibase-item'),
-  z.literal('wikibase-property'),
-  z.literal('quantity'),
-  z.literal('time'),
-  z.literal('globe-coordinate'),
-  z.literal('url'),
-  z.literal('external-id'),
-  z.literal('monolingualtext'),
-  z.literal('commonsMedia'),
-])
+export const WikibaseDataType = z.enum([
+  'string',
+  'wikibase-item',
+  'wikibase-property',
+  'quantity',
+  'time',
+  'globe-coordinate',
+  'url',
+  'external-id',
+  'monolingualtext',
+  'commonsMedia',
+])
backend/src/types/error-schemas.ts (2)

6-20: Optional: convert union of literals to z.enum for error codes.

Cleaner and simpler to extend.

-export const ErrorCodeSchema = z.union([
-  z.literal('VALIDATION'),
-  z.literal('MISSING_FILE_PATH'),
-  z.literal('MISSING_FILE'),
-  z.literal('INVALID_FILE_TYPE'),
-  z.literal('EMPTY_FILE'),
-  z.literal('FILE_NOT_FOUND'),
-  z.literal('TABLE_ALREADY_EXISTS'),
-  z.literal('INTERNAL_SERVER_ERROR'),
-  z.literal('DATABASE_ERROR'),
-  z.literal('PROJECT_CREATION_FAILED'),
-  z.literal('DATA_IMPORT_FAILED'),
-  z.literal('INVALID_JSON'),
-  z.literal('NOT_FOUND'),
-])
+export const ErrorCodeSchema = z.enum([
+  'VALIDATION',
+  'MISSING_FILE_PATH',
+  'MISSING_FILE',
+  'INVALID_FILE_TYPE',
+  'EMPTY_FILE',
+  'FILE_NOT_FOUND',
+  'TABLE_ALREADY_EXISTS',
+  'INTERNAL_SERVER_ERROR',
+  'DATABASE_ERROR',
+  'PROJECT_CREATION_FAILED',
+  'DATA_IMPORT_FAILED',
+  'INVALID_JSON',
+  'NOT_FOUND',
+])

39-41: Docstring mismatch with implementation.

Comment says “with data array” but the schema has no data field.

-/**
- * Error response with data array
- */
+/**
+ * Standard error response (array of errors)
+ */
frontend/src/features/project-management/stores/project-list.store.ts (1)

12-24: Reduce loading-state duplication with finally.
Keeps state consistent on early returns and failures.

Apply this diff:

-  const fetchProjects = async () => {
-    isLoading.value = true
-
-    const { data, error: apiError } = await api.project.get()
-
-    if (apiError) {
-      showError(apiError)
-    } else {
-      projects.value = data.data
-    }
-
-    isLoading.value = false
-  }
+  const fetchProjects = async () => {
+    isLoading.value = true
+    try {
+      const { data, error: apiError } = await api.project.get()
+      if (apiError) return showError(apiError)
+      projects.value = data.data
+    } finally {
+      isLoading.value = false
+    }
+  }
@@
-  const deleteProject = async (projectId: string) => {
-    isLoading.value = true
-
-    const { error: apiError } = await api.project({ projectId }).delete()
-
-    if (apiError?.value) {
-      showError(apiError)
-      isLoading.value = false
-      return
-    }
-
-    // Remove from local state
-    projects.value = projects.value.filter((p) => p.id !== projectId)
-    isLoading.value = false
-  }
+  const deleteProject = async (projectId: string) => {
+    isLoading.value = true
+    try {
+      const { error: apiError } = await api.project({ projectId }).delete()
+      if (apiError?.value) return showError(apiError)
+      projects.value = projects.value.filter((p) => p.id !== projectId)
+    } finally {
+      isLoading.value = false
+    }
+  }

Also applies to: 26-40

backend/tests/api/project/project.wikibase.test.ts (1)

265-275: Updated error shape assertion is consistent for 404s.
Good shift to { value: { errors: [...] } }. Note: other tests use a flat array for validation errors—keep that duality documented.

Consider a shared expectApiError helper to handle both shapes (object vs array) to avoid duplication.

backend/tests/api/project/project.create.test.ts (1)

49-56: Validation error assertions match the new Zod-driven shape.
Keeps messages specific; good.

Extract a reusable matcher for Zod error arrays to DRY up test code across suites.

Also applies to: 67-76

backend/src/services/mediawiki-api.service.ts (1)

39-45: Broaden public param types to match coercion

Align get/post params with the new coercion and prevent accidental type widening at call sites.

-  async get<T = any>(params: Record<string, any>): Promise<ApiResponse<T>> {
+  async get<T = any>(params: Record<string, string | number | boolean | null | undefined>): Promise<ApiResponse<T>> {
     return this.request<T>(params, 'GET')
   }
 
-  async post<T = any>(params: Record<string, any>): Promise<ApiResponse<T>> {
+  async post<T = any>(params: Record<string, string | number | boolean | null | undefined>): Promise<ApiResponse<T>> {
     return this.request<T>(params, 'POST')
   }
backend/tests/api/project/project.import-file.test.ts (5)

80-93: Avoid asserting on fragile numeric validator codes

Hard-coding type: 31 etc. is brittle across validator/runtime upgrades. Prefer message/path/schema checks and relax type to a number.

-        expect(error).toHaveProperty('value', [
-          {
-            errors: [],
-            message: "Expected kind 'File'",
-            path: '/file',
-            schema: {
-              default: 'File',
-              format: 'binary',
-              minSize: 1,
-              type: 'string',
-            },
-            type: 31,
-          },
-        ])
+        expect(error.value).toEqual([
+          expect.objectContaining({
+            path: '/file',
+            message: expect.stringContaining("Expected"),
+            schema: expect.objectContaining({ format: 'binary' }),
+            type: expect.any(Number),
+          }),
+        ])

104-118: Relax expectations for empty-file validation details

Same concern as above; keep tests resilient to library changes.

-        expect(error).toHaveProperty('value', [
-          {
-            errors: [],
-            path: '/file',
-            message: "Expected kind 'File'",
-            schema: {
-              default: 'File',
-              format: 'binary',
-              minSize: 1,
-              type: 'string',
-            },
-            type: 31,
-            value: {},
-          },
-        ])
+        expect(error.value).toEqual([
+          expect.objectContaining({
+            path: '/file',
+            message: expect.stringContaining('Expected'),
+            schema: expect.objectContaining({ minSize: 1 }),
+            type: expect.any(Number),
+          }),
+        ])

134-148: Stabilize string-length assertions

Assert on message and limits, not numeric code.

-        expect(error).toHaveProperty('value', [
-          {
-            errors: [],
-            path: '/name',
-            message: 'Expected string length less or equal to 255',
-            schema: {
-              error: 'Project name must be between 1 and 255 characters long if provided',
-              maxLength: 255,
-              minLength: 1,
-              type: 'string',
-            },
-            type: 51,
-            value: longName,
-          },
-        ])
+        expect(error.value).toEqual([
+          expect.objectContaining({
+            path: '/name',
+            message: expect.stringContaining('less or equal to 255'),
+            schema: expect.objectContaining({ maxLength: 255 }),
+            type: expect.any(Number),
+          }),
+        ])

163-177: Same: keep min-length validation robust

-        expect(error).toHaveProperty('value', [
-          {
-            errors: [],
-            path: '/name',
-            message: 'Expected string length greater or equal to 1',
-            schema: {
-              error: 'Project name must be between 1 and 255 characters long if provided',
-              maxLength: 255,
-              minLength: 1,
-              type: 'string',
-            },
-            type: 52,
-            value: '',
-          },
-        ])
+        expect(error.value).toEqual([
+          expect.objectContaining({
+            path: '/name',
+            message: expect.stringContaining('greater or equal to 1'),
+            schema: expect.objectContaining({ minLength: 1 }),
+            type: expect.any(Number),
+          }),
+        ])

29-38: Temp directory cleanup may target the wrong path

new URL('../../temp', import.meta.url) resolves to backend/tests/temp, but the routes write to ./temp. Consider aligning paths to prevent leaks.

Want a small helper to centralize the temp dir path shared between app and tests?

backend/src/services/wikibase-clients.ts (1)

5-43: Prefer Map over Record for client registry

Avoid prototype key collisions and enable O(1) existence/size ops.

-export class WikibaseClient {
-  private clients: Record<string, MediaWikiApiService> = {
-    wikidata: new MediaWikiApiService({
+export class WikibaseClient {
+  private clients = new Map<string, MediaWikiApiService>([
+    ['wikidata', new MediaWikiApiService({
       endpoint: 'https://www.wikidata.org/w/api.php',
       userAgent: 'DataForge/1.0 (https://github.com/DaxServer/dataforge)',
       timeout: 30000,
-    }),
-  }
+    })],
+  ])
@@
-    this.clients[id] = client
+    this.clients.set(id, client)
@@
-    const client = this.clients[instanceId]
+    const client = this.clients.get(instanceId)
@@
-    return this.clients[instanceId] !== undefined
+    return this.clients.has(instanceId)
@@
-    const clientRemoved = this.clients[instanceId] !== undefined
-    delete this.clients[instanceId]
-    return clientRemoved
+    return this.clients.delete(instanceId)
backend/src/api/project/index.ts (1)

165-185: DuckDB DDL: transactions + checkpoint — nice; add NOT NULL for clarity

Primary key implies NOT NULL, but being explicit improves pragma introspection consistency.

-        ADD COLUMN "${primaryKeyColumnName}" BIGINT DEFAULT nextval('project_${project.id}_${primaryKeyColumnName}_seq');
+        ADD COLUMN "${primaryKeyColumnName}" BIGINT NOT NULL DEFAULT nextval('project_${project.id}_${primaryKeyColumnName}_seq');
backend/src/api/project/project.wikibase.ts (4)

125-133: Validate timestamp fields as RFC 3339 datetimes

Strengthen response contracts for created_at/updated_at.

 const WikibaseSchemaResponse = z.object({
   id: UUIDPattern,
   project_id: UUIDPattern,
   name: SchemaName,
   wikibase: z.string(),
   schema: ItemSchemaMapping,
-  created_at: z.string(),
-  updated_at: z.string(),
+  created_at: z.string().datetime(),
+  updated_at: z.string().datetime(),
 })

142-150: Avoid duplicate defaults; rely on schema defaults (wikibase)

Define default once in the Zod schema and remove handler default for wikibase.

 // Body schema
-    wikibase: z.string().default('wikidata').optional(),
+    wikibase: z.string().default('wikidata'),

 // Handler
-    async ({ db, body: { schemaId = Bun.randomUUIDv7(), projectId, name, wikibase = 'wikidata', schema = blankSchema }, status }) => {
+    async ({ db, body: { schemaId = Bun.randomUUIDv7(), projectId, name, wikibase, schema = blankSchema }, status }) => {

Also applies to: 265-279


266-266: Verify Bun.randomUUIDv7 availability or use crypto.randomUUID

Elysia/Bun environments may not have Bun.randomUUIDv7 in all versions.

-async ({ db, body: { schemaId = Bun.randomUUIDv7(), projectId, name, wikibase, schema = blankSchema }, status }) => {
+async ({ db, body: { schemaId = (globalThis as any).Bun?.randomUUIDv7?.() ?? crypto.randomUUID(), projectId, name, wikibase, schema = blankSchema }, status }) => {

If you target a Bun version that guarantees randomUUIDv7, keep your original line. Otherwise, prefer the fallback.


336-345: created_at/updated_at exist but updated_at is not auto-updated on UPDATE

Found: backend/src/plugins/database.ts declares created_at and updated_at with DEFAULT CURRENT_TIMESTAMP (lines ~39–40). No DB trigger or ON UPDATE clause was found. The UPDATE in backend/src/api/project/project.wikibase.ts (lines ~336–345) explicitly sets updated_at. Ensure either every UPDATE path sets updated_at explicitly or add a DB trigger to set updated_at = CURRENT_TIMESTAMP on UPDATE.

backend/src/services/wikibase.service.ts (3)

63-69: Safer property ID extraction

Titles in ns=120 are prefixed. Ensure we only strip the leading namespace.

-          id: page.title.replace('Property:', ''),
+          id: page.title.replace(/^Property:/, ''),

105-116: Add formatVersion for consistent fields in wbsearchentities

Align with item search and ensure aliases/pageid/title presence.

   const searchParams: Record<string, string | number | boolean> = {
     action: 'wbsearchentities',
     search: query,
     type: 'property',
     language: options.language,
     uselang: options.language,
     limit: options.limit,
     continue: options.offset,
     format: 'json',
+    formatVersion: 2,
     strictlanguage: !languageFallback,
   }

76-81: “inserted” counts include REPLACE operations

If you want “inserted” vs “updated”, consider separate counters or use UPSERT metadata if available.

backend/src/api/project/schemas.ts (3)

10-11: Static regex; safe from ReDoS (document to silence tools)

Add a note to clarify the pattern is static.

-export const UUID_REGEX_PATTERN = new RegExp(UUID_REGEX, 'i')
+export const UUID_REGEX_PATTERN = new RegExp(UUID_REGEX, 'i') // safe: static, bounded pattern

22-25: Constrain pagination to non-negative integers

 export const PaginationQuery = z.object({
-  offset: z.coerce.number().default(0).optional(),
-  limit: z.coerce.number().default(25).optional(),
+  offset: z.coerce.number().int().min(0).default(0).optional(),
+  limit: z.coerce.number().int().min(1).max(1000).default(25).optional(),
 })

124-139: Mixing t. and zod: acceptable, but consider unifying*

If Elysia 1.4 file validation is stable for zod, consider a zod-based multipart schema for consistency.

backend/src/api/wikibase/schemas.ts (3)

83-96: Model sitelinks with SiteLinkSchema

Avoid z.any for better guarantees.

 export const ItemDetailsSchema = z.object({
   id: z.string(),
   pageid: z.number().optional(),
   ns: z.number().optional(),
   title: z.string().optional(),
   lastrevid: z.number().optional(),
   modified: z.string().optional(),
   type: z.literal('item'),
   labels: z.record(z.string(), z.string()).optional(),
   descriptions: z.record(z.string(), z.string()).optional(),
   aliases: z.record(z.string(), z.array(z.string())).optional(),
   claims: z.record(z.string(), z.array(z.any())).optional(),
-  sitelinks: z.record(z.string(), z.any()).optional(),
+  sitelinks: z.record(z.string(), SiteLinkSchema).optional(),
 })

319-327: Coerce query params for item search limit/offset

Query strings arrive as strings; coerce to numbers.

   query: z.object({
     q: z.string().describe('Search query for items'),
     instance: InstanceId.optional(),
-    limit: z.number().default(10).describe('Maximum number of results').optional(),
-    offset: z.number().default(0).describe('Offset for pagination').optional(),
+    limit: z.coerce.number().default(10).describe('Maximum number of results').optional(),
+    offset: z.coerce.number().default(0).describe('Offset for pagination').optional(),
     language: z.string().default('en').describe('Language code for search results').optional(),
     languageFallback: z.boolean().default(true).describe('Enable language fallback').optional(),
   }),

369-375: Use PropertyId in violation/warning shapes

 export const ConstraintViolationSchema = z.object({
   constraintType: z.string(),
   message: z.string(),
   severity: z.union([z.literal('error'), z.literal('warning')]),
-  propertyId: z.string(),
+  propertyId: PropertyId,
   value: z.optional(z.any()),
})

 export const ConstraintWarningSchema = z.object({
   constraintType: z.string(),
   message: z.string(),
-  propertyId: z.string(),
+  propertyId: PropertyId,
})

Also applies to: 377-382

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84c9c2e and fee3393.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (50)
  • .kiro/steering/code-conventions.md (1 hunks)
  • .kiro/steering/structure.md (1 hunks)
  • backend/package.json (1 hunks)
  • backend/src/api/_meta_projects.ts (3 hunks)
  • backend/src/api/project/_schemas.ts (0 hunks)
  • backend/src/api/project/import.ts (2 hunks)
  • backend/src/api/project/index.ts (6 hunks)
  • backend/src/api/project/project.create.ts (0 hunks)
  • backend/src/api/project/project.delete.ts (0 hunks)
  • backend/src/api/project/project.get-all.ts (0 hunks)
  • backend/src/api/project/project.get.ts (0 hunks)
  • backend/src/api/project/project.import-file.ts (0 hunks)
  • backend/src/api/project/project.wikibase.ts (7 hunks)
  • backend/src/api/project/schemas.ts (1 hunks)
  • backend/src/api/wikibase/entities.ts (3 hunks)
  • backend/src/api/wikibase/schemas.ts (12 hunks)
  • backend/src/index.ts (2 hunks)
  • backend/src/plugins/database.ts (1 hunks)
  • backend/src/plugins/error-handler.ts (1 hunks)
  • backend/src/services/mediawiki-api.service.ts (1 hunks)
  • backend/src/services/wikibase-clients.ts (1 hunks)
  • backend/src/services/wikibase.service.ts (6 hunks)
  • backend/src/types/error-handler.ts (0 hunks)
  • backend/src/types/error-schemas.ts (1 hunks)
  • backend/src/types/mediawiki-api.ts (2 hunks)
  • backend/src/types/wikibase-api.ts (1 hunks)
  • backend/src/types/wikibase-schema.ts (1 hunks)
  • backend/src/utils/duckdb-types.ts (1 hunks)
  • backend/tests/api/project/import-file.test.ts (1 hunks)
  • backend/tests/api/project/import.test.ts (0 hunks)
  • backend/tests/api/project/project.create.test.ts (3 hunks)
  • backend/tests/api/project/project.delete.test.ts (2 hunks)
  • backend/tests/api/project/project.get-all.test.ts (0 hunks)
  • backend/tests/api/project/project.get.test.ts (4 hunks)
  • backend/tests/api/project/project.import-file.test.ts (5 hunks)
  • backend/tests/api/project/project.wikibase.test.ts (1 hunks)
  • backend/tests/api/wikibase/entities.test.ts (0 hunks)
  • backend/tests/error-handler.test.ts (0 hunks)
  • frontend/package.json (1 hunks)
  • frontend/src/features/data-processing/composables/__tests__/useColumnGeneration.test.ts (1 hunks)
  • frontend/src/features/data-processing/composables/useColumnGeneration.ts (1 hunks)
  • frontend/src/features/project-management/composables/useProjectCreationComposable.ts (0 hunks)
  • frontend/src/features/project-management/stores/project-list.store.ts (1 hunks)
  • frontend/src/features/project-management/stores/project.store.ts (1 hunks)
  • frontend/src/features/wikibase-schema/composables/__tests__/useSchemaApi.test.ts (0 hunks)
  • frontend/src/features/wikibase-schema/composables/useSchemaApi.ts (0 hunks)
  • frontend/src/features/wikibase-schema/stores/schema.store.ts (0 hunks)
  • frontend/src/shared/types/client-errors.ts (0 hunks)
  • guidelines/reference/TESTING.md (1 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (16)
  • frontend/src/features/project-management/composables/useProjectCreationComposable.ts
  • backend/tests/api/project/project.get-all.test.ts
  • frontend/src/features/wikibase-schema/composables/tests/useSchemaApi.test.ts
  • backend/src/api/project/_schemas.ts
  • backend/tests/api/wikibase/entities.test.ts
  • backend/src/api/project/project.delete.ts
  • backend/tests/api/project/import.test.ts
  • backend/tests/error-handler.test.ts
  • frontend/src/features/wikibase-schema/stores/schema.store.ts
  • backend/src/api/project/project.create.ts
  • frontend/src/features/wikibase-schema/composables/useSchemaApi.ts
  • backend/src/api/project/project.get-all.ts
  • frontend/src/shared/types/client-errors.ts
  • backend/src/api/project/project.import-file.ts
  • backend/src/types/error-handler.ts
  • backend/src/api/project/project.get.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript or JavaScript files
Do not use dotenv; Bun automatically loads .env files
Use Bun.serve() for HTTP servers and WebSockets instead of express
Use bun:sqlite for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of ws
Prefer Bun.file over node:fs's readFile/writeFile
Use Bun.$ (e.g., Bun.$ls``) instead of execa for running shell commands

Files:

  • frontend/src/features/data-processing/composables/__tests__/useColumnGeneration.test.ts
  • backend/src/plugins/error-handler.ts
  • backend/src/services/wikibase-clients.ts
  • backend/tests/api/project/project.wikibase.test.ts
  • backend/src/types/wikibase-api.ts
  • backend/src/plugins/database.ts
  • backend/src/utils/duckdb-types.ts
  • frontend/src/features/project-management/stores/project.store.ts
  • frontend/src/features/data-processing/composables/useColumnGeneration.ts
  • backend/src/types/wikibase-schema.ts
  • backend/tests/api/project/project.delete.test.ts
  • backend/tests/api/project/project.get.test.ts
  • frontend/src/features/project-management/stores/project-list.store.ts
  • backend/src/index.ts
  • backend/tests/api/project/import-file.test.ts
  • backend/src/services/mediawiki-api.service.ts
  • backend/tests/api/project/project.create.test.ts
  • backend/src/types/error-schemas.ts
  • backend/src/api/project/project.wikibase.ts
  • backend/src/api/_meta_projects.ts
  • backend/src/api/wikibase/entities.ts
  • backend/tests/api/project/project.import-file.test.ts
  • backend/src/types/mediawiki-api.ts
  • backend/src/api/project/import.ts
  • backend/src/services/wikibase.service.ts
  • backend/src/api/project/schemas.ts
  • backend/src/api/project/index.ts
  • backend/src/api/wikibase/schemas.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun test instead of jest for running tests

Files:

  • frontend/src/features/data-processing/composables/__tests__/useColumnGeneration.test.ts
  • backend/tests/api/project/project.wikibase.test.ts
  • backend/tests/api/project/project.delete.test.ts
  • backend/tests/api/project/project.get.test.ts
  • backend/tests/api/project/import-file.test.ts
  • backend/tests/api/project/project.create.test.ts
  • backend/tests/api/project/project.import-file.test.ts
**/*.{html,ts,tsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file.html|file.ts|file.css> instead of webpack or esbuild for building HTML, TypeScript, or CSS files

Files:

  • frontend/src/features/data-processing/composables/__tests__/useColumnGeneration.test.ts
  • backend/src/plugins/error-handler.ts
  • backend/src/services/wikibase-clients.ts
  • backend/tests/api/project/project.wikibase.test.ts
  • backend/src/types/wikibase-api.ts
  • backend/src/plugins/database.ts
  • backend/src/utils/duckdb-types.ts
  • frontend/src/features/project-management/stores/project.store.ts
  • frontend/src/features/data-processing/composables/useColumnGeneration.ts
  • backend/src/types/wikibase-schema.ts
  • backend/tests/api/project/project.delete.test.ts
  • backend/tests/api/project/project.get.test.ts
  • frontend/src/features/project-management/stores/project-list.store.ts
  • backend/src/index.ts
  • backend/tests/api/project/import-file.test.ts
  • backend/src/services/mediawiki-api.service.ts
  • backend/tests/api/project/project.create.test.ts
  • backend/src/types/error-schemas.ts
  • backend/src/api/project/project.wikibase.ts
  • backend/src/api/_meta_projects.ts
  • backend/src/api/wikibase/entities.ts
  • backend/tests/api/project/project.import-file.test.ts
  • backend/src/types/mediawiki-api.ts
  • backend/src/api/project/import.ts
  • backend/src/services/wikibase.service.ts
  • backend/src/api/project/schemas.ts
  • backend/src/api/project/index.ts
  • backend/src/api/wikibase/schemas.ts
package.json

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

package.json: Use bun install instead of npm install, yarn install, or pnpm install for dependency installation
Use bun run <script> instead of npm run <script>, yarn run <script>, or pnpm run <script> for running scripts

Files:

  • package.json
🧠 Learnings (8)
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to package.json : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install` for dependency installation

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: For more information, read the official Bun documentation at https://bun.sh/docs or check `node_modules/bun-types/docs/**.md` if available locally

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>` for running scripts

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to **/*.{html,ts,tsx,css} : Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild` for building HTML, TypeScript, or CSS files

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript or JavaScript files

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` (e.g., `Bun.$`ls``) instead of execa for running shell commands

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` for running tests

Applied to files:

  • package.json
📚 Learning: 2025-07-20T14:13:40.153Z
Learnt from: CR
PR: DaxServer/dataforge#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-20T14:13:40.153Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` for SQLite instead of `better-sqlite3`

Applied to files:

  • package.json
🧬 Code graph analysis (10)
backend/src/services/wikibase-clients.ts (2)
backend/src/services/mediawiki-api.service.ts (1)
  • MediaWikiApiService (3-80)
backend/src/types/mediawiki-api.ts (1)
  • MediaWikiConfig (12-19)
backend/src/services/mediawiki-api.service.ts (1)
backend/src/types/mediawiki-api.ts (1)
  • ApiResponse (307-314)
backend/src/types/error-schemas.ts (1)
backend/src/types/mediawiki-api.ts (1)
  • ApiError (295-298)
backend/src/api/project/project.wikibase.ts (3)
backend/src/types/wikibase-schema.ts (8)
  • PropertyId (6-6)
  • PropertyId (7-7)
  • WikibaseDataType (16-27)
  • WikibaseDataType (28-28)
  • StatementRank (9-13)
  • StatementRank (14-14)
  • ItemId (3-3)
  • ItemId (4-4)
backend/src/api/project/schemas.ts (2)
  • UUIDPattern (11-11)
  • ProjectParams (37-39)
backend/src/types/error-schemas.ts (2)
  • ApiError (41-43)
  • ApiError (49-49)
backend/src/api/wikibase/entities.ts (2)
backend/src/api/wikibase/schemas.ts (1)
  • WikibasePropertiesFetchSchema (475-491)
backend/src/types/error-handler.ts (1)
  • ApiErrorHandler (6-210)
backend/src/types/mediawiki-api.ts (2)
backend/src/types/wikibase-schema.ts (2)
  • WikibaseDataType (16-27)
  • WikibaseDataType (28-28)
backend/src/api/wikibase/schemas.ts (1)
  • Term (34-34)
backend/src/services/wikibase.service.ts (3)
backend/src/services/wikibase-clients.ts (1)
  • WikibaseClient (4-43)
backend/src/types/wikibase-api.ts (3)
  • SearchOptions (121-126)
  • SearchResponse (128-133)
  • PropertySearchResult (84-93)
backend/src/api/wikibase/schemas.ts (1)
  • PropertySearchResult (50-50)
backend/src/api/project/schemas.ts (1)
backend/src/types/error-schemas.ts (2)
  • ApiError (41-43)
  • ApiError (49-49)
backend/src/api/project/index.ts (1)
backend/src/api/project/schemas.ts (2)
  • Project (20-20)
  • ProjectParams (37-39)
backend/src/api/wikibase/schemas.ts (3)
backend/src/types/wikibase-schema.ts (6)
  • WikibaseDataType (16-27)
  • WikibaseDataType (28-28)
  • PropertyId (6-6)
  • PropertyId (7-7)
  • ItemId (3-3)
  • ItemId (4-4)
backend/src/types/wikibase-api.ts (1)
  • PropertySearchResult (84-93)
backend/src/types/error-schemas.ts (2)
  • ApiError (41-43)
  • ApiError (49-49)
🪛 GitHub Actions: Typecheck code
frontend/src/features/project-management/stores/project-list.store.ts

[error] 32-32: TS2345: Argument of type '{ errors: any[]; } | { type: 'validation'; on: string; summary?: string | undefined; message?: string | undefined; found?: unknown; property?: string | undefined; expected?: string | undefined; }' is not assignable to parameter of type 'ExtendedError'.


[error] 32-32: TS2345: Property 'errors' is missing in type '{ type: 'validation'; on: string; summary?: string | undefined; message?: string | undefined; found?: unknown; property?: string | undefined; expected?: string | undefined; }' but required in type 'ExtendedError'.

backend/src/api/project/index.ts

[error] 6-6: TypeScript error TS6133: 'ProjectDeleteSchema' is declared but its value is never read.


[error] 6-6: TypeScript error TS6133: 'ProjectDeleteSchema' is declared but its value is never read.

🪛 ast-grep (0.38.6)
backend/src/api/project/schemas.ts

[warning] 9-9: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(UUID_REGEX, 'i')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🔇 Additional comments (34)
backend/package.json (1)

19-24: Catalog mappings verified — Elysia 1.4.x are pinned; zod is caret (^4.0.0).
bun.lock (catalog) shows elysia → 1.4.4; @elysiajs/cors, eden, openapi → 1.4.0; backend/package.json uses "catalog:" tokens; zod → ^4.0.0 — tighten the catalog zod entry to an exact or narrower range if you want to avoid silent drift.

frontend/package.json (1)

60-64: LGTM on dev tooling bumps.

Minor version bumps for Vite, devtools, and vue-tsc look safe.

backend/src/plugins/error-handler.ts (1)

17-17: Normalize validation error shape; return stable issues array

File: backend/src/plugins/error-handler.ts (line 17)

Do not return framework-specific error.valueError; map to an issues[] with a safe fallback.

-      return [error.valueError]
+      const issues =
+        (error as any)?.valueError?.issues ??
+        (error as any)?.cause?.issues ??
+        (Array.isArray((error as any)?.errors) ? (error as any).errors : null)
+      return issues ?? [{ message: 'Validation failed' }]

Verification: ran rg -nC2 -g '!**/node_modules/**' '422|VALIDATION|issues' backend/tests frontend — no matches found. Confirm whether tests or other callers expect an 'issues' array before applying this change.

backend/tests/api/project/project.get.test.ts (3)

202-202: No-op reordering of query keys.

Key order is irrelevant; keeping a consistent style is fine.


213-213: No-op reordering of query keys.

Looks good.


268-268: No-op reordering of query keys.

Looks good.

backend/src/api/_meta_projects.ts (2)

5-6: Confirm Zod is registered with Elysia/OpenAPI.

If the app isn’t using a Zod adapter, response schemas won’t validate or document correctly.

Do you want me to add the Zod adapter wiring in backend/index.ts as a follow-up?


43-45: LGTM — SQL CASE formatting change only.

No functional change.

backend/src/types/mediawiki-api.ts (1)

15-16: Making userAgent/timeout optional is fine.

Ensure sensible defaults in the service layer.

backend/src/types/wikibase-schema.ts (1)

3-4: Enforce positive-integer Q/P IDs; don’t rely on z.templateLiteral unless Zod v4 is present

package.json has no zod entry; cannot assume z.templateLiteral is available — replace with a regex-based string validator (or install zod@^4 and use templateLiteral with z.number().int().min(1)).

File: backend/src/types/wikibase-schema.ts (lines 3-4, 6-7)

export const ItemId = z.string().regex(/^Q[1-9]\d*$/, { message: 'ItemId must be Q followed by a positive integer' })
export type ItemId = z.infer<typeof ItemId>

export const PropertyId = z.string().regex(/^P[1-9]\d*$/, { message: 'PropertyId must be P followed by a positive integer' })
export type PropertyId = z.infer<typeof PropertyId>

Alternative (only if you add zod@^4):

z.templateLiteral([z.literal('Q'), z.number().int().min(1)])
z.templateLiteral([z.literal('P'), z.number().int().min(1)])
backend/src/utils/duckdb-types.ts (1)

1-1: LGTM: import path update aligns with centralized schemas module.

frontend/src/features/project-management/stores/project.store.ts (1)

1-1: LGTM: type import switched to central schemas barrel.

frontend/src/features/data-processing/composables/__tests__/useColumnGeneration.test.ts (1)

1-1: LGTM: test type import tracks backend schema consolidation.

frontend/src/features/data-processing/composables/useColumnGeneration.ts (1)

1-1: Import path update looks correct.
Matches the centralized schemas module. No further action.

guidelines/reference/TESTING.md (1)

89-89: Doc snippet import path updated correctly.
Aligns with the new centralized module.

frontend/src/features/project-management/stores/project-list.store.ts (1)

1-1: TS path alias verified — no action required.
frontend/tsconfig.json maps "@backend/" → "../backend/src/" and backend/src/api/project/schemas.ts exports export type Project = ... (so the import is resolvable).

backend/src/index.ts (2)

21-31: Double-check OpenAPI scalar config block.
If the plugin expects scalar at the top level, this is fine; otherwise, adjust per the installed version’s docs.

Would you like me to look up the exact option names for your installed version and propose an exact config?


10-10: Confirm @elysiajs/openapi version supports scalar option

backend/package.json reports "@elysiajs/openapi": "catalog:" — no semver found so compatibility can’t be verified. Provide the exact dependency line or a lockfile entry (pnpm-lock.yaml / yarn.lock / package-lock.json), or run rg -n "@elysiajs/openapi" backend and paste the output so I can confirm whether the scalar option is supported.

backend/tests/api/project/import-file.test.ts (1)

67-81: 422 validation expectation aligned with new flat array error shape.
Looks correct for file validation errors.

backend/tests/api/project/project.create.test.ts (1)

2-2: Import path migration to centralized schemas is correct.
No action needed.

backend/src/api/project/import.ts (2)

21-25: Revisit comment: Elysia 1.3.x note.
You’re targeting Elysia 1.4; re-validate whether file type validation is still disabled and update the comment accordingly.


10-11: Response 201 as z.null() vs tests expecting empty.
If clients/tests expect empty object, consider z.object({}).strict() to avoid null vs {} mismatch.

I can adjust to {} and update any dependent tests if desired.

backend/src/services/mediawiki-api.service.ts (1)

26-37: Authentication likely needs cookie persistence

Node/Bun fetch typically doesn’t maintain a cookie jar between requests. If authenticate() is used, you may need explicit cookie handling.

Would you like me to add a lightweight cookie jar for Bun (store Set-Cookie and send Cookie on subsequent calls)?

backend/tests/api/project/project.import-file.test.ts (1)

2-2: Import path change looks correct

UUID pattern sourced from centralized schemas is consistent with the PR direction.

backend/src/services/wikibase-clients.ts (2)

5-11: Preloaded wikidata client: good default

Sensible defaults and UA. This will benefit consumers immediately.


13-24: Pass-through token is unused downstream

token is stored but MediaWikiApiService doesn’t apply it to requests. Either wire it into headers or drop it here to avoid confusion.

I can wire Authorization header usage if that token is OAuth/Bearer-like. Confirm expected scheme?

backend/src/api/wikibase/entities.ts (2)

24-37: New fetch-all-properties endpoint: LGTM

Clear contract and response shape; leverages db() correctly.


43-58: Guard against empty queries; ensure schema enforces non-empty

q.trim() implies string. Ensure PropertySearchSchema enforces z.string().min(1) to avoid runtime trim() on undefined.

If it already does, no change needed. Otherwise, I can update the schema.

backend/src/api/project/index.ts (2)

344-374: Temp file upload helper: looks good

Uses Bun APIs correctly and returns a simple payload.


221-257: Confirm default pagination change to 25 — frontend & tests already align

Backend GET /api/project/:projectId sets limit = 25; frontend fetchProject defaults to limit = 25; backend tests expect limit = 25. No callers assuming limit = 0 were found — only the store's initial meta.limit = 0 before any fetch. No change required.

Locations:

  • backend/src/api/project/index.ts — GET /:projectId handler (limit = 25)
  • frontend/src/features/project-management/stores/project.store.ts — fetchProject(..., limit = 25) and initial meta.limit = 0
  • backend/tests/api/project/project.get.test.ts — getExpectedMeta default limit = 25
backend/src/api/project/project.wikibase.ts (1)

162-215: Route schema wiring reads clean and consistent

Tags, response envelopes, and ApiError alignment look good.

backend/src/services/wikibase.service.ts (1)

33-42: Client resolution design looks good

Extending WikibaseClient and centralizing client management improves cohesion.

backend/src/api/project/schemas.ts (1)

66-79: Centralized schemas and tags look solid

Good consolidation and consistent ApiError usage.

backend/src/api/wikibase/schemas.ts (1)

98-141: Overall: Zod migration and route schemas look good

Good consolidation, clearer docs, and consistent ApiError usage.

@@ -1,12 +1,13 @@
import { ApiError } from '@backend/types/error-schemas'
import { t } from 'elysia'
import z from 'zod'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Prefer named import for Zod.
Use the canonical import { z } from 'zod' to avoid interop pitfalls.

Apply:

-import z from 'zod'
+import { z } from 'zod'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import z from 'zod'
import { z } from 'zod'
🤖 Prompt for AI Agents
In backend/src/api/project/import.ts around line 3, the file uses a
default-style import "import z from 'zod'" which can cause interop issues;
change it to the canonical named import "import { z } from 'zod'" and update any
references if necessary, then run TypeScript/ESLint to ensure no remaining
import errors.

Comment on lines +4 to +11
GetProjectByIdSchema,
ProjectCreateSchema,
ProjectDeleteSchema,
ProjectImportFileSchema,
} from '@backend/api/project/project.import-file'
ProjectParams,
ProjectsGetAllSchema,
type Project,
} from '@backend/api/project/schemas'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unused import triggers pipeline failure

ProjectDeleteSchema is imported but not used (TS6133). Remove import or re-enable schema on the DELETE route.

-  ProjectCreateSchema,
-  ProjectDeleteSchema,
+  ProjectCreateSchema,
@@
-    // ProjectDeleteSchema,
+    // ProjectDeleteSchema, // re-enable when DELETE has a schema again

Or remove the import entirely:

-  ProjectDeleteSchema,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
GetProjectByIdSchema,
ProjectCreateSchema,
ProjectDeleteSchema,
ProjectImportFileSchema,
} from '@backend/api/project/project.import-file'
ProjectParams,
ProjectsGetAllSchema,
type Project,
} from '@backend/api/project/schemas'
GetProjectByIdSchema,
ProjectCreateSchema,
ProjectImportFileSchema,
ProjectParams,
ProjectsGetAllSchema,
type Project,
} from '@backend/api/project/schemas'
🧰 Tools
🪛 GitHub Actions: Typecheck code

[error] 6-6: TypeScript error TS6133: 'ProjectDeleteSchema' is declared but its value is never read.


[error] 6-6: TypeScript error TS6133: 'ProjectDeleteSchema' is declared but its value is never read.

🤖 Prompt for AI Agents
In backend/src/api/project/index.ts around lines 4 to 11, ProjectDeleteSchema is
imported but unused causing a TypeScript TS6133 failure; remove
ProjectDeleteSchema from the import list (or re-add/enable its use on the DELETE
route if that was intended). Update the import statement to only include
actually used symbols (e.g., remove the ProjectDeleteSchema token) and run
TypeScript to confirm the unused-import error is resolved.

Comment on lines +30 to +35
const PropertyReference = z.object({
id: PropertyId,
label: t.Optional(t.String()),
dataType: t.String(),
label: z.string().optional(),
dataType: z.string(),
})

export type PropertyReference = typeof PropertyReference.static
export type PropertyReference = z.infer<typeof PropertyReference>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use WikibaseDataType for PropertyReference.dataType

Align with ValueMapping and wikibase types to prevent mismatches.

-const PropertyReference = z.object({
+const PropertyReference = z.object({
   id: PropertyId,
-  label: z.string().optional(),
-  dataType: z.string(),
+  label: z.string().optional(),
+  dataType: WikibaseDataType,
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const PropertyReference = z.object({
id: PropertyId,
label: t.Optional(t.String()),
dataType: t.String(),
label: z.string().optional(),
dataType: z.string(),
})
export type PropertyReference = typeof PropertyReference.static
export type PropertyReference = z.infer<typeof PropertyReference>
const PropertyReference = z.object({
id: PropertyId,
label: z.string().optional(),
dataType: WikibaseDataType,
})
export type PropertyReference = z.infer<typeof PropertyReference>
🤖 Prompt for AI Agents
In backend/src/api/project/project.wikibase.ts around lines 30 to 35, the
PropertyReference schema currently uses z.string() for dataType which can
diverge from your defined Wikibase types; replace z.string() with the existing
WikibaseDataType schema/type (e.g., use WikibaseDataType or
z.nativeEnum(WikibaseDataType) as appropriate), add the necessary import for
WikibaseDataType at the top of the file, and keep the exported type inference
unchanged so PropertyReference.dataType aligns with the ValueMapping/wikibase
types.

Comment on lines +13 to +19
export const ProjectResponseSchema = z.object({
id: z.string(),
name: z.string(),
created_at: z.string(),
updated_at: z.string(),
})

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use UUIDPattern and datetime validators for stronger contracts

 export const ProjectResponseSchema = z.object({
-  id: z.string(),
+  id: UUIDPattern,
   name: z.string(),
-  created_at: z.string(),
-  updated_at: z.string(),
+  created_at: z.string().datetime(),
+  updated_at: z.string().datetime(),
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const ProjectResponseSchema = z.object({
id: z.string(),
name: z.string(),
created_at: z.string(),
updated_at: z.string(),
})
export const ProjectResponseSchema = z.object({
id: z.string().uuid(),
name: z.string(),
created_at: z.string().datetime(),
updated_at: z.string().datetime(),
})
🤖 Prompt for AI Agents
In backend/src/api/project/schemas.ts around lines 13 to 19, the schema
currently uses plain strings for id and timestamps; replace the loose types with
stricter validators by validating id as a UUID and created_at/updated_at as ISO
datetimes (e.g. use z.string().uuid() for id and z.string().datetime() or an
equivalent ISO datetime regex validator for the timestamps) so the contract
enforces correct formats and fails on invalid values.

Comment on lines +43 to +51
export const ProjectCreateSchema = {
body: z.object({
name: z
.string({
error: 'Project name is required and must be at least 1 character long',
})
.trim()
.min(1),
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Zod error option; use required_error/min message

The key “error” is not a valid Zod option.

   body: z.object({
-    name: z
-      .string({
-        error: 'Project name is required and must be at least 1 character long',
-      })
-      .trim()
-      .min(1),
+    name: z
+      .string({ required_error: 'Project name is required' })
+      .trim()
+      .min(1, 'Project name must be at least 1 character long'),
   }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const ProjectCreateSchema = {
body: z.object({
name: z
.string({
error: 'Project name is required and must be at least 1 character long',
})
.trim()
.min(1),
}),
export const ProjectCreateSchema = {
body: z.object({
name: z
.string({ required_error: 'Project name is required' })
.trim()
.min(1, 'Project name must be at least 1 character long'),
}),
🤖 Prompt for AI Agents
In backend/src/api/project/schemas.ts around lines 43 to 51, replace the invalid
Zod option "error" on z.string(...) with the proper Zod options and move the min
message into the .min call: use z.string({ required_error: 'Project name is
required and must be at least 1 character long', invalid_type_error: 'Project
name must be a string' }).trim().min(1, { message: 'Project name is required and
must be at least 1 character long' }) so you provide a
required_error/invalid_type_error for the string constructor and a message for
the min validator.

* @see https://www.mediawiki.org/wiki/API:Main_page
*/

import type { Term } from '@backend/api/wikibase/schemas'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Layering issue: types importing from api module.

types/ shouldn’t depend on api/. Move Term to a shared types/ module and import from there.

Apply:

-import type { Term } from '@backend/api/wikibase/schemas'
+import type { Term } from '@backend/types/wikibase-shared'

And extract Term to backend/src/types/wikibase-shared.ts for both modules to consume.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In backend/src/types/mediawiki-api.ts around line 7 the file imports Term from
@backend/api/wikibase/schemas which creates a layering violation (types
depending on api); extract the Term type into a new shared file
backend/src/types/wikibase-shared.ts, move the Term definition there, then
update this file (and any other modules that currently import Term from
@backend/api/...) to import Term from backend/src/types/wikibase-shared.ts
instead and remove the api dependency.

Comment on lines +329 to 353
title: string
pageid: number
datatype: WikibaseDataType
concepturi: string
repository: string
url: string
display: {
label?: {
value: string
language: string
}
description?: {
value: string
language: string
}
}
label: string
description: string
match: {
type: Term
language: string
text: string
}
aliases?: string[]
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

WikibaseSearchEntityResult: required fields and datatype now mandatory — this is incorrect for items and mismatched with runtime schema.

  • datatype exists for properties, not items. Making it required breaks item results.
  • Several fields are now required here but optional in WikibaseSearchEntityResultSchema below — type/runtime drift.

Apply one of:

Option A — keep a single interface with optionals:

 export interface WikibaseSearchEntityResult<T> {
   id: T
-  title: string
-  pageid: number
-  datatype: WikibaseDataType
-  concepturi: string
-  repository: string
-  url: string
+  title?: string
+  pageid?: number
+  datatype?: WikibaseDataType
+  concepturi?: string
+  repository?: string
+  url?: string
   display: {
-    label?: {
+    label?: {
       value: string
       language: string
     }
     description?: {
       value: string
       language: string
     }
   }
-  label: string
-  description: string
+  label?: string
+  description?: string
   match: {
     type: Term
     language: string
     text: string
   }
   aliases?: string[]
 }

Option B — model a discriminated union for item vs property and update the schema accordingly. I can generate the full union if you prefer.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
title: string
pageid: number
datatype: WikibaseDataType
concepturi: string
repository: string
url: string
display: {
label?: {
value: string
language: string
}
description?: {
value: string
language: string
}
}
label: string
description: string
match: {
type: Term
language: string
text: string
}
aliases?: string[]
}
export interface WikibaseSearchEntityResult<T> {
id: T
title?: string
pageid?: number
datatype?: WikibaseDataType
concepturi?: string
repository?: string
url?: string
display: {
label?: {
value: string
language: string
}
description?: {
value: string
language: string
}
}
label?: string
description?: string
match: {
type: Term
language: string
text: string
}
aliases?: string[]
}
🤖 Prompt for AI Agents
In backend/src/types/mediawiki-api.ts around lines 329-353, the interface forces
fields (notably datatype) as required which is incorrect for item search results
and diverges from the runtime WikibaseSearchEntityResultSchema; make datatype
optional (datatype?: WikibaseDataType) and relax any other fields to match the
schema OR implement a discriminated union (e.g., PropertySearchEntity vs
ItemSearchEntity) so properties include datatype while items do not, then update
the downstream schema/type usages to the chosen representation to restore
type/runtime parity.

Comment on lines +356 to 359
search: WikibaseSearchEntityResult<T>[]
searchinfo: {
search: number
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Response shape drift: searchinfo.search is not aligned with the existing schema or API usage here.

Either add searchinfo to WikibaseSearchEntitiesResponseSchema and validate it, or revert the interface to match the current runtime schema.

I can update both the TS interface and the Elysia schema to stay in lockstep.

🤖 Prompt for AI Agents
backend/src/types/mediawiki-api.ts lines 356-359: the TypeScript interface adds
a searchinfo.search field that no longer matches the runtime/Elysia schema;
update the runtime schema to include searchinfo: { search: number } and its
validation in WikibaseSearchEntitiesResponseSchema (or revert the TS interface
to the previous shape) so runtime and types match; ensure the schema export, any
parsing/validation code, and tests are updated to accept and validate
searchinfo.search accordingly.

Comment on lines +122 to 125
limit: number
offset: number
language: string
languageFallback?: boolean
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Breaking change: making limit/offset/language required in SearchOptions.

If callers relied on defaults, this will break. Either keep them optional with defaults in the service layer or update all call sites.

Apply:

-export interface SearchOptions {
-  limit: number
-  offset: number
-  language: string
+export interface SearchOptions {
+  limit?: number
+  offset?: number
+  language?: string
   languageFallback?: boolean
 }

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Find interface declaration(s) for SearchOptions"
rg -n --hidden --no-ignore-vcs -S 'interface\s+SearchOptions\b' -C3 || true

echo
echo "2) All occurrences of 'SearchOptions' (type references/imports/params)"
rg -n --hidden --no-ignore-vcs -S '\bSearchOptions\b' -C3 || true

echo
echo "3) Occurrences of property access '.limit', '.offset', '.language' (context)"
rg -n --hidden --no-ignore-vcs -S '\.limit\b' -C3 || true
rg -n --hidden --no-ignore-vcs -S '\.offset\b' -C3 || true
rg -n --hidden --no-ignore-vcs -S '\.language\b' -C3 || true

echo
echo "4) Object literals with 'limit:', 'offset:', 'language:' (explicit passing sites)"
rg -n --hidden --no-ignore-vcs -S '\blimit\s*:' -C2 || true
rg -n --hidden --no-ignore-vcs -S '\boffset\s*:' -C2 || true
rg -n --hidden --no-ignore-vcs -S '\blanguage\s*:' -C2 || true

echo
echo "5) Parameter destructuring with defaults for 'limit'/'offset'/'language' (in signatures)"
rg -n --hidden --no-ignore-vcs -S '\{\s*[^}]*limit\s*=' -C2 || true
rg -n --hidden --no-ignore-vcs -S '\{\s*[^}]*offset\s*=' -C2 || true
rg -n --hidden --no-ignore-vcs -S '\{\s*[^}]*language\s*=' -C2 || true

echo
echo "6) Functions/methods explicitly typed with SearchOptions"
rg -n --hidden --no-ignore-vcs -S ':\s*SearchOptions\b' -C3 || true

echo
echo "7) Imports of SearchOptions"
rg -n --hidden --no-ignore-vcs -S "import .*SearchOptions" -C2 || true

Length of output: 53604


Revert SearchOptions fields to optional (breaking change otherwise)

SearchOptions currently requires limit/offset/language; callers and the API layer use defaults (zod schemas / route destructuring) and the service uses nullish coalescing — make these optional to avoid TypeScript breakage.

File: backend/src/types/wikibase-api.ts (lines 121–125)

Apply:

-export interface SearchOptions {
-  limit: number
-  offset: number
-  language: string
+export interface SearchOptions {
+  limit?: number
+  offset?: number
+  language?: string
   languageFallback?: boolean
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
limit: number
offset: number
language: string
languageFallback?: boolean
export interface SearchOptions {
limit?: number
offset?: number
language?: string
languageFallback?: boolean
}
🤖 Prompt for AI Agents
In backend/src/types/wikibase-api.ts around lines 122 to 125, the SearchOptions
fields are currently required; change limit, offset and language to be optional
(limit?: number, offset?: number, language?: string) while leaving
languageFallback as optional; update any local usages/types if needed to accept
undefined (e.g., keep nullish coalescing in callers/services) so this is a
non-breaking revert to optional fields.

const projects = selectReader.getRowObjectsJson()

expect(projects).toEqual([])
expect(projects).toBeArrayOfSize(0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use a built-in matcher; toBeArrayOfSize requires jest-extended.

bun:test doesn’t include toBeArrayOfSize by default. Prefer toHaveLength(0).

Apply:

-    expect(projects).toBeArrayOfSize(0)
+    expect(projects).toHaveLength(0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(projects).toBeArrayOfSize(0)
expect(projects).toHaveLength(0)
🤖 Prompt for AI Agents
In backend/tests/api/project/project.delete.test.ts around line 46, the test
uses the non-standard matcher toBeArrayOfSize(0) (from jest-extended) which
bun:test doesn't provide; replace that call with the built-in matcher
expect(projects).toHaveLength(0) and remove any unnecessary jest-extended
imports/setup in this test file if present.

@DaxServer DaxServer merged commit 720f7ba into main Sep 13, 2025
5 of 6 checks passed
@DaxServer DaxServer deleted the elysia-1.4 branch September 13, 2025 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant