feat(wikibase-integration): integrate nodemw#145
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds 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
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: ... }
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
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
mockOpenApiSpecis 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 URLsTests 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.tsfor@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 anyand typeApiClientlocally asany. 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 fetchRight now the test relies on a live network call to exercise feature extraction. Consider stubbing
globalThis.fetchto 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 shapeUsing
(await response.json()) as anyis 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?.versionandopenApiSpec.pathsif desired.backend/src/index.ts (1)
39-39: Entities API registered successfullyRegistering 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 DXDecorating 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: TypedgetPropertysignature: LGTM; consider optional runtime ID validationThe 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: TypedgetItemsignature: LGTM; same note on optional runtime validationSimilar 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 consistencyElsewhere 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 valueBy 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 beforeEachCalling 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 argumentsYou 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 searchItems 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 readabilitySmall 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.
📒 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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript or JavaScript files
Do not use dotenv; Bun automatically loads .env files
UseBun.serve()for HTTP servers and WebSockets instead ofexpress
Usebun:sqlitefor SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead ofws
PreferBun.fileovernode:fs's readFile/writeFile
UseBun.$(e.g.,Bun.$ls``) instead of execa for running shell commands
Files:
backend/src/services/wikibase-api.service.tsbackend/src/plugins/wikibase.tsbackend/tests/services/wikibase-config-connectivity.test.tsbackend/tests/api/wikibase/entities.test.tsbackend/tests/services/wikibase-config.service.test.tsbackend/src/api/wikibase/entities.tsbackend/tests/services/wikibase-api.service.test.tsbackend/src/index.tsbackend/tests/api/wikibase/instances.test.tsbackend/src/services/wikibase-config.service.tsbackend/src/services/nodemw-wikibase.service.tsbackend/tests/services/nodemw-wikibase.service.test.tsbackend/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 ofwebpackoresbuildfor building HTML, TypeScript, or CSS files
Files:
backend/src/services/wikibase-api.service.tsbackend/src/plugins/wikibase.tsbackend/tests/services/wikibase-config-connectivity.test.tsbackend/tests/api/wikibase/entities.test.tsbackend/tests/services/wikibase-config.service.test.tsbackend/src/api/wikibase/entities.tsbackend/tests/services/wikibase-api.service.test.tsbackend/src/index.tsbackend/tests/api/wikibase/instances.test.tsbackend/src/services/wikibase-config.service.tsbackend/src/services/nodemw-wikibase.service.tsbackend/tests/services/nodemw-wikibase.service.test.tsbackend/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 testinstead ofjestfor running tests
Files:
backend/tests/services/wikibase-config-connectivity.test.tsbackend/tests/api/wikibase/entities.test.tsbackend/tests/services/wikibase-config.service.test.tsbackend/tests/services/wikibase-api.service.test.tsbackend/tests/api/wikibase/instances.test.tsbackend/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 implementationThe 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-definedThe 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 signaturesImporting 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 importsSwitching 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 improvementImporting 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 surfaceUsing 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 behaviorsThese 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 wrappingThe 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 behaviorCorrectly asserts instance propagation and the { data } envelope. Looks good.
86-120: Items search test mirrors properties search wellSolid assertions on parameter coercion and response shape for items.
122-141: Item details test is accurateVerifies 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-safeCasts param to PropertyId and returns a strongly-typed { data } envelope. Looks good.
176-206: Items search endpoint mirrors properties search correctlyConsistent parameter handling and response typing. Good symmetry.
208-236: Item details endpoint is solidTyped 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 fineCorrectly derives protocol/server/path from baseUrl and sets a conservative concurrency. No issues.
| 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, | ||
| }, | ||
| })) ?? [] |
There was a problem hiding this comment.
🛠️ Refactor suggestion
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.
| 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.
| resolve({ | ||
| results, | ||
| totalCount: data['search-info']?.search || results.length, | ||
| hasMore: data['search-continue'] !== undefined, | ||
| query, | ||
| }) | ||
| }) |
There was a problem hiding this comment.
🛠️ Refactor suggestion
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.
| 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() |
There was a problem hiding this comment.
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 anyOptional: 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.
| expect(service.getProperty('test-instance', 'P999999' as PropertyId)).rejects.toThrow( | ||
| 'Failed to get property P999999', | ||
| ) |
There was a problem hiding this comment.
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", | ||
| ) |
There was a problem hiding this comment.
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.
Addresses nodemw Task 2 of #137