Skip to content

feat(wikibase-integration): integrate nodemw#145

Merged
DaxServer merged 1 commit intomainfrom
wikibase-integration-task2
Aug 17, 2025
Merged

feat(wikibase-integration): integrate nodemw#145
DaxServer merged 1 commit intomainfrom
wikibase-integration-task2

Conversation

@DaxServer
Copy link
Owner

Addresses nodemw Task 2 of #137

@coderabbitai
Copy link

coderabbitai bot commented Aug 17, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Search and view Wikibase properties and items via new API endpoints.
    • Retrieve detailed information for a specific property or item.
    • Get the currently configured default Wikibase instance.
    • Validate a Wikibase configuration without saving it.
  • Improvements

    • Unified, structured error responses across Wikibase instance endpoints for clearer diagnostics.
    • Health check responses now explicitly report status and messages.
  • Tests

    • Added comprehensive tests for entities search/detail endpoints and service behaviors to ensure reliability.

Walkthrough

Adds a Wikibase entities API with search/get endpoints for properties and items, wires a new wikibase plugin exposing nodemw service, expands the nodemw service with entity operations and instance inspection, updates instances API with structured errors and new endpoints, integrates routes in app index, adjusts typings in WikibaseApiService, and updates/adds tests.

Changes

Cohort / File(s) Summary
Specs update
.kiro/specs/mwn-wikibase-integration/tasks.md
Marks 2.x tasks as completed; removes two subtasks under 2.1 and 2.4.
Wikibase entities API
backend/src/api/wikibase/entities.ts
New router /api/wikibase/entities with GET properties/items search and details; TypeBox schemas; uses cors, databasePlugin, errorHandlerPlugin, wikibasePlugin; exports wikibaseEntitiesApi.
Wikibase instances API
backend/src/api/wikibase/instances.ts
Adds/updates endpoints: GET default, POST validate; structured error payloads; updated body schemas; consistent success/error responses; reorganized route metadata.
App integration
backend/src/index.ts
Switches to alias imports; registers wikibaseEntitiesApi; keeps existing middleware chain.
Wikibase plugin
backend/src/plugins/wikibase.ts
New plugin exporting wikibasePlugin that decorates app with nodemwWikibaseService.
Nodemw Wikibase service
backend/src/services/nodemw-wikibase.service.ts
Adds search/get for properties/items, instance inspection APIs; broadens client return types to any; scaffolds auth token handling; exposes typed models; minor config tidy.
Wikibase API service typing
backend/src/services/wikibase-api.service.ts
Changes method params to use PropertyId/ItemId; no logic changes.
Wikibase config service formatting
backend/src/services/wikibase-config.service.ts
Formatting-only edits; no behavioral changes.
Entities API tests
backend/tests/api/wikibase/entities.test.ts
New tests for properties/items search/get; mocks service; validates param translation and response wrapping.
Instances API tests formatting
backend/tests/api/wikibase/instances.test.ts
Formatting adjustments (trailing commas/whitespace); no logic changes.
Nodemw service tests
backend/tests/services/nodemw-wikibase.service.test.ts
Adds entity operation tests (search/get, errors, non-existent instance); expands typings; note duplicate suite present.
Wikibase API service tests typing
backend/tests/services/wikibase-api.service.test.ts
Uses PropertyId/ItemId in tests; updates casts/messages.
Wikibase config connectivity tests
backend/tests/services/wikibase-config-connectivity.test.ts
Whitespace-only changes.
Wikibase config service tests formatting
backend/tests/services/wikibase-config.service.test.ts
Formatting-only changes.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant App as Elysia App
  participant EntitiesAPI as /api/wikibase/entities
  participant Plugin as wikibasePlugin
  participant Service as nodemwWikibaseService
  participant WB as Wikibase API

  Client->>App: GET /properties/search?q=...&instance=...&limit&offset
  App->>EntitiesAPI: Route handling
  EntitiesAPI->>Plugin: access wikibase
  Plugin->>Service: searchProperties(instance, q, {limit, offset})
  Service->>WB: wbsearchentities (type=property)
  WB-->>Service: results
  Service-->>EntitiesAPI: SearchResponse
  EntitiesAPI-->>Client: { data: ... }

  Client->>App: GET /properties/:propertyId?instance=...
  App->>EntitiesAPI: Route handling
  EntitiesAPI->>Plugin: access wikibase
  Plugin->>Service: getProperty(instance, propertyId)
  Service->>WB: wbgetentities (props: labels, descriptions, aliases, datatype, claims)
  WB-->>Service: entity
  Service-->>EntitiesAPI: PropertyDetails
  EntitiesAPI-->>Client: { data: ... }
