-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Description
Description
The TypeScript SDK fails to retrieve queries using getQueries() and getQuery() methods due to a schema validation mismatch between what the API returns and what the SDK expects.
Current Behavior
When calling builderClient.getQueries() or builderClient.getQuery(queryId), the SDK throws validation errors:
Invalid input: expected string, received undefined
- Path: data[0]._created
- Path: data[0]._updated
- Path: data[0].owner
- Path: data[0].variables (expected record)
- Path: data[0].pipeline (expected array)
Expected Behavior
The methods should successfully return query information, similar to how the Python SDK handles these operations.
Root Cause Analysis
TypeScript SDK expects (from queries.dto.ts:45-54):
const QueryDocumentResponse = z.object({
_id: z.uuid(),
_created: z.iso.datetime(),
_updated: z.iso.datetime(),
owner: Did,
name: z.string().min(1).max(100),
collection: z.uuid(),
variables: z.record(z.string(), QueryVariableValidator),
pipeline: z.array(z.record(z.string(), z.unknown())),
});
Python SDK expects (simpler structure):
class QueryDocumentResponse(BaseModel):
id: Uuid = Field(alias="_id")
name: str
collection: Uuid
API actually returns: Only the basic fields (_id, name, collection), not the full document.
Impact
- Cannot list queries -
getQueries()fails, preventing users from discovering available queries - Cannot get query details -
getQuery(id)fails, preventing users from inspecting query configuration - Poor developer experience - Errors are confusing as they suggest the API is broken when it's actually a client-side
validation issue - Feature parity - TypeScript SDK lacks functionality that works in Python SDK
Workaround
Currently, devs must:
- Track query IDs separately after creation
- Cannot verify query configuration after creation
- Cannot implement query management UIs
Proposed Solution
Option 1: Create separate DTOs (Recommended)
// For list operations - matches actual API response
const QuerySummaryResponse = z.object({
_id: z.uuid(),
name: z.string(),
collection: z.uuid(),
});
// For create operations - full document
const QueryDocumentResponse = z.object({
_id: z.uuid(),
_created: z.iso.datetime(),
_updated: z.iso.datetime(),
owner: Did,
name: z.string().min(1).max(100),
collection: z.uuid(),
variables: z.record(z.string(), QueryVariableValidator),
pipeline: z.array(z.record(z.string(), z.unknown())),
});
Option 2: Make fields optional
const QueryDocumentResponse = z.object({
_id: z.uuid(),
name: z.string(),
collection: z.uuid(),
// Optional fields for read operations
_created: z.iso.datetime().optional(),
_updated: z.iso.datetime().optional(),
owner: Did.optional(),
variables: z.record(z.string(), QueryVariableValidator).optional(),
pipeline: z.array(z.record(z.string(), z.unknown())).optional(),
});
Reproduction Steps
// Create a query (works fine)
const queryId = randomUUID();
await builderClient.createQuery({
_id: queryId,
name: 'Test Query',
collection: collectionId,
variables: {},
pipeline: [{ $match: {} }]
});
// Try to list queries (fails)
const queries = await builderClient.getQueries(); // ❌ Validation error
// Try to get specific query (fails)
const query = await builderClient.getQuery(queryId); // ❌ Validation error
Metadata
Metadata
Assignees
Labels
No labels