Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/datasource-cosmos/src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default class CosmosCollection extends BaseCollection {
model: ModelCosmos,
logger: Logger,
nativeDriver: CosmosClient,
options?: { maxConditions?: number },
) {
if (!model) throw new Error('Invalid (null) model instance.');

Expand All @@ -53,6 +54,7 @@ export default class CosmosCollection extends BaseCollection {
validationOptions: {
// Allow unknown fields since schema might not include all nested paths
allowUnknownFields: true,
maxConditions: options?.maxConditions,
},
});

Expand Down
14 changes: 10 additions & 4 deletions packages/datasource-cosmos/src/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ export default class CosmosDataSource extends BaseDataSource<CosmosCollection> {
cosmosClient: CosmosClient,
collectionModels: ModelCosmos[],
logger: Logger,
options?: { liveQueryConnections?: string; liveQueryDatabase?: string },
options?: { liveQueryConnections?: string; liveQueryDatabase?: string; maxConditions?: number },
) {
super();

if (!cosmosClient) throw new Error('Invalid (null) CosmosClient instance.');
this.cosmosClient = cosmosClient;

// Creating collections
this.createCollections(collectionModels, logger);
this.createCollections(collectionModels, logger, options?.maxConditions);

if (options?.liveQueryConnections && options?.liveQueryDatabase) {
this.addNativeQueryConnection(options.liveQueryConnections, {
Expand All @@ -39,12 +39,18 @@ export default class CosmosDataSource extends BaseDataSource<CosmosCollection> {
logger?.('Info', 'CosmosDataSource - Built');
}

protected async createCollections(collectionModels: ModelCosmos[], logger: Logger) {
protected async createCollections(
collectionModels: ModelCosmos[],
logger: Logger,
maxConditions?: number,
) {
collectionModels
// avoid schema reordering
.sort((modelA, modelB) => (modelA.name > modelB.name ? 1 : -1))
.forEach(model => {
const collection = new CosmosCollection(this, model, logger, this.cosmosClient);
const collection = new CosmosCollection(this, model, logger, this.cosmosClient, {
maxConditions,
});
this.addCollection(collection);
});
}
Expand Down
8 changes: 8 additions & 0 deletions packages/datasource-cosmos/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ export function createCosmosDataSource(
* Default: false
*/
logQueries?: boolean;
/**
* Maximum number of conditions allowed in a single query condition tree
* Increase this if you use charts with many time buckets or complex filters
* Default: 1000
*/
maxConditions?: number;
},
): DataSourceFactory {
return async (logger: Logger) => {
Expand All @@ -203,6 +209,7 @@ export function createCosmosDataSource(
schema,
logRuConsumption,
logQueries,
maxConditions,
} = options || {};

// Configure RU logging if enabled
Expand Down Expand Up @@ -263,6 +270,7 @@ export function createCosmosDataSource(
const datasource = new CosmosDataSource(client, collectionModels, logger, {
liveQueryConnections,
liveQueryDatabase,
maxConditions,
});

// Add virtual array collections if specified
Expand Down
10 changes: 6 additions & 4 deletions packages/datasource-cosmos/src/utils/query-validation-error.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ValidationError } from '@forestadmin/datasource-toolkit';

/**
* Error codes for query validation failures
*/
Expand All @@ -12,15 +14,15 @@ export enum QueryValidationErrorCode {
}

/**
* Security and validation errors for query operations
* Security and validation errors for query operations.
* Extends ValidationError so the agent returns 400 (Bad Request) instead of 500.
*/
export default class QueryValidationError extends Error {
export default class QueryValidationError extends ValidationError {
constructor(
message: string,
public readonly code: QueryValidationErrorCode,
public readonly field?: string,
) {
super(message);
this.name = 'QueryValidationError';
super(message, undefined, 'QueryValidationError');
}
}
4 changes: 2 additions & 2 deletions packages/datasource-cosmos/src/utils/query-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface QueryValidatorOptions {

/**
* Maximum number of conditions in a condition tree
* Default: 100
* Default: 1000
*/
maxConditions?: number;
}
Expand Down Expand Up @@ -78,7 +78,7 @@ export default class QueryValidator {
validateAgainstSchema: options.validateAgainstSchema ?? schemaFields !== undefined,
allowUnknownFields: options.allowUnknownFields ?? false,
maxFieldNameLength: options.maxFieldNameLength ?? 256,
maxConditions: options.maxConditions ?? 100,
maxConditions: options.maxConditions ?? 1000,
};

if (schemaFields) {
Expand Down
Loading
Loading