Loading
sequenceDiagram
  participant Client
  participant App as Elysia App
  participant InstancesAPI as /api/wikibase/instances
  participant Service as nodemwWikibaseService

  Client->>App: GET /default
  App->>InstancesAPI: Route handling
  InstancesAPI->>Service: getAllInstances()/getInstanceIds()
  Service-->>InstancesAPI: instances/default
  InstancesAPI-->>Client: { success, data }

  Client->>App: POST /validate { config }
  App->>InstancesAPI: Route handling
  InstancesAPI->>Service: create temp client / validate
  Service-->>InstancesAPI: validation result or error
  InstancesAPI-->>Client: { success, data } or structured error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch wikibase-integration-task2

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 6

🔭 Outside diff range comments (3)
backend/tests/services/wikibase-config-connectivity.test.ts (1)

196-206: Remove unused variable to fix TS6133 in pipeline

mockOpenApiSpec is declared but never used, causing TypeScript to fail the pipeline.

Apply this diff to remove the unused variable:

-      const mockOpenApiSpec = {
-        paths: {
-          '/entities/items': {},
-          '/entities/properties': {},
-          '/search/entities': {},
-          '/statements': {},
-          '/labels': {},
-          '/descriptions': {},
-          '/aliases': {},
-        },
-      }
backend/src/services/wikibase-config.service.ts (2)

47-60: Align pre-defined instances with tests and expected base URLs

Tests expect two pre-defined instances (‘wikidata’ default + ‘wikimedia-commons’) and Wikidata baseUrl with “wikibase/v0”. Current code only includes one instance and uses “v1”, causing test failures.

Apply this diff to restore compatibility:

 const PREDEFINED_INSTANCES: WikibaseInstanceConfig[] = [
   {
     id: 'wikidata',
     name: 'Wikidata',
-    baseUrl: 'https://www.wikidata.org/w/rest.php/wikibase/v1',
+    baseUrl: 'https://www.wikidata.org/w/rest.php/wikibase/v0',
     userAgent: 'DataForge/0.1 (https://github.com/dataforge/dataforge)',
     isDefault: true,
     metadata: {
       description: 'The free knowledge base that anyone can edit',
       language: 'en',
       version: 'v0',
     },
   },
+  {
+    id: 'wikimedia-commons',
+    name: 'Wikimedia Commons',
+    baseUrl: 'https://commons.wikimedia.org/w/rest.php/wikibase/v0',
+    userAgent: 'DataForge/0.1 (https://github.com/dataforge/dataforge)',
+    isDefault: false,
+    metadata: {
+      description: 'Media file repository for Wikimedia projects',
+      language: 'en',
+      version: 'v0',
+    },
+  },
 ]

2-2: Fix missing type declarations for ‘@wmde/wikibase-rest-api’ (TS7016)

TypeScript is failing due to missing .d.ts for @wmde/wikibase-rest-api. Add a shim declaration to unblock the type-checker.

Create a new file, for example backend/src/types/shims-wmde-wikibase-rest-api.d.ts:

declare module '@wmde/wikibase-rest-api' {
  export class ApiClient {
    basePath: string
    defaultHeaders?: Record<string, string>
    constructor(basePath: string)
  }
}

Alternatively, if you want to avoid a global shim, replace the import with a lazy const { ApiClient } = require('@wmde/wikibase-rest-api') as any and type ApiClient locally as any. The shim approach is preferred.

🧹 Nitpick comments (12)
backend/tests/services/wikibase-config-connectivity.test.ts (1)

208-216: Optional: Make the “Feature Extraction” test deterministic by stubbing fetch

Right now the test relies on a live network call to exercise feature extraction. Consider stubbing globalThis.fetch to return a controlled OpenAPI spec so the test is stable and actually validates feature detection.

I can provide a minimal fetch stub for Bun tests if you want to make this change.

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

