-
Notifications
You must be signed in to change notification settings - Fork 0
feat: expand MediaWiki Action API integration #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR consolidates Wikibase types into @backend/types/wikibase-schema, removes codegen and wikibase-sdk dependencies, restructures Wikibase APIs (instance-scoped paths and route schemas), refactors services (client management and types), removes legacy instance/config modules, updates schemas and tests, and adjusts frontend imports and minor behaviors. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Client
participant API as Elysia API (/api/wikibase)
participant S as WikibaseService
participant MW as MediaWiki API
rect rgb(230,240,255)
note over C,API: Instance-scoped entities flow (new)
C->>API: GET /:instanceId/properties/search?q=...&languageFallback=true
API->>S: searchProperties(instanceId, options)
S->>MW: wbsearchentities (strictlanguage based on languageFallback)
MW-->>S: results
S-->>API: mapped results with relevanceScore, metadata
API-->>C: { data: enhancedResults, searchMetadata }
end
rect rgb(235,255,235)
note over C,API: Property details with optional constraints
C->>API: GET /:instanceId/properties/:propertyId?includeConstraints=true
API->>S: getProperty(instanceId, propertyId)
S->>MW: wbgetentities
MW-->>S: entity data
API->>API: if includeConstraints → call constraints service
API-->>C: { data: propertyDetails (+constraints) }
end
sequenceDiagram
autonumber
participant C as Client
participant API as Elysia API (/api/wikibase/constraints)
participant CVS as ConstraintValidationService
participant Cache as In-memory Cache
participant S as WikibaseService
rect rgb(255,245,230)
note over C,API: Constraints retrieval
C->>API: GET /properties/:propertyId/constraints?instance=wikidata
API->>CVS: getPropertyConstraints(instanceId, propertyId)
CVS->>Cache: check constraints
alt cache hit
Cache-->>CVS: constraints
else cache miss
CVS->>S: fetch property/entity as needed
S-->>CVS: entity
CVS->>Cache: store constraints
end
CVS-->>API: constraints
API-->>C: { data }
end
rect rgb(255,235,245)
note over C,API: Validation
C->>API: POST /validate/schema { schema }
API->>CVS: validateSchema(instanceId, Record<string, unknown[]>)
CVS-->>API: ValidationResult
API-->>C: { data: ValidationResult }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
Pre-merge checks (2 passed, 1 inconclusive)❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. ✨ 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
frontend/src/features/wikibase-schema/stores/schema.store.ts (1)
12-18: Import ItemId as a type and add missing Ref importItemId is a type; importing it as a value can cause a runtime import error under Bun/Vite. Also, Ref is used but not imported as a type.
Apply:
-import type { StatementRank } from '@backend/types/wikibase-schema' -import { ItemId } from '@backend/types/wikibase-schema' +import type { StatementRank } from '@backend/types/wikibase-schema' +import type { ItemId } from '@backend/types/wikibase-schema' @@ -import { computed, ref } from 'vue' +import { computed, ref, type Ref } from 'vue'backend/src/types/mediawiki-api.ts (1)
326-346: Wikibase search result/response interfaces don’t match the validated schema
- Interface WikibaseSearchEntityResult exposes only a small subset, while the validator allows title/pageid/repository/url/concepturi/aliases/display.
- Interface WikibaseSearchEntityResponse has 'search-info' but the validator uses 'search' plus optional 'search-continue' and 'success' (no 'search-info').
Align to avoid consumers seeing properties as missing at type level.
Apply:
-export interface WikibaseSearchEntityResult<T> { - id: T - label?: string - description?: string - datatype?: WikibaseDataType - match?: { - type?: string - language?: string - text?: string - } -} +export interface WikibaseSearchEntityResult<T> { + id: T + title?: string + pageid?: number + repository?: string + url?: string + concepturi?: string + label?: string + description?: string + aliases?: string[] + display?: { + label?: { value: string; language: string } + description?: { value: string; language: string } + } + match?: { + type?: string + language?: string + text?: string + } + datatype?: WikibaseDataType +} @@ -export interface WikibaseSearchEntityResponse<T> { - search?: WikibaseSearchEntityResult<T>[] - 'search-info'?: { - search?: number - } - 'search-continue'?: number - error?: ApiError -} +export interface WikibaseSearchEntityResponse<T> { + search?: WikibaseSearchEntityResult<T>[] + 'search-continue'?: number + success?: number + error?: ApiError +}Also applies to: 509-516, 474-507
frontend/src/features/wikibase-schema/composables/useSchemaBuilder.ts (1)
22-34: Missing import for WikibaseSchemaMapping (compile error)
WikibaseSchemaMappingis used but not imported.import type { Alias, ItemSchema, Label, PropertyReference, PropertyValueMap, ReferenceSchemaMapping, StatementSchemaMapping, TermsSchemaMapping, ValueMapping, } from '@backend/api/project/project.wikibase' +import type { WikibaseSchemaMapping } from '@backend/api/project/project.wikibase'backend/tests/api/wikibase/entities.test.ts (1)
95-116: Remove duplicate test case.There are two identical "Item endpoints" describe blocks (lines 53-93 and 95-116) with the same test case "should return 404 for non-existent item". This appears to be a copy-paste error.
Remove the duplicate describe block:
- describe('Item endpoints', () => { - test('should return 404 for non-existent item', async () => { - const { data, status, error } = await api - .wikibase({ instanceId: 'wikidata' }) - .items({ itemId: 'Q1000000' }) - .get() - - expect(data).toBeNull() - expect(status).toBe(404) - expect(error).toHaveProperty('value', { - data: [], - errors: [ - { - details: [], - code: 'NOT_FOUND', - message: "Item with identifier 'Q1000000' not found", - }, - ], - }) - }) - })backend/src/api/wikibase/schemas.ts (3)
132-157: Response schema for constraints is incorrect and duplicated.
parameters: t.Object({})will reject any non-empty object (TypeBox disallows additional props by default). Also duplicates the laterPropertyConstraintSchema.Refactor to reuse the canonical schema:
export const InstancePropertyConstraintsSchema = { params: t.Object({ instanceId: t.String({ description: 'Wikibase instance ID' }), propertyId: PropertyId, }), - response: { - 200: t.Object({ - data: t.Array( - t.Object({ - type: t.String(), - parameters: t.Object({}), - description: t.Optional(t.String()), - violationMessage: t.Optional(t.String()), - }), - ), - }), - 400: ApiError, - 404: ApiError, - 500: ApiError, - }, + response: { + 200: t.Object({ data: PropertyConstraintsResponseSchema }), + 400: ApiError, + 404: ApiError, + 500: ApiError, + }, detail: { summary: 'Get property constraints', description: 'Retrieve all constraints for a specific property', tags: ['Wikibase', 'Properties', 'Constraints'], }, }
159-213: Tighten ID types and make violation propertyId optional.Use
PropertyIdwhere appropriate. Violations/warnings may be item-level; makepropertyIdoptional.export const PropertyValidationSchema = { params: t.Object({ instanceId: t.String({ description: 'Wikibase instance ID' }), }), body: t.Object({ - propertyId: PropertyId, + propertyId: PropertyId, value: t.Any({ description: 'Value to validate against property constraints' }), context: t.Optional( t.Object({ entityId: t.Optional(t.String({ description: 'Entity ID for context' })), additionalProperties: t.Optional( t.Array( t.Object({ property: t.String(), value: t.Any(), }), { description: 'Additional properties for validation context' }, ), ), }), ), }), response: { data: t.Object({ isValid: t.Boolean(), violations: t.Array( t.Object({ constraintType: t.String(), message: t.String(), severity: t.Union([t.Literal('error'), t.Literal('warning')]), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), value: t.Optional(t.Any()), }), ), warnings: t.Array( t.Object({ constraintType: t.String(), message: t.String(), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), value: t.Optional(t.Any()), }), ), suggestions: t.Array(t.String()), }), }), },
215-267: Mirror the same tightening in schema-level validation.export const SchemaValidationSchema = { params: t.Object({ instanceId: t.String({ description: 'Wikibase instance ID' }), }), body: t.Object({ schema: t.Any({ description: 'Schema object to validate' }), options: t.Optional( t.Object({ strictMode: t.Optional( t.Boolean({ description: 'Enable strict validation mode', default: false }), ), includeWarnings: t.Optional( t.Boolean({ description: 'Include warnings in validation results', default: true }), ), validateReferences: t.Optional( t.Boolean({ description: 'Validate referenced entities', default: false }), ), }), ), }), response: { data: t.Object({ isValid: t.Boolean(), violations: t.Array( t.Object({ constraintType: t.String(), message: t.String(), severity: t.Union([t.Literal('error'), t.Literal('warning')]), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), value: t.Optional(t.Any()), }), ), warnings: t.Array( t.Object({ constraintType: t.String(), message: t.String(), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), value: t.Optional(t.Any()), }), ), suggestions: t.Array(t.String()), }), }), },
🧹 Nitpick comments (39)
backend/src/services/wikibase.service.ts (7)
62-64: Clear tokens when removing a client to avoid stale auth in memory.Call clearTokens() before deletion.
Apply this diff:
- removeClient(instanceId: string): boolean { - const clientRemoved = this.clients[instanceId] !== undefined - delete this.clients[instanceId] - return clientRemoved - } + removeClient(instanceId: string): boolean { + const client = this.clients[instanceId] + const clientRemoved = client !== undefined + if (clientRemoved) client.clearTokens?.() + delete this.clients[instanceId] + return clientRemoved + }
134-141: Prefer consistent response shape: request formatversion=2 for wbgetentities.Keeps structures stable across MW versions.
Apply this diff:
const params = { action: 'wbgetentities', ids: propertyId, languagefallback: true, format: 'json', + formatversion: 2, }
237-244: Ditto: formatversion=2 for getItem.Apply this diff:
const params = { action: 'wbgetentities', ids: itemId, languagefallback: true, format: 'json', - errorformat: 'raw', + formatversion: 2, + errorformat: 'raw', }
95-95: Improve error context in thrown messages.Include serialized error payload for easier debugging.
Apply this diff:
- throw new Error(`Search failed: ${response.error.code}`) + throw new Error(`Search failed: ${response.error.code} ${JSON.stringify(response.error)}`)(Apply in both searchProperties and searchItems.)
Also applies to: 205-205
22-28: Use Map<string, MediaWikiApiService> for clients to avoid prototype-key collisions.Record works, but Map is safer and expresses intent. Update get/set/delete accordingly.
Also applies to: 41-41, 50-50, 58-58, 62-64
22-28: Use Wikimedia-compliant User-Agent and lazy-initialize Wikidata client
Update theuserAgentto the recommended<clientName>/<version> (contactInfo) <library>/<version>format per Wikimedia policy and defer creating the defaultMediaWikiApiServiceuntil it’s first needed.
33-39: Expose authentication flow and honor timeout
- createClient accepts only
token(no username/password) and returns an anonymous client; require callers to invokeMediaWikiApiService.authenticate(username, password)or extendMediaWikiConfig/docs to support credential-based login.config.timeoutis never applied to thefetchcall; wire it viaAbortController/AbortSignalor remove the unused timeout field.package.json (1)
14-15: Avoid duplicate/ambiguous typecheck scriptsHaving both "tsc" and "typecheck" where "tsc" actually runs the workspace fan-out can confuse contributors who expect "tsc" to be the TypeScript CLI. Prefer a single canonical script.
Apply to remove the redundant alias:
- "tsc": "bun -F '*' typecheck",backend/src/types/wikibase-schema.ts (2)
3-7: Prefer explicit regex for Q/P IDs to tighten runtime validationTemplateLiteral with t.Numeric({ min: 1 }) yields a string at runtime but can be looser than a pattern check across some validators. A regex avoids edge cases and communicates intent.
-export const ItemId = t.TemplateLiteral([t.Literal('Q'), t.Numeric({ min: 1 })]) +export const ItemId = t.RegExp(/^Q[1-9]\d*$/) export type ItemId = typeof ItemId.static -export const PropertyId = t.TemplateLiteral([t.Literal('P'), t.Numeric({ min: 1 })]) +export const PropertyId = t.RegExp(/^P[1-9]\d*$/) export type PropertyId = typeof PropertyId.static
16-28: Centralize the datatype literals to avoid drift between backend and UIMultiple frontend files hardcode these strings. Exporting a single source of truth (array) reduces mismatch risk and helps generate options in UIs.
Inside this block, you can build from a constant:
// Place near the top of the file export const WIKIBASE_DATA_TYPES = [ 'string', 'wikibase-item', 'wikibase-property', 'quantity', 'time', 'globe-coordinate', 'url', 'external-id', 'monolingualtext', 'commonsMedia', ] as const export type WikibaseDataType = (typeof WIKIBASE_DATA_TYPES)[number]Then keep the runtime schema in sync:
-export const WikibaseDataType = t.Union([ - t.Literal('string'), - t.Literal('wikibase-item'), - t.Literal('wikibase-property'), - t.Literal('quantity'), - t.Literal('time'), - t.Literal('globe-coordinate'), - t.Literal('url'), - t.Literal('external-id'), - t.Literal('monolingualtext'), - t.Literal('commonsMedia'), -]) -export type WikibaseDataType = typeof WikibaseDataType.static +export const WikibaseDataType = t.Union(WIKIBASE_DATA_TYPES.map((v) => t.Literal(v))) +export type WikibaseDataType = typeof WikibaseDataType.staticfrontend/src/shared/types/drag-drop.ts (1)
1-1: Use strong typing for property IDsNow that PropertyId exists, prefer it over plain string to catch mapping mistakes at compile time.
Apply within the changed import line:
-import type { WikibaseDataType } from '@backend/types/wikibase-schema' +import type { WikibaseDataType, PropertyId } from '@backend/types/wikibase-schema'And update the field type (outside the changed hunk, shown for clarity):
export interface DropTarget { // ... acceptedTypes: WikibaseDataType[] language?: string propertyId?: PropertyId isRequired?: boolean }Also applies to: 39-43
frontend/src/features/wikibase-schema/composables/useValidation.ts (1)
1-1: Path update OK; consider typing propertyId with PropertyIdImport change is fine. As a small enhancement, also import PropertyId and use it in MappingInfo to prevent invalid IDs from slipping in.
Within the changed import line:
-import type { WikibaseDataType } from '@backend/types/wikibase-schema' +import type { WikibaseDataType, PropertyId } from '@backend/types/wikibase-schema'And update MappingInfo (outside the changed hunk, shown for clarity):
interface MappingInfo { // ... propertyId?: PropertyId }backend/src/types/mediawiki-api.ts (1)
369-377: Prefer WikibaseDataType for snak.datatype (interface) for parity with validatorsKeep interfaces consistent with the stricter validators and the union.
Apply:
export interface WikibaseEntitySnak { snaktype: 'value' | 'somevalue' | 'novalue' property: string - datatype?: string + datatype?: WikibaseDataType datavalue?: { value: any type: string } hash?: string }backend/src/types/wikibase-api.ts (9)
39-44: Tighten Snak.snaktype to a safe discriminantUse the concrete union to avoid accidental misuse and enable narrowing in consumers.
-export interface Snak { - snaktype: any +export interface Snak { + snaktype: 'value' | 'somevalue' | 'novalue' property: PropertyId datavalue?: SnakDataValue datatype: WikibaseDataType }
46-49: Narrow SnakDataValue.type (and optionally value) to align with WikibaseLooser typing hampers downstream validation. Consider this minimal tightening.
-export interface SnakDataValue { - value: any - type: string -} +export interface SnakDataValue { + // Keep `value` broad unless you introduce per-type value shapes + value: unknown + type: + | 'string' + | 'time' + | 'wikibase-entityid' + | 'quantity' + | 'monolingualtext' + | 'globecoordinate' + | 'url' + | 'external-id' + | 'commonsMedia' +}
9-17: Use PropertyId and strongly-typed claim keys on PropertyThis improves correctness and consistency with ItemDetails/PropertyDetails.
export interface Property { - id: string + id: PropertyId type: 'property' labels: Record<string, string> descriptions: Record<string, string> aliases: Record<string, string[]> datatype: WikibaseDataType - claims: Record<string, Claim[]> + claims: Record<PropertyId, Claim[]> }
19-27: Use ItemId and PropertyId-typed claim keys on ItemKeeps entity IDs and property keys strongly typed throughout.
export interface Item { - id: string + id: ItemId type: 'item' labels: Record<string, string> descriptions: Record<string, string> aliases: Record<string, string[]> - claims: Record<string, Claim[]> + claims: Record<PropertyId, Claim[]> sitelinks?: Record<string, SiteLink> }
29-37: Normalize field naming: qualifiers_order → qualifiersOrderPrefer conventional camelCase for internal shapes; reserve API wire names for IO mappers.
export interface Claim { id: string mainsnak: Snak qualifiers?: Record<PropertyId, Snak[]> - qualifiers_order?: PropertyId[] + qualifiersOrder?: PropertyId[] references?: Reference[] rank: StatementRank type: 'claim' }
51-55: Normalize field naming: snaks_order → snaksOrderAlign with TS conventions to reduce ambiguity with wire JSON’s
snaks-order.export interface Reference { hash: string snaks: Record<PropertyId, Snak[]> - snaks_order: PropertyId[] + snaksOrder: PropertyId[] }
95-100: Type constraint parameters by PropertyId keysConstraint parameters are keyed by property IDs (e.g., P2306). Tighten the map key type.
export interface PropertyConstraint { type: string - parameters: Record<string, SnakDataValue> + parameters: Record<PropertyId, SnakDataValue> description?: string violationMessage?: string }
144-151: Type propertyId fields as PropertyId in violationsStrengthens contracts and avoids accidental non-P IDs.
export interface ConstraintViolation { constraintType: string message: string severity: 'error' | 'warning' - propertyId: string + propertyId: PropertyId value?: SnakDataValue }
152-158: Type propertyId fields as PropertyId in warningsSame rationale as above.
export interface ConstraintWarning { constraintType: string message: string - propertyId: string + propertyId: PropertyId value?: SnakDataValue }frontend/src/features/wikibase-schema/composables/useReferenceValueMapping.ts (4)
55-57: Guard against non-string sample valuesAvoid runtime errors if sample values aren’t strings.
- if (columnInfo.sampleValues.some((val) => val.startsWith('http'))) { + if (columnInfo.sampleValues.some((val) => typeof val === 'string' && val.startsWith('http'))) { return 'url' }
109-115: Null-safe source checks in column mapping validation
typeof null === 'object'. Add a truthy check.- const source = snak.value.source - if (typeof source === 'object' && !source.columnName) { + const source = snak.value.source + if (source && typeof source === 'object' && !('columnName' in source) || (source && typeof source === 'object' && !source.columnName)) { errors.push('Column name is required for column mapping') } - if (typeof source === 'object' && source.dataType) { + if (source && typeof source === 'object' && source.dataType) { const isCompatible = isReferenceDataTypeCompatible(source.dataType, snak.property.dataType) if (!isCompatible) {
158-162: De-duplicate duplicate property IDs in error reportCleaner feedback for users.
- const duplicates = propertyIds.filter((id, index) => propertyIds.indexOf(id) !== index) - if (duplicates.length > 0) { - errors.push(`Duplicate properties in reference: ${duplicates.join(', ')}`) + const seen = new Set<string>() + const dups = [...new Set(propertyIds.filter((id) => (seen.has(id) ? true : (seen.add(id), false))))]] + if (dups.length > 0) { + errors.push(`Duplicate properties in reference: ${dups.join(', ')}`) }
14-21: Type the compatibility map with WikibaseDataType keysImproves safety and editor help.
- const referenceDataTypeCompatibility: Record<string, string[]> = { + const referenceDataTypeCompatibility: Partial<Record<WikibaseDataType, readonly string[]>> = { url: ['VARCHAR', 'TEXT', 'STRING'], time: ['DATE', 'DATETIME', 'TIMESTAMP'], 'wikibase-item': ['VARCHAR', 'TEXT', 'STRING'], string: ['VARCHAR', 'TEXT', 'STRING'], 'external-id': ['VARCHAR', 'TEXT', 'STRING'], quantity: ['INTEGER', 'DECIMAL', 'NUMERIC', 'FLOAT'], }frontend/src/features/wikibase-schema/composables/useSchemaBuilder.ts (1)
23-33: Safe default types for IDs in function signaturesOnce
UUIDis localized, ensure function params use it consistently without importing Node modules.- const buildSchema = ( - id: UUID, - projectId: UUID, + const buildSchema = ( + id: UUID, + projectId: UUID, name: string, wikibaseUrl: string,(After applying the previous import fix, no further change needed—this is a no-op if you adopt
type UUID = string.)frontend/src/features/wikibase-schema/composables/useStatementEditor.ts (1)
55-66: Avoid drifting type option catalogs across composableswikibaseDataTypes here duplicates the list maintained in useValueMapping. Extract a single shared constant (e.g., @frontend/shared/constants/wikibaseDataTypes.ts) to prevent divergence.
frontend/src/features/wikibase-schema/composables/useStatementConfig.ts (2)
72-81: Keep column source strongly typed instead of storing raw stringsCurrently, sourceValue setter assigns a string to value.source even for column mappings, which likely violates ValueMapping typing and forces downstream shape checks.
Apply:
const sourceValue = computed({ get: () => { - return typeof currentStatement.value.value.source === 'string' - ? currentStatement.value.value.source - : '' + const s = currentStatement.value.value.source + return typeof s === 'string' ? s : s?.columnName ?? '' }, set: (value: string) => { - currentStatement.value.value.source = value + if (currentStatement.value.value.type === 'column') { + const prev = currentStatement.value.value.source + currentStatement.value.value.source = + typeof prev === 'object' + ? { ...prev, columnName: value } + : { columnName: value, dataType: 'VARCHAR' } + } else { + currentStatement.value.value.source = value + } }, })
84-96: Make canSaveStatement robust to both string and object source shapesIf adopting the strongly typed column source above, adjust validation to accept either shape.
Apply:
- const hasSource = - typeof currentStatement.value.value.source === 'string' - ? currentStatement.value.value.source.trim() !== '' - : false + const s = currentStatement.value.value.source + const hasSource = + typeof s === 'string' ? s.trim() !== '' : !!s?.columnName && s.columnName.trim() !== ''frontend/src/features/wikibase-schema/composables/useStatementDataTypeValidation.ts (1)
106-109: Replace magic index with named constant for readabilityClarify how “optimal” is determined to avoid magic numbers.
- const isOptimal = compatibleTypes.indexOf(valueMapping.dataType) <= 1 // First two are most optimal + const OPTIMAL_TYPE_LIMIT = 2 + const isOptimal = compatibleTypes.slice(0, OPTIMAL_TYPE_LIMIT).includes(valueMapping.dataType)frontend/src/features/wikibase-schema/composables/useValueMapping.ts (1)
31-42: De-duplicate wikibaseDataTypes across composablesShare a single exported list to avoid drift between this file and useStatementEditor.
backend/src/services/constraint-validation.service.ts (1)
488-489: Consider adding runtime validation for the PropertyId cast.The function now accepts a generic
Record<string, unknown[]>and casts keys toPropertyId[]on line 494. While this maintains backward compatibility, it bypasses TypeScript's type safety. Consider validating that the keys match the PropertyId pattern (P followed by a number) before casting.Consider adding validation:
async validateSchema( instanceId: string, schema: Record<string, unknown[]>, ): Promise<ValidationResult> { const allViolations: ConstraintViolation[] = [] const allWarnings: ConstraintWarning[] = [] const allSuggestions: string[] = [] - const propertyIds = Object.keys(schema) as PropertyId[] + // Validate property IDs match expected pattern + const propertyIds = Object.keys(schema).filter(key => /^P\d+$/.test(key)) as PropertyId[] + const invalidKeys = Object.keys(schema).filter(key => !/^P\d+$/.test(key)) + + if (invalidKeys.length > 0) { + allWarnings.push({ + constraintType: 'invalid_property_id', + message: `Invalid property IDs found: ${invalidKeys.join(', ')}`, + propertyId: 'schema', + }) + }Also applies to: 494-500
backend/src/api/wikibase/entities.ts (2)
43-59: Consider making the relevance scoring more sophisticated.The current implementation assigns a fixed score (1.0 for label matches, 0.8 for others). Consider implementing a more nuanced scoring system based on match quality, exact vs. partial matches, and match position.
Example enhancement:
relevanceScore: calculateRelevanceScore(property.match, q),Where
calculateRelevanceScorecould consider factors like:
- Exact match vs. partial match
- Match at beginning vs. middle of string
- Match type (label, alias, description)
- Edit distance for fuzzy matches
108-113: Consider supporting batch validation for multiple values.The current implementation wraps a single value in an array, but the underlying service already supports validating multiple values. Consider enhancing the endpoint to accept either a single value or an array of values.
- async ({ params: { instanceId }, body: { propertyId, value } }) => { + async ({ params: { instanceId }, body: { propertyId, value, values } }) => { + const valuesToValidate = values ?? (value !== undefined ? [value] : []) const validationResult = await constraintValidationService.validateProperty( instanceId, propertyId, - [value], // Convert single value to array as expected by the service + valuesToValidate, )And update the schema to accept either:
value: t.Optional(t.Any()), values: t.Optional(t.Array(t.Any())),backend/src/api/wikibase/constraints.ts (3)
9-9: Avoid type assertions by tightening the schema.The handler later casts
propertyId as PropertyId. Prefer validating it at the schema level so the cast isn’t needed. I’ve proposed schema fixes in schemas.ts comments.
21-28: Return envelope LGTM; drop the cast after schema fix.Handler is clean. Once
PropertyConstraintsRouteSchema.params.propertyIdusesPropertyId, you can removeas PropertyId.
33-42: ValidatepropertyIdshape via schema, not at callsite.Same note as above; once
PropertyValidationRequestSchema.propertyIdisPropertyId, you can passpropertyIddirectly without a cast.backend/src/api/wikibase/schemas.ts (1)
337-356: Make constraint violation IDs strongly typed and optional.export const ConstraintViolationSchema = t.Object({ constraintType: t.String(), message: t.String(), severity: t.Union([t.Literal('error'), t.Literal('warning')]), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), value: t.Optional(t.Any()), }) export const ConstraintWarningSchema = t.Object({ constraintType: t.String(), message: t.String(), - propertyId: t.String(), + propertyId: t.Optional(PropertyId), })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (36)
backend/package.json(1 hunks)backend/scripts/generate-wikibase-typebox.ts(0 hunks)backend/src/api/project/project.wikibase.ts(3 hunks)backend/src/api/wikibase/constraints.ts(2 hunks)backend/src/api/wikibase/entities.ts(1 hunks)backend/src/api/wikibase/handlers.ts(0 hunks)backend/src/api/wikibase/index.ts(0 hunks)backend/src/api/wikibase/instances.ts(0 hunks)backend/src/api/wikibase/schemas.ts(9 hunks)backend/src/index.ts(1 hunks)backend/src/services/constraint-validation.service.ts(7 hunks)backend/src/services/mediawiki-config.service.ts(0 hunks)backend/src/services/wikibase.service.ts(10 hunks)backend/src/types/mediawiki-api.ts(5 hunks)backend/src/types/wikibase-api.ts(5 hunks)backend/src/types/wikibase-schema.ts(1 hunks)backend/tests/api/project/project.wikibase.test.ts(1 hunks)backend/tests/api/wikibase/entities.test.ts(4 hunks)frontend/src/features/data-processing/composables/useColumnDataTypeIndicators.ts(1 hunks)frontend/src/features/data-processing/composables/useDataTypeCompatibility.ts(1 hunks)frontend/src/features/wikibase-schema/composables/__tests__/useStatementConfig.test.ts(1 hunks)frontend/src/features/wikibase-schema/composables/__tests__/useStatementDataTypeValidation.test.ts(1 hunks)frontend/src/features/wikibase-schema/composables/__tests__/useStatementEditor.test.ts(1 hunks)frontend/src/features/wikibase-schema/composables/__tests__/useValidation.test.ts(1 hunks)frontend/src/features/wikibase-schema/composables/__tests__/useValueMapping.test.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useReferenceValueMapping.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useSchemaBuilder.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useStatementConfig.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useStatementDataTypeValidation.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useStatementEditor.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useValidation.ts(1 hunks)frontend/src/features/wikibase-schema/composables/useValueMapping.ts(2 hunks)frontend/src/features/wikibase-schema/stores/schema.store.ts(4 hunks)frontend/src/shared/stores/__tests__/drag-drop.store.test.ts(1 hunks)frontend/src/shared/types/drag-drop.ts(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (5)
- backend/src/api/wikibase/index.ts
- backend/src/api/wikibase/instances.ts
- backend/scripts/generate-wikibase-typebox.ts
- backend/src/api/wikibase/handlers.ts
- backend/src/services/mediawiki-config.service.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}: 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:
frontend/src/features/wikibase-schema/composables/__tests__/useStatementConfig.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValueMapping.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementDataTypeValidation.test.tsfrontend/src/features/wikibase-schema/composables/useStatementConfig.tsfrontend/src/features/data-processing/composables/useColumnDataTypeIndicators.tsfrontend/src/shared/stores/__tests__/drag-drop.store.test.tsfrontend/src/features/wikibase-schema/composables/useSchemaBuilder.tsfrontend/src/features/wikibase-schema/composables/useValidation.tsfrontend/src/features/wikibase-schema/composables/useStatementDataTypeValidation.tsfrontend/src/features/data-processing/composables/useDataTypeCompatibility.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValidation.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementEditor.test.tsfrontend/src/features/wikibase-schema/composables/useReferenceValueMapping.tsbackend/tests/api/project/project.wikibase.test.tsfrontend/src/features/wikibase-schema/composables/useStatementEditor.tsbackend/src/types/wikibase-schema.tsfrontend/src/features/wikibase-schema/stores/schema.store.tsbackend/src/api/project/project.wikibase.tsfrontend/src/features/wikibase-schema/composables/useValueMapping.tsfrontend/src/shared/types/drag-drop.tsbackend/src/index.tsbackend/src/services/constraint-validation.service.tsbackend/src/api/wikibase/entities.tsbackend/src/types/wikibase-api.tsbackend/tests/api/wikibase/entities.test.tsbackend/src/api/wikibase/schemas.tsbackend/src/types/mediawiki-api.tsbackend/src/api/wikibase/constraints.tsbackend/src/services/wikibase.service.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:
frontend/src/features/wikibase-schema/composables/__tests__/useStatementConfig.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValueMapping.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementDataTypeValidation.test.tsfrontend/src/shared/stores/__tests__/drag-drop.store.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValidation.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementEditor.test.tsbackend/tests/api/project/project.wikibase.test.tsbackend/tests/api/wikibase/entities.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 ofwebpackoresbuildfor building HTML, TypeScript, or CSS files
Files:
frontend/src/features/wikibase-schema/composables/__tests__/useStatementConfig.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValueMapping.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementDataTypeValidation.test.tsfrontend/src/features/wikibase-schema/composables/useStatementConfig.tsfrontend/src/features/data-processing/composables/useColumnDataTypeIndicators.tsfrontend/src/shared/stores/__tests__/drag-drop.store.test.tsfrontend/src/features/wikibase-schema/composables/useSchemaBuilder.tsfrontend/src/features/wikibase-schema/composables/useValidation.tsfrontend/src/features/wikibase-schema/composables/useStatementDataTypeValidation.tsfrontend/src/features/data-processing/composables/useDataTypeCompatibility.tsfrontend/src/features/wikibase-schema/composables/__tests__/useValidation.test.tsfrontend/src/features/wikibase-schema/composables/__tests__/useStatementEditor.test.tsfrontend/src/features/wikibase-schema/composables/useReferenceValueMapping.tsbackend/tests/api/project/project.wikibase.test.tsfrontend/src/features/wikibase-schema/composables/useStatementEditor.tsbackend/src/types/wikibase-schema.tsfrontend/src/features/wikibase-schema/stores/schema.store.tsbackend/src/api/project/project.wikibase.tsfrontend/src/features/wikibase-schema/composables/useValueMapping.tsfrontend/src/shared/types/drag-drop.tsbackend/src/index.tsbackend/src/services/constraint-validation.service.tsbackend/src/api/wikibase/entities.tsbackend/src/types/wikibase-api.tsbackend/tests/api/wikibase/entities.test.tsbackend/src/api/wikibase/schemas.tsbackend/src/types/mediawiki-api.tsbackend/src/api/wikibase/constraints.tsbackend/src/services/wikibase.service.ts
package.json
📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)
package.json: Usebun installinstead ofnpm install,yarn install, orpnpm installfor dependency installation
Usebun run <script>instead ofnpm run <script>,yarn run <script>, orpnpm run <script>for running scripts
Files:
package.json
🧠 Learnings (5)
📚 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 **/*.{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.jsonbackend/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.$` (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 **/*.{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
🧬 Code graph analysis (8)
backend/src/api/project/project.wikibase.ts (1)
backend/src/types/wikibase-schema.ts (4)
PropertyId(6-6)PropertyId(7-7)ItemId(3-3)ItemId(4-4)
backend/src/services/constraint-validation.service.ts (1)
backend/src/types/wikibase-schema.ts (2)
PropertyId(6-6)PropertyId(7-7)
backend/src/api/wikibase/entities.ts (3)
backend/src/plugins/wikibase.ts (1)
wikibasePlugin(4-7)backend/src/api/wikibase/schemas.ts (6)
PropertySearchSchema(78-104)InstancePropertyDetailsSchema(107-130)InstancePropertyConstraintsSchema(132-157)PropertyValidationSchema(159-213)SchemaValidationSchema(215-267)ItemSearchSchema(283-308)backend/src/services/constraint-validation.service.ts (1)
constraintValidationService(567-567)
backend/src/types/wikibase-api.ts (2)
backend/src/types/wikibase-schema.ts (8)
WikibaseDataType(16-27)WikibaseDataType(28-28)PropertyId(6-6)PropertyId(7-7)StatementRank(9-13)StatementRank(14-14)ItemId(3-3)ItemId(4-4)backend/src/api/project/project.wikibase.ts (1)
Reference(79-79)
backend/src/api/wikibase/schemas.ts (1)
backend/src/types/wikibase-schema.ts (2)
WikibaseDataType(16-27)WikibaseDataType(28-28)
backend/src/types/mediawiki-api.ts (1)
backend/src/types/wikibase-schema.ts (2)
WikibaseDataType(16-27)WikibaseDataType(28-28)
backend/src/api/wikibase/constraints.ts (3)
backend/src/services/constraint-validation.service.ts (1)
constraintValidationService(567-567)backend/src/types/wikibase-schema.ts (2)
PropertyId(6-6)PropertyId(7-7)backend/src/api/wikibase/schemas.ts (4)
PropertyConstraintsRouteSchema(370-388)PropertyValidationConstraintsRouteSchema(391-406)SchemaValidationConstraintsRouteSchema(409-425)CacheClearRouteSchema(428-446)
backend/src/services/wikibase.service.ts (4)
backend/src/services/mediawiki-api.service.ts (1)
MediaWikiApiService(3-76)backend/src/types/mediawiki-api.ts (4)
MediaWikiConfig(11-18)WikibaseSearchEntityResponse(338-345)WikibaseSearchEntityResult(326-336)WikibaseGetEntitiesResponse(411-414)backend/src/types/wikibase-schema.ts (4)
PropertyId(6-6)PropertyId(7-7)ItemId(3-3)ItemId(4-4)backend/src/types/wikibase-api.ts (2)
PropertySearchResult(84-93)ItemSearchResult(110-118)
🔇 Additional comments (36)
backend/package.json (3)
14-15: OK to keep backend-local tsc; aligns with root fan-out"types": repo uses root "bun -F '*' typecheck" and backend keeps a plain "tsc" for local checks. This is reasonable.
18-18: Alpha bump of @duckdb/node-api — validate on CI matricesUpgrading to 1.3.4-alpha.27 is fine, but since it’s an alpha and a Node-API binding, please ensure CI covers Linux/macOS and Bun 1.2.x to catch ABI/runtime quirks.
Would you confirm dev/start flows and relevant integration tests pass on Bun 1.2.x across your CI runners?
22-22: Catalog-pinned elysia looks goodUsing "catalog:" keeps backend aligned with the workspace version; no action needed.
backend/src/types/wikibase-schema.ts (1)
9-15: StatementRank union is clear and minimalThe literal union matches common Wikibase usage. Looks good.
frontend/src/features/data-processing/composables/useColumnDataTypeIndicators.ts (1)
1-1: Path update to centralized types looks goodType-only import swap; no behavioral change.
frontend/src/features/data-processing/composables/useDataTypeCompatibility.ts (1)
1-1: Path update to centralized types looks goodType-only import swap; compatible with existing usage.
frontend/src/shared/stores/__tests__/drag-drop.store.test.ts (1)
1-1: Tests updated to use centralized typesImport swap to @backend/types/wikibase-schema aligns tests with the new source of truth. Looks good.
backend/tests/api/project/project.wikibase.test.ts (1)
3-3: Type-only import migration looks correctSwitching ItemId/PropertyId to the centralized type module with a type-only import is consistent with the PR direction and prevents runtime imports. LGTM.
backend/src/types/wikibase-api.ts (1)
51-55: No conflictingReferencetype found
Only a singleReferenceinterface is exported (backend/src/types/wikibase-api.ts:51); no otherReferencedefinitions or imports exist.Likely an incorrect or invalid review comment.
frontend/src/features/wikibase-schema/composables/useReferenceValueMapping.ts (2)
6-6: LGTM: import path update aligns with centralized typesNo runtime impact; matches backend type consolidation.
1-7: All referenced types remain exported frombackend/src/api/project/project.wikibase.ts. No changes needed.frontend/src/features/wikibase-schema/composables/useSchemaBuilder.ts (2)
80-95: LGTM: Statement builder with default rank and UUIDsStructure matches the schema contracts; default rank is sensible.
1-12: DOM lib already enabled; crypto.randomUUID() types available
tsconfig.json’scompilerOptions.libincludes"dom"(alongside"esnext"), so no Node polyfill is required forcrypto.randomUUID().frontend/src/features/wikibase-schema/composables/__tests__/useValueMapping.test.ts (1)
1-2: WikibaseDataType import migration verified
No instances of importing WikibaseDataType from @backend/api/project/project.wikibase remain.frontend/src/features/wikibase-schema/composables/useStatementEditor.ts (1)
1-2: Type imports centralized — LGTMImporting StatementRank and WikibaseDataType from @backend/types/wikibase-schema aligns with the new type surface.
frontend/src/features/wikibase-schema/composables/__tests__/useStatementDataTypeValidation.test.ts (1)
1-2: Type import path updated correctlyThis keeps tests aligned with the centralized type definitions.
frontend/src/features/wikibase-schema/composables/__tests__/useStatementConfig.test.ts (1)
1-1: Centralized StatementRank/PropertyId import — looks goodMatches the backend type module and keeps tests consistent.
frontend/src/features/wikibase-schema/composables/useStatementConfig.ts (1)
1-2: Centralized type imports — LGTMThe move to @backend/types/wikibase-schema for StatementRank and WikibaseDataType is consistent with the PR.
frontend/src/features/wikibase-schema/composables/__tests__/useValidation.test.ts (1)
1-1: WikibaseDataType import path change — OKTests remain on bun:test and only the type source moved.
frontend/src/features/wikibase-schema/composables/useStatementDataTypeValidation.ts (1)
1-2: Centralized type import — LGTMNo runtime impact; aligns with the new backend type module.
frontend/src/features/wikibase-schema/composables/useValueMapping.ts (1)
1-2: Type import centralization — goodWikibaseDataType now sourced from @backend/types/wikibase-schema as intended.
frontend/src/features/wikibase-schema/composables/__tests__/useStatementEditor.test.ts (1)
1-2: LGTM! Type imports correctly migrated to the new module structure.The migration of
StatementRankandWikibaseDataTypeto@backend/types/wikibase-schemaaligns with the PR's consolidation of Wikibase types. The imports from@backend/api/project/project.wikibaseremain appropriate forPropertyReferenceandValueMapping.backend/src/index.ts (1)
5-5: LGTM! Clean removal of deprecated API surface.The removal of
wikibaseInstanceApifrom the imports aligns with the PR's shift to a route-schema-driven approach with instance-scoped paths. The remaining imports for constraints and entities APIs are appropriate.backend/src/services/constraint-validation.service.ts (1)
8-8: LGTM! Type import correctly migrated to the new module.The migration of
PropertyIdimport fromwikibase-sdkto@backend/types/wikibase-schemais consistent with the PR's type consolidation strategy.backend/tests/api/wikibase/entities.test.ts (1)
33-36: LGTM! Test correctly updated to use instance-scoped API.The migration to
api.wikibase({ instanceId: 'wikidata' })properly reflects the new per-instance API surface. The chained method calls and query structure align with the updated API design.backend/src/api/project/project.wikibase.ts (1)
6-6: LGTM! Types correctly migrated to use centralized Wikibase schema types.The migration to use strongly-typed identifiers (
PropertyId,ItemId) and enums (WikibaseDataType,StatementRank) from@backend/types/wikibase-schemaimproves type safety and aligns with the PR's consolidation strategy.Also applies to: 30-31, 42-43, 46-47, 52-53, 86-86, 112-112
backend/src/api/wikibase/entities.ts (2)
18-18: LGTM! API prefix correctly updated.The change from
/api/wikibase/entitiesto/api/wikibasealigns with the new instance-scoped path structure.
79-85: Good defensive programming with conditional constraint fetching.The implementation correctly checks the
includeConstraintsflag before making the additional API call to fetch constraints, which helps optimize performance when constraints aren't needed.backend/src/api/wikibase/constraints.ts (2)
1-6: Good shift to centralized route schemas.Importing route schemas from a single module simplifies validation and docs consistency.
47-52: Schema validation route: looks good.Consistent envelope and error handling.
backend/src/api/wikibase/schemas.ts (6)
9-10: Strongly-typed datatype: good upgrade.Using
WikibaseDataTypehere tightens validation and reduces downstream branching.
17-25: ID shape relaxed to string — verify downstream consumers.Switching
PropertyDetailsSchema.idtot.String()may allow invalid IDs to leak. If clients rely onP\\d+, consider keepingPropertyId, or at least validate at boundaries.Would you like a quick repo scan to list all consumers of
PropertyDetailsSchemaand check for assumptions on ID shape?
279-281: Reuse of response/detail blocks: fine.Nice DRY reuse from
InstancePropertyDetailsSchema.
292-295: Item search language fallback: good default.Defaults and description are clear and consistent with property search.
Also applies to: 305-306
310-314: Instance-scoped item details: good alignment with path design.
427-446: Docs say “clear all if not provided” — ensure handler honors it.After adjusting the handler to not default
instance(see constraints.ts comment), this schema’s description will match behavior.
| async ({ query: { instance = 'wikidata' } }) => { | ||
| constraintValidationService.clearCache(instance) | ||
| return { data: { message: 'Cache cleared successfully' } } | ||
| }, | ||
| { | ||
| query: t.Object({ | ||
| instance: t.Optional( | ||
| t.String({ | ||
| description: | ||
| 'Wikibase instance ID to clear cache for (optional - clears all if not provided)', | ||
| }), | ||
| ), | ||
| }), | ||
| response: { | ||
| 200: t.Object({ data: t.Object({ message: t.String() }) }), | ||
| 500: ApiError, | ||
| }, | ||
| detail: { | ||
| summary: 'Clear constraint cache', | ||
| description: 'Clear the constraint validation cache for better performance', | ||
| tags: ['Wikibase', 'Constraints', 'Cache'], | ||
| }, | ||
| }, | ||
| CacheClearRouteSchema, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cache clearing semantics are wrong; also ensure we await async clears.
The schema says “optional - clears all if not provided”, but the handler defaults instance = 'wikidata', making “clear all” unreachable. Also, if clearCache is async, not awaiting can race with the response.
Apply this diff:
- .delete(
- '/cache',
- async ({ query: { instance = 'wikidata' } }) => {
- constraintValidationService.clearCache(instance)
- return { data: { message: 'Cache cleared successfully' } }
- },
- CacheClearRouteSchema,
- )
+ .delete(
+ '/cache',
+ async ({ query }) => {
+ await constraintValidationService.clearCache(query.instance)
+ return {
+ data: {
+ message:
+ query.instance
+ ? `Cache cleared for instance "${query.instance}"`
+ : 'Cache cleared for all instances',
+ },
+ }
+ },
+ CacheClearRouteSchema,
+ )📝 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.
| async ({ query: { instance = 'wikidata' } }) => { | |
| constraintValidationService.clearCache(instance) | |
| return { data: { message: 'Cache cleared successfully' } } | |
| }, | |
| { | |
| query: t.Object({ | |
| instance: t.Optional( | |
| t.String({ | |
| description: | |
| 'Wikibase instance ID to clear cache for (optional - clears all if not provided)', | |
| }), | |
| ), | |
| }), | |
| response: { | |
| 200: t.Object({ data: t.Object({ message: t.String() }) }), | |
| 500: ApiError, | |
| }, | |
| detail: { | |
| summary: 'Clear constraint cache', | |
| description: 'Clear the constraint validation cache for better performance', | |
| tags: ['Wikibase', 'Constraints', 'Cache'], | |
| }, | |
| }, | |
| CacheClearRouteSchema, | |
| ) | |
| .delete( | |
| '/cache', | |
| async ({ query }) => { | |
| await constraintValidationService.clearCache(query.instance) | |
| return { | |
| data: { | |
| message: | |
| query.instance | |
| ? `Cache cleared for instance "${query.instance}"` | |
| : 'Cache cleared for all instances', | |
| }, | |
| } | |
| }, | |
| CacheClearRouteSchema, | |
| ) |
🤖 Prompt for AI Agents
In backend/src/api/wikibase/constraints.ts around lines 57-62, the handler
incorrectly defaults query.instance to 'wikidata' making the "clear all"
behavior unreachable and it doesn't await the async cache clear; change the
handler to accept instance as optional (do not default to 'wikidata'), call and
await constraintValidationService.clearCache(instance) so undefined means clear
all, and then return the success response after the awaited call completes.
| export const PropertyValidationRequestSchema = t.Object({ | ||
| propertyId: t.String(), | ||
| values: t.Array(t.Any()), | ||
| }) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use PropertyId in request body.
export const PropertyValidationRequestSchema = t.Object({
- propertyId: t.String(),
+ propertyId: PropertyId,
values: t.Array(t.Any()),
})📝 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.
| export const PropertyValidationRequestSchema = t.Object({ | |
| propertyId: t.String(), | |
| values: t.Array(t.Any()), | |
| }) | |
| export const PropertyValidationRequestSchema = t.Object({ | |
| propertyId: PropertyId, | |
| values: t.Array(t.Any()), | |
| }) |
🤖 Prompt for AI Agents
In backend/src/api/wikibase/schemas.ts around lines 360 to 364, the
PropertyValidationRequestSchema currently uses t.String() for propertyId;
replace that with the existing PropertyId codec/type (e.g., PropertyId) so the
request body validates against the canonical property id format, and ensure
PropertyId is imported where this schema is defined (or export it if missing).
| // Property Constraints Route Schemas | ||
| export const PropertyConstraintsRouteSchema = { | ||
| params: t.Object({ | ||
| propertyId: t.String({ description: 'Property ID' }), | ||
| }), | ||
| query: t.Object({ | ||
| instance: t.Optional(t.String({ description: 'Wikibase instance ID', default: 'wikidata' })), | ||
| }), | ||
| response: { | ||
| 200: t.Object({ data: PropertyConstraintsResponseSchema }), | ||
| 400: ApiError, | ||
| 404: ApiError, | ||
| 500: ApiError, | ||
| }, | ||
| detail: { | ||
| summary: 'Get property constraints', | ||
| description: 'Retrieve all constraints defined for a specific property', | ||
| tags: ['Wikibase', 'Constraints'], | ||
| }, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Param should be PropertyId to avoid handler casts.
export const PropertyConstraintsRouteSchema = {
params: t.Object({
- propertyId: t.String({ description: 'Property ID' }),
+ propertyId: PropertyId,
}),
query: t.Object({
instance: t.Optional(t.String({ description: 'Wikibase instance ID', default: 'wikidata' })),
}),📝 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.
| // Property Constraints Route Schemas | |
| export const PropertyConstraintsRouteSchema = { | |
| params: t.Object({ | |
| propertyId: t.String({ description: 'Property ID' }), | |
| }), | |
| query: t.Object({ | |
| instance: t.Optional(t.String({ description: 'Wikibase instance ID', default: 'wikidata' })), | |
| }), | |
| response: { | |
| 200: t.Object({ data: PropertyConstraintsResponseSchema }), | |
| 400: ApiError, | |
| 404: ApiError, | |
| 500: ApiError, | |
| }, | |
| detail: { | |
| summary: 'Get property constraints', | |
| description: 'Retrieve all constraints defined for a specific property', | |
| tags: ['Wikibase', 'Constraints'], | |
| }, | |
| } | |
| // Property Constraints Route Schemas | |
| export const PropertyConstraintsRouteSchema = { | |
| params: t.Object({ | |
| propertyId: PropertyId, | |
| }), | |
| query: t.Object({ | |
| instance: t.Optional(t.String({ description: 'Wikibase instance ID', default: 'wikidata' })), | |
| }), | |
| response: { | |
| 200: t.Object({ data: PropertyConstraintsResponseSchema }), | |
| 400: ApiError, | |
| 404: ApiError, | |
| 500: ApiError, | |
| }, | |
| detail: { | |
| summary: 'Get property constraints', | |
| description: 'Retrieve all constraints defined for a specific property', | |
| tags: ['Wikibase', 'Constraints'], | |
| }, | |
| } |
🤖 Prompt for AI Agents
In backend/src/api/wikibase/schemas.ts around lines 369 to 388, the params
object uses "propertyId" but the handler expects "PropertyId", causing casts;
rename the params key to PropertyId (i.e. t.Object({ PropertyId: t.String({
description: 'Property ID' }) })) and ensure any default/description stays the
same and that any references in the route/handler use params.PropertyId to match
the schema.
| export const PropertyValidationConstraintsRouteSchema = { | ||
| body: PropertyValidationRequestSchema, | ||
| query: t.Object({ | ||
| instance: t.Optional(t.String({ description: 'Wikibase instance ID', default: 'wikidata' })), | ||
| }), | ||
| response: { | ||
| 200: t.Object({ data: ValidationResultSchema }), | ||
| 400: ApiError, | ||
| 500: ApiError, | ||
| }, | ||
| detail: { | ||
| summary: 'Validate property values', | ||
| description: 'Validate property values against their defined constraints', | ||
| tags: ['Wikibase', 'Constraints', 'Validation'], | ||
| }, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Body propertyId should also be PropertyId.
export const PropertyValidationConstraintsRouteSchema = {
- body: PropertyValidationRequestSchema,
+ body: PropertyValidationRequestSchema, // with PropertyId as aboveAnd ensure PropertyValidationRequestSchema.propertyId is PropertyId per prior suggestion.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In backend/src/api/wikibase/schemas.ts around lines 391-406, the route schema
uses PropertyValidationRequestSchema for body but that schema's propertyId must
be the typed PropertyId; update PropertyValidationRequestSchema so its
propertyId field uses the existing PropertyId type (instead of a plain string or
other type) and ensure the PropertyValidationConstraintsRouteSchema.body
continues to reference the updated request schema; keep types consistent and
import/reference PropertyId where necessary.
| formatVersion: 2, | ||
| strictlanguage: !languageFallback, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong parameter name: use formatversion (lowercase) for MW API.
MediaWiki expects formatversion, not formatVersion. Current calls may return v1 structures.
Apply this diff:
- formatVersion: 2,
+ formatversion: 2,(Apply in both searchProperties and searchItems.)
Also applies to: 198-200
🤖 Prompt for AI Agents
In backend/src/services/wikibase.service.ts around lines 88-90 (and also update
lines ~198-200), the request body uses the wrong parameter name formatVersion;
MediaWiki expects formatversion (all lowercase), causing the API to return v1
structures. Replace formatVersion with formatversion in both searchProperties
and searchItems request payloads and ensure the value (e.g., 2) and surrounding
keys (strictlanguage etc.) remain unchanged so the API returns v2 structures.
| import type { WikibaseDataType } from '@backend/types/wikibase-schema' | ||
| import { t } from 'elysia' | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reuse the union schema for Wikibase data types in Elysia validators
Interfaces use WikibaseDataType, but Elysia schemas accept any string. Reuse the union from @backend/types/wikibase-schema to keep validation and types in sync.
Apply:
-import type { WikibaseDataType } from '@backend/types/wikibase-schema'
+import { WikibaseDataType as WikibaseDataTypeSchema } from '@backend/types/wikibase-schema'
+import type { WikibaseDataType } from '@backend/types/wikibase-schema'
@@
export const WikibaseSnakSchema = t.Object({
snaktype: t.String(),
property: t.String(),
hash: t.Optional(t.String()),
datavalue: t.Optional(WikibaseDataValueSchema),
- datatype: t.Optional(t.String()),
+ datatype: t.Optional(WikibaseDataTypeSchema),
})
@@
export const WikibaseEntitySchema = t.Object({
@@
- datatype: t.Optional(t.String()),
+ datatype: t.Optional(WikibaseDataTypeSchema),
})Also applies to: 594-617, 562-568
🤖 Prompt for AI Agents
In backend/src/types/mediawiki-api.ts around lines 7-9, the Elysia validators
currently accept any string for Wikibase data types; import and reuse the union
schema exported from @backend/types/wikibase-schema (the Elysia-compatible
union/enum schema) instead of t.string() so the runtime validator matches the
WikibaseDataType TypeScript type; replace the generic string schema with that
imported union schema where applicable and add the import, and apply the same
change to the other occurrences at lines 562-568 and 594-617.
| export interface ApiError { | ||
| code: string | ||
| info: string | ||
| docref?: string | ||
| module?: string | ||
| key?: string | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApiError interface and runtime schema disagree (missing info/docref in interface)
Interface ApiError removed info/docref but MediaWikiApiBaseResponseSchema still validates them. This creates type/runtime divergence and will force unsafe casts.
Apply:
export interface ApiError {
code: string
- key?: string
+ info?: string
+ docref?: string
+ module?: string
+ key?: string
}If you intend to standardize on the lean structure, also remove info/docref from the schema instead—but aligning to MediaWiki’s documented shape is safer.
Also applies to: 426-446
| ValueMapping, | ||
| } from '@backend/api/project/project.wikibase' | ||
| import type { StatementRank } from '@backend/types/wikibase-schema' | ||
| import type { UUID } from 'crypto' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove invalid UUID import from node crypto (breaks TS and bundling)
crypto doesn’t export a UUID type; importing Node modules in frontend code can also bloat bundles. Use a local alias.
-import type { UUID } from 'crypto'
+// Prefer a local UUID brand or plain string for frontend code
+type UUID = string📝 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.
| import type { UUID } from 'crypto' | |
| // Prefer a local UUID brand or plain string for frontend code | |
| type UUID = string |
🤖 Prompt for AI Agents
In frontend/src/features/wikibase-schema/composables/useSchemaBuilder.ts around
line 13, remove the invalid "import type { UUID } from 'crypto'" which breaks
TypeScript and frontend bundling; instead declare a local type alias (e.g., type
UUID = string) or reuse an existing frontend-safe UUID type and update
references to use that alias so no Node builtin is imported in client code.
| // Fallback to string | ||
| return 'string' | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fallback to first compatible type instead of hardcoding 'string'
Hardcoding 'string' can yield invalid suggestions for non-VARCHAR columns (e.g., INTEGER). Prefer the first compatible type when property is incompatible.
- // Fallback to string
- return 'string'
+ // Fallback to the first compatible type (safer for non-VARCHAR columns), else 'string'
+ return compatibleTypes[0] ?? 'string'📝 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.
| // Fallback to string | |
| return 'string' | |
| } | |
| // Fallback to the first compatible type (safer for non-VARCHAR columns), else 'string' | |
| return compatibleTypes[0] ?? 'string' | |
| } |
🤖 Prompt for AI Agents
In frontend/src/features/wikibase-schema/composables/useValueMapping.ts around
lines 216 to 218, the function falls back to the hardcoded string 'string' which
can produce invalid suggestions for non-VARCHAR columns; change the fallback to
return the first compatible type from the compatibility list instead of
'string'. Modify the logic so that when the preferred type is incompatible you
scan the computed compatibleTypes (or equivalent array in scope) and return
compatibleTypes[0] (or null/undefined-safe first element) as the fallback,
ensuring you handle the case where no compatible types exist (e.g., return
undefined or a safe default) and update any type annotations accordingly.
| id: 'P31', | ||
| dataType: '', | ||
| }, | ||
| value: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Hard-coding property id 'P31' risks wrong defaults on non-Wikidata instances; also inconsistent source.dataType values
- Defaulting qualifiers/references/snak property to 'P31' assumes Wikidata semantics and IDs. On other Wikibase instances, P31 may not exist or mean something else. Prefer empty/default state, or inject instance-aware defaults from configuration.
- source.dataType mixes 'VARCHAR' and 'string'. Keep consistent (likely 'string') to match the rest of the schema builder and backend expectations.
Option A (neutral default):
- id: 'P31',
+ id: '',
dataType: '',Option B (instance-aware default via DI/config; example signature only):
- const addNewQualifier = (statementId: UUID) => {
+ const addNewQualifier = (statementId: UUID, defaultPropertyId = '') => {
@@
- property: {
- id: 'P31',
+ property: {
+ id: defaultPropertyId,
dataType: '',
},
@@
- dataType: 'VARCHAR',
+ dataType: 'string',Repeat the same adjustment for addNewReference and addSnakToReference.
Also applies to: 271-274, 349-352, 218-221, 276-281, 356-359
🏁 Script executed:
#!/bin/bash
# Search for hard-coded property id 'P31'
rg -n "id:\s*'P31'" frontend/src/features/wikibase-schema/stores/schema.store.ts
# Search for dataType 'VARCHAR'
rg -n "dataType:\s*'VARCHAR'" frontend/src/features/wikibase-schema/stores/schema.store.ts
# List unique dataType values used in the file
rg -n "dataType:" frontend/src/features/wikibase-schema/stores/schema.store.ts \
| sed 's/.*dataType:/dataType:/' | sort -u
# Locate the addNewQualifier function context
rg -nP "addNewQualifier" -C5 frontend/src/features/wikibase-schema/stores/schema.store.ts
# Find all occurrences of 'P31' in the file
rg -n "P31" frontend/src/features/wikibase-schema/stores/schema.store.tsLength of output: 726
Remove hard-coded ‘P31’ and unify dataType usage
- At lines 211, 271, and 349,
property.idis hard-coded to'P31'. This assumes Wikidata semantics and will break other Wikibase instances. Use an empty default ('') or inject the instance’s default via DI/config. - The
dataTypefield is defined inconsistently (empty string,'VARCHAR', and'string'). Standardize to'string'to align with the rest of the schema builder and backend.
Apply the same fixes in addNewReference (lines 276–281, 356–359) and addSnakToReference (lines 218–221, 349–352).
No description provided.