523-535: Safe JSON parsing is fine; optional: validate OpenAPI shape

Using (await response.json()) as any is acceptable here. If you want to harden this later, consider validating against a minimal OpenAPI schema subset before extracting features, and defaulting gracefully if structure is unexpected.

I can provide a lightweight runtime type guard for openApiSpec.info?.version and openApiSpec.paths if desired.

backend/src/index.ts (1)

39-39: Entities API registered successfully

Registering wikibaseEntitiesApi completes the new entities surface. One note: both the global app and the entities module apply errorHandlerPlugin; double application is typically safe in Elysia, but consider centralizing to avoid redundant registrations.

backend/src/plugins/wikibase.ts (1)

1-7: Plugin wiring looks correct; consider augmenting Elysia typing for DX

Decorating the app with nodemwWikibaseService under 'wikibase' is fine. For stronger type inference in handlers, consider module augmentation so ctx.wikibase is always typed, even outside the immediate chain.

Example augmentation (outside this file, e.g., a d.ts in backend/src/types):

import 'elysia'
import type { NodemwWikibaseService } from '@backend/services/nodemw-wikibase.service'

declare module 'elysia' {
  interface Context {
    wikibase: NodemwWikibaseService
  }
}
backend/src/services/wikibase-api.service.ts (2)

173-193: Typed getProperty signature: LGTM; consider optional runtime ID validation

The signature hardens ID correctness at compile time. Optionally add a lightweight runtime check (e.g., /^P\d+$/) to produce immediate, clearer errors before hitting the API.

Example:

if (!/^P\d+$/.test(propertyId)) {
  throw new Error(`Invalid property ID format: ${propertyId}`)
}

242-261: Typed getItem signature: LGTM; same note on optional runtime validation

Similar to properties, a quick /^Q\d+$/ validation can fail fast with clearer errors.

backend/tests/services/nodemw-wikibase.service.test.ts (2)

11-11: Unify typed ID imports for consistency

Elsewhere tests import PropertyId/ItemId from @backend/types/wikibase-schema. Consider using the same source here to avoid subtle incompatibilities between external and internal type aliases.

-import type { PropertyId, ItemId } from 'wikibase-sdk'
+import type { PropertyId, ItemId } from '@backend/types/wikibase-schema'

128-176: Spying on the method under test reduces test value

By mocking service.searchProperties/getProperty/searchItems/getItem on the same instance you're testing, assertions mainly verify spy calls, not behavior. Prefer:

  • spying with .mockImplementationOnce on underlying HTTP client or a dependency, or
  • using spyOn(...).mockResolvedValueOnce only for specific edge cases and defaulting to callThrough for the happy path.

This will improve confidence in the real implementation while keeping controllable scenarios.

backend/tests/api/wikibase/entities.test.ts (2)

16-22: Remove redundant spy setup in beforeEach

Calling spyOn(...).mockRestore() in beforeEach creates a new spy and immediately restores it, which is a no-op and adds noise. Either omit these lines and define spies only in tests, or use a single global restore in an afterEach hook.

Example cleanup:

-  beforeEach(() => {
-    // Reset all mocks before each test
-    spyOn(nodemwWikibaseService, 'searchProperties').mockRestore()
-    spyOn(nodemwWikibaseService, 'getProperty').mockRestore()
-    spyOn(nodemwWikibaseService, 'searchItems').mockRestore()
-    spyOn(nodemwWikibaseService, 'getItem').mockRestore()
-  })
+  // Define spies within each test as needed. If cleanup is required, add:
+  // afterEach(() => mock.restore()); // if using Bun's mock.restore()

143-165: Consider asserting defaulted response shape in addition to call arguments

You verify defaulting of limit/offset. Optionally also assert that the response body uses the same { data } envelope for consistency.

-    await api.api.wikibase.entities.properties.search.get({
+    const response = await api.api.wikibase.entities.properties.search.get({
       query: {
         q: 'test',
       },
     })
 
     expect(searchSpy).toHaveBeenCalledWith('wikidata', 'test', {
       limit: 10,
       offset: 0,
     })
+    expect(response.data).toEqual({ data: mockResults })
backend/src/services/nodemw-wikibase.service.ts (2)

254-287: Unify totalCount computation across item/property search

Items search estimates totalCount from limit/offset when 'search-continue' exists, which diverges from properties and is still not authoritative. For consistency and correctness, prefer results.length as totalCount unless you fetch and compute a real total.

Proposed change:

-        resolve({
-          results,
-          totalCount: data['search-continue'] ? limit + (options.offset ?? 0) + 1 : results.length,
-          hasMore: !!data['search-continue'],
-          query,
-        })
+        resolve({
+          results,
+          totalCount: results.length,
+          hasMore: data['search-continue'] !== undefined,
+          query,
+        })

125-140: Minor: name the offset and reuse; improves readability

Small readability improvement when mapping the offset to the 'continue' parameter expected by wbsearchentities.

-    const limit = options.limit ?? 10
-    const language = options.language ?? 'en'
+    const limit = options.limit ?? 10
+    const language = options.language ?? 'en'
+    const offset = options.offset ?? 0
...
-      continue: options.offset ?? 0,
+      continue: offset,

Apply similarly in searchItems.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 62c91eb and c3b9e6a.

📒 Files selected for processing (14)
  • .kiro/specs/mwn-wikibase-integration/tasks.md (1 hunks)
  • backend/src/api/wikibase/entities.ts (1 hunks)
  • backend/src/api/wikibase/instances.ts (1 hunks)
  • backend/src/index.ts (2 hunks)
  • backend/src/plugins/wikibase.ts (1 hunks)
  • backend/src/services/nodemw-wikibase.service.ts (5 hunks)
  • backend/src/services/wikibase-api.service.ts (4 hunks)
  • backend/src/services/wikibase-config.service.ts (9 hunks)
  • backend/tests/api/wikibase/entities.test.ts (1 hunks)
  • backend/tests/api/wikibase/instances.test.ts (21 hunks)
  • backend/tests/services/nodemw-wikibase.service.test.ts (2 hunks)
  • backend/tests/services/wikibase-api.service.test.ts (3 hunks)
  • backend/tests/services/wikibase-config-connectivity.test.ts (7 hunks)
  • backend/tests/services/wikibase-config.service.test.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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:

  • backend/src/services/wikibase-api.service.ts
  • backend/src/plugins/wikibase.ts
  • backend/tests/services/wikibase-config-connectivity.test.ts
  • backend/tests/api/wikibase/entities.test.ts
  • backend/tests/services/wikibase-config.service.test.ts
  • backend/src/api/wikibase/entities.ts
  • backend/tests/services/wikibase-api.service.test.ts
  • backend/src/index.ts
  • backend/tests/api/wikibase/instances.test.ts
  • backend/src/services/wikibase-config.service.ts
  • backend/src/services/nodemw-wikibase.service.ts
  • backend/tests/services/nodemw-wikibase.service.test.ts
  • backend/src/api/wikibase/instances.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:

  • backend/src/services/wikibase-api.service.ts
  • backend/src/plugins/wikibase.ts
  • backend/tests/services/wikibase-config-connectivity.test.ts
  • backend/tests/api/wikibase/entities.test.ts
  • backend/tests/services/wikibase-config.service.test.ts
  • backend/src/api/wikibase/entities.ts
  • backend/tests/services/wikibase-api.service.test.ts
  • backend/src/index.ts
  • backend/tests/api/wikibase/instances.test.ts
  • backend/src/services/wikibase-config.service.ts
  • backend/src/services/nodemw-wikibase.service.ts
  • backend/tests/services/nodemw-wikibase.service.test.ts
  • backend/src/api/wikibase/instances.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:

  • backend/tests/services/wikibase-config-connectivity.test.ts
  • backend/tests/api/wikibase/entities.test.ts
  • backend/tests/services/wikibase-config.service.test.ts
  • backend/tests/services/wikibase-api.service.test.ts
  • backend/tests/api/wikibase/instances.test.ts
  • backend/tests/services/nodemw-wikibase.service.test.ts
🧬 Code Graph Analysis (10)
backend/src/services/wikibase-api.service.ts (1)
backend/src/types/wikibase-api.ts (2)
  • PropertyDetails (44-52)
  • ItemDetails (73-80)
backend/src/plugins/wikibase.ts (1)
backend/src/services/nodemw-wikibase.service.ts (1)
  • nodemwWikibaseService (381-381)
backend/tests/api/wikibase/entities.test.ts (3)
backend/src/api/wikibase/entities.ts (1)
  • wikibaseEntitiesApi (108-236)
backend/src/services/nodemw-wikibase.service.ts (1)
  • nodemwWikibaseService (381-381)
backend/src/types/wikibase-api.ts (5)
  • SearchResponse (136-141)
  • PropertySearchResult (54-63)
  • PropertyDetails (44-52)
  • ItemSearchResult (82-90)
  • ItemDetails (73-80)
backend/src/api/wikibase/entities.ts (4)
backend/src/types/wikibase-api.ts (9)
  • StatementValue (102-105)
  • ReferencePart (116-119)
  • Statement (93-100)
  • PropertyConstraint (65-70)
  • PropertySearchResult (54-63)
  • PropertyDetails (44-52)
  • ItemSearchResult (82-90)
  • SiteLink (122-126)
  • ItemDetails (73-80)
backend/src/plugins/database.ts (1)
  • databasePlugin (63-70)
backend/src/plugins/error-handler.ts (1)
  • errorHandlerPlugin (9-38)
backend/src/plugins/wikibase.ts (1)
  • wikibasePlugin (4-7)
backend/src/index.ts (1)
backend/src/api/wikibase/entities.ts (1)
  • wikibaseEntitiesApi (108-236)
backend/tests/api/wikibase/instances.test.ts (1)
backend/src/index.ts (1)
  • elysiaApp (14-42)
backend/src/services/wikibase-config.service.ts (1)
backend/src/types/wikibase-api.ts (1)
  • WikibaseInstanceConfig (6-18)
backend/src/services/nodemw-wikibase.service.ts (1)
backend/src/types/wikibase-api.ts (7)
  • NodemwWikibaseInstanceConfig (21-41)
  • SearchOptions (129-134)
  • SearchResponse (136-141)
  • PropertySearchResult (54-63)
  • PropertyDetails (44-52)
  • ItemSearchResult (82-90)
  • ItemDetails (73-80)
backend/tests/services/nodemw-wikibase.service.test.ts (1)
backend/src/types/wikibase-api.ts (6)
  • WikibaseInstanceConfig (6-18)
  • SearchResponse (136-141)
  • PropertySearchResult (54-63)
  • PropertyDetails (44-52)
  • ItemSearchResult (82-90)
  • ItemDetails (73-80)
backend/src/api/wikibase/instances.ts (1)
backend/src/services/wikibase-config.service.ts (1)
  • wikibaseConfigService (619-619)
🪛 GitHub Actions: Typecheck code
backend/tests/services/wikibase-config-connectivity.test.ts

[error] 196-196: TS6133: 'mockOpenApiSpec' is declared but its value is never read.

backend/tests/services/wikibase-config.service.test.ts

[error] 71-71: TS2532: Object is possibly 'undefined'.


[error] 76-76: TS2532: Object is possibly 'undefined'.


[error] 76-76: TS2532: Object is possibly 'undefined'.


[error] 90-90: TS2532: Object is possibly 'undefined'.

backend/tests/api/wikibase/instances.test.ts

[error] 34-36: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 39-40: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 55-57: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 70-73: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 92-93: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 117-120: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 149-152: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 184-185: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 203-206: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 233-234: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 247-250: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 269-272: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 296-298: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 313-316: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 329-332: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 347-352: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 365-368: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 383-385: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 412-413: TypeScript error TS18046: 'data' is of type 'unknown'.


[error] 426-429: TypeScript error TS18046: 'data' is of type 'unknown'.

backend/src/services/wikibase-config.service.ts

[error] 2-2: TS7016: Could not find a declaration file for module '@wmde/wikibase-rest-api'. '/home/runner/work/dataforge/dataforge/node_modules/@wmde/wikibase-rest-api/dist/index.js' implicitly has an 'any' type.

🪛 GitHub Actions: Run tests
backend/tests/services/wikibase-config.service.test.ts

[error] 1-1: Test assertion failed: Expected: true.

🔇 Additional comments (17)
backend/tests/services/wikibase-config.service.test.ts (1)

27-48: Test expectations assume two pre-defined instances including ‘wikimedia-commons’

Multiple tests assert that both ‘wikidata’ and ‘wikimedia-commons’ are pre-defined and that there are exactly two. Ensure the service defines both (see related comment on wikibase-config.service.ts).

I’ve suggested a concrete fix in wikibase-config.service.ts to add ‘wikimedia-commons’ and align baseUrl versions with tests.

.kiro/specs/mwn-wikibase-integration/tasks.md (1)

9-10: Task status updates look consistent with the implementation

The 2.x tasks are marked complete in line with the new Nodemw Wikibase integration and entities API added in this PR.

Also applies to: 15-15, 21-21, 27-27

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

38-41: Tests assume ‘wikimedia-commons’ is pre-defined

The assertions here expect ‘wikimedia-commons’ to exist out-of-the-box. Ensure the service includes it (see suggested fix in wikibase-config.service.ts) or adjust expectations.

backend/tests/services/wikibase-api.service.test.ts (1)

4-4: Typed IDs import aligns with updated service signatures

Importing PropertyId and ItemId from the shared wikibase-schema keeps tests aligned with the stricter API typing.

backend/src/index.ts (1)

10-12: Good move to alias-based imports

Switching to @backend/... aliases improves maintainability and avoids fragile relative paths.

backend/src/services/wikibase-api.service.ts (2)

19-19: Aligning IDs to typed aliases is a good improvement

Importing PropertyId and ItemId from wikibase-schema aligns the service with stricter ID handling across the codebase.


268-297: Typed constraints method is consistent with the new API surface

Using PropertyId here keeps the constraints API consistent. The preliminary instance check is fine for early failure semantics.

backend/tests/services/nodemw-wikibase.service.test.ts (1)

269-276: Error-path tests read clearly and assert the right behaviors

These cover invalid IDs and non-existent instances well.

Also applies to: 278-285, 288-301

backend/tests/api/wikibase/entities.test.ts (4)

24-61: Good coverage of properties.search parameters and response wrapping

The test correctly verifies translation of q/instance/limit/offset and asserts that the API returns { data: ... }. This protects the contract against regression in pagination coercion.


63-84: Property details test is precise and aligned with handler behavior

Correctly asserts instance propagation and the { data } envelope. Looks good.


86-120: Items search test mirrors properties search well

Solid assertions on parameter coercion and response shape for items.


122-141: Item details test is accurate

Verifies instance and ID forwarding with the expected { data } wrapper. All good.

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

114-144: Endpoints and schemas for properties.search are well-structured

  • Correct defaulting and numeric coercion for limit/offset
  • Typed response wrapper with { data: PropertySearchResponse }
  • Route metadata is informative

No changes needed.


146-174: Property details endpoint is consistent and type-safe

Casts param to PropertyId and returns a strongly-typed { data } envelope. Looks good.


176-206: Items search endpoint mirrors properties search correctly

Consistent parameter handling and response typing. Good symmetry.


208-236: Item details endpoint is solid

Typed ID casting and response envelope are consistent with the rest of the API surface.

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

367-376: Default nodemw config looks fine

Correctly derives protocol/server/path from baseUrl and sets a conservative concurrency. No issues.

Comment on lines +149 to +160
const results: PropertySearchResult[] =
data.search?.map((item: any) => ({
id: item.id,
label: item.label || item.id,
description: item.description || '',
dataType: item.datatype || 'unknown',
match: {
type: item.match?.type || ('label' as const),
language: item.match?.language || language,
text: item.match?.text || item.label || item.id,
},
})) ?? []
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

Type mismatch: extra field in match; remove language to align with PropertySearchResult

PropertySearchResult.match only allows { type, text }. Returning language causes a type error and contract drift from your API typings and schemas.

Apply this diff:

-        const results: PropertySearchResult[] =
-          data.search?.map((item: any) => ({
+        const results: PropertySearchResult[] =
+          (data.search ?? []).map((item: any) => ({
             id: item.id,
             label: item.label || item.id,
             description: item.description || '',
             dataType: item.datatype || 'unknown',
             match: {
               type: item.match?.type || ('label' as const),
-              language: item.match?.language || language,
               text: item.match?.text || item.label || item.id,
             },
           })) ?? []
📝 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 results: PropertySearchResult[] =
data.search?.map((item: any) => ({
id: item.id,
label: item.label || item.id,
description: item.description || '',
dataType: item.datatype || 'unknown',
match: {
type: item.match?.type || ('label' as const),
language: item.match?.language || language,
text: item.match?.text || item.label || item.id,
},
})) ?? []
const results: PropertySearchResult[] =
(data.search ?? []).map((item: any) => ({
id: item.id,
label: item.label || item.id,
description: item.description || '',
dataType: item.datatype || 'unknown',
match: {
type: item.match?.type || ('label' as const),
text: item.match?.text || item.label || item.id,
},
})) ?? []
🤖 Prompt for AI Agents
In backend/src/services/nodemw-wikibase.service.ts around lines 149 to 160, the
mapped PropertySearchResult includes a match.language property which is not
allowed by the PropertySearchResult type; remove the language field from the
match object and only return { type, text } (keep existing fallbacks for type
and text), ensuring the mapped shape matches the declared interface and avoids
the extra field.

Comment on lines +162 to +168
resolve({
results,
totalCount: data['search-info']?.search || results.length,
hasMore: data['search-continue'] !== undefined,
query,
})
})
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

Incorrect key 'search-info'; use a reliable totalCount or drop it

wbsearchentities returns searchinfo (no hyphen), and it doesn’t expose an authoritative total count. Using data['search-info'] will always be undefined.

Simplify totalCount and keep hasMore derived from 'search-continue':

-        resolve({
-          results,
-          totalCount: data['search-info']?.search || results.length,
-          hasMore: data['search-continue'] !== undefined,
-          query,
-        })
+        resolve({
+          results,
+          totalCount: results.length,
+          hasMore: data['search-continue'] !== undefined,
+          query,
+        })
📝 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
resolve({
results,
totalCount: data['search-info']?.search || results.length,
hasMore: data['search-continue'] !== undefined,
query,
})
})
resolve({
results,
totalCount: results.length,
hasMore: data['search-continue'] !== undefined,
query,
})
🤖 Prompt for AI Agents
In backend/src/services/nodemw-wikibase.service.ts around lines 162 to 168, the
code uses data['search-info'] which is incorrect (the API returns searchinfo
without a hyphen and doesn't provide an authoritative total), so replace the
totalCount expression with a reliable value such as results.length (or omit
totalCount) and keep hasMore derived from data['search-continue'] as before;
update the resolve payload to use totalCount: results.length (or remove
totalCount) and preserve hasMore: data['search-continue'] !== undefined and the
other fields.

expect(response.status).toBe(200)

const data = await response.json()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Cast response JSON to a concrete type to fix TS18046 (“unknown”)

In Bun, Response.json() returns unknown. Cast to a concrete type (or any) in tests to satisfy the type checker.

Minimal fix across all occurrences:

-      const data = await response.json()
+      const data = (await response.json()) as any

Optional: define a small helper and a response shape to improve clarity:

type ApiResponse<T = unknown> = {
  success: boolean
  data: T
  errors?: { code: string; message: string }[]
  message?: string
}

const json = <T>(r: Response) => r.json() as Promise<T>

Then use const data = await json<ApiResponse<any>>(response).

Also applies to: 54-54, 69-69, 91-91, 116-116, 149-149, 183-183, 203-203, 233-233, 247-247, 269-269, 295-295, 313-313, 329-329, 347-347, 365-365, 383-383, 411-411, 425-425

🤖 Prompt for AI Agents
backend/tests/api/wikibase/instances.test.ts lines
33,54,69,91,116,149,183,203,233,247,269,295,313,329,347,365,383,411,425:
Response.json() returns unknown in Bun causing TS18046; cast the result to a
concrete type (e.g., ApiResponse<any> or any) or add a small helper json<T>(r:
Response): Promise<T> and replace each usage with await json<YourType>(response)
so the tests compile—update each listed line to await response.json() as
Promise<ApiResponse<any>> (or use the helper) to satisfy the type checker.

Comment on lines +273 to 275
expect(service.getProperty('test-instance', 'P999999' as PropertyId)).rejects.toThrow(
'Failed to get property P999999',
)
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 un-awaited Promise assertions using .rejects

These tests use .rejects.toThrow(...) without awaiting or returning the Promise, which can cause false positives or unhandled rejections. Mark the tests async and await the expectations (or return the Promise).

Apply these minimal changes inside each affected test:

- test('should throw meaningful errors for invalid property IDs', () => {
-   expect(service.getProperty('test-instance', 'P999999' as PropertyId)).rejects.toThrow(
-     'Failed to get property P999999',
-   )
- })
+ test('should throw meaningful errors for invalid property IDs', async () => {
+   await expect(service.getProperty('test-instance', 'P999999' as PropertyId)).rejects.toThrow(
+     'Failed to get property P999999',
+   )
+ })
- test('should throw meaningful errors for invalid item IDs', () => {
-   expect(service.getItem('test-instance', 'Q999999' as ItemId)).rejects.toThrow(
-     'Failed to get item Q999999',
-   )
- })
+ test('should throw meaningful errors for invalid item IDs', async () => {
+   await expect(service.getItem('test-instance', 'Q999999' as ItemId)).rejects.toThrow(
+     'Failed to get item Q999999',
+   )
+ })
- test('should return empty constraints array for properties without constraints', () => {
-   expect(service.getPropertyConstraints('test-instance', 'P1' as PropertyId)).rejects.toThrow(
-     'Failed to get constraints for property P1',
-   )
- })
+ test('should return empty constraints array for properties without constraints', async () => {
+   await expect(
+     service.getPropertyConstraints('test-instance', 'P1' as PropertyId),
+   ).rejects.toThrow('Failed to get constraints for property P1')
+ })
- test('should handle constraint parsing errors gracefully', () => {
-   expect(
-     service.getPropertyConstraints('test-instance', 'P999999' as PropertyId),
-   ).rejects.toThrow('Failed to get constraints for property P999999')
- })
+ test('should handle constraint parsing errors gracefully', async () => {
+   await expect(
+     service.getPropertyConstraints('test-instance', 'P999999' as PropertyId),
+   ).rejects.toThrow('Failed to get constraints for property P999999')
+ })

Also applies to: 279-281, 311-311, 317-320

🤖 Prompt for AI Agents
In backend/tests/services/wikibase-api.service.test.ts around lines 273-275 (and
also update the similar cases at 279-281, 311, and 317-320), the tests call
expect(...).rejects.toThrow(...) without awaiting or returning the Promise; mark
each affected test function async and await the expect(...).rejects.toThrow(...)
(or return the expect Promise) so the assertion is actually awaited and
unhandled rejections are avoided; apply this minimal change to each listed test.

await expect(service.addInstance(configWithExistingId)).rejects.toThrow(
"Instance with ID 'wikidata' already exists"
"Instance with ID 'wikidata' already exists",
)
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 TS2532 (“possibly undefined”) by asserting non-null when indexing

With noUncheckedIndexedAccess enabled, direct indexing returns possibly undefined. Use non-null assertions for test-only indexing to satisfy the type checker.

Apply this diff:

-      expect(instances[0].isDefault).toBe(true)
+      expect(instances[0]!.isDefault).toBe(true)
-      for (let i = 1; i < nonDefaultInstances.length; i++) {
-        expect(nonDefaultInstances[i].name >= nonDefaultInstances[i - 1].name).toBe(true)
-      }
+      for (let i = 1; i < nonDefaultInstances.length; i++) {
+        expect(nonDefaultInstances[i]!.name >= nonDefaultInstances[i - 1]!.name).toBe(true)
+      }
-      expect(customInstances[0].id).toBe('custom-test')
+      expect(customInstances[0]!.id).toBe('custom-test')

Also applies to: 76-77, 90-90

🧰 Tools
🪛 GitHub Actions: Typecheck code

[error] 71-71: TS2532: Object is possibly 'undefined'.

🤖 Prompt for AI Agents
In backend/tests/services/wikibase-config.service.test.ts around lines 71 (also
applies to lines 76-77 and 90), the test is failing TS2532 because indexing into
the instances array returns a possibly undefined value under
noUncheckedIndexedAccess; update the test assertions to use non-null assertions
when indexing (e.g., instances[0]!, instances[1]!, etc.) so the type checker
knows the elements are present; modify each affected expect(...) call to assert
non-null on the indexed element before accessing its properties.

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