diff --git a/packages/datasource-customizer/src/collection-customizer.ts b/packages/datasource-customizer/src/collection-customizer.ts
index 932b302597..8e4d606041 100644
--- a/packages/datasource-customizer/src/collection-customizer.ts
+++ b/packages/datasource-customizer/src/collection-customizer.ts
@@ -178,7 +178,9 @@ export default class CollectionCustomizer<
*/
addChart(name: string, definition: CollectionChartDefinition): this {
return this.pushCustomization(async () => {
- this.stack.chart.getCollection(this.name).addChart(name, definition);
+ this.stack.chart
+ .getCollection(this.name)
+ .addChart(name, definition as unknown as CollectionChartDefinition);
});
}
@@ -228,7 +230,10 @@ export default class CollectionCustomizer<
? collectionBeforeRelations
: collectionAfterRelations;
- collection.registerComputed(name, mapDeprecated(definition));
+ collection.registerComputed(
+ name,
+ mapDeprecated(definition) as unknown as ComputedDefinition,
+ );
});
};
@@ -261,7 +266,7 @@ export default class CollectionCustomizer<
addHook
(
position: P,
type: T,
- handler: HookHandler,
): this {
return this.pushCustomization(async () => {
- this.stack.write.getCollection(this.name).replaceFieldWriting(name, definition);
+ this.stack.write
+ .getCollection(this.name)
+ .replaceFieldWriting(name, definition as unknown as WriteDefinition);
});
}
@@ -609,7 +616,9 @@ export default class CollectionCustomizer<
*/
overrideCreate(handler: CreateOverrideHandler): this {
return this.pushCustomization(async () => {
- this.stack.override.getCollection(this.name).addCreateHandler(handler);
+ this.stack.override
+ .getCollection(this.name)
+ .addCreateHandler(handler as unknown as CreateOverrideHandler);
});
}
@@ -625,7 +634,9 @@ export default class CollectionCustomizer<
*/
overrideUpdate(handler: UpdateOverrideHandler): this {
return this.pushCustomization(async () => {
- this.stack.override.getCollection(this.name).addUpdateHandler(handler);
+ this.stack.override
+ .getCollection(this.name)
+ .addUpdateHandler(handler as unknown as UpdateOverrideHandler);
});
}
@@ -641,7 +652,9 @@ export default class CollectionCustomizer<
*/
overrideDelete(handler: DeleteOverrideHandler): this {
return this.pushCustomization(async () => {
- this.stack.override.getCollection(this.name).addDeleteHandler(handler);
+ this.stack.override
+ .getCollection(this.name)
+ .addDeleteHandler(handler as unknown as DeleteOverrideHandler);
});
}
diff --git a/packages/datasource-customizer/src/datasource-customizer.ts b/packages/datasource-customizer/src/datasource-customizer.ts
index 43b89fb340..5b54f11847 100644
--- a/packages/datasource-customizer/src/datasource-customizer.ts
+++ b/packages/datasource-customizer/src/datasource-customizer.ts
@@ -104,7 +104,7 @@ export default class DataSourceCustomizer {
*/
addChart(name: string, definition: DataSourceChartDefinition): this {
this.stack.queueCustomization(async () => {
- this.stack.chart.addChart(name, definition);
+ this.stack.chart.addChart(name, definition as unknown as DataSourceChartDefinition);
});
return this;
diff --git a/packages/datasource-customizer/src/decorators/actions/collection.ts b/packages/datasource-customizer/src/decorators/actions/collection.ts
index 6bf2ea8615..12c3b1274b 100644
--- a/packages/datasource-customizer/src/decorators/actions/collection.ts
+++ b/packages/datasource-customizer/src/decorators/actions/collection.ts
@@ -8,7 +8,7 @@ import type {
SearchOptionsHandler,
ValueOrHandler,
} from './types/fields';
-import type { TSchema } from '../../templates';
+import type { TFilter, TSchema } from '../../templates';
import type {
ActionFormElement,
ActionResult,
@@ -18,7 +18,6 @@ import type {
Filter,
GetFormMetas,
LayoutElementPageWithField,
- PlainFilter,
RecordData,
} from '@forestadmin/datasource-toolkit';
@@ -177,7 +176,7 @@ export default class ActionCollectionDecorator extends CollectionDecorator {
Global: ActionContext,
Bulk: ActionContext,
Single: ActionContextSingle,
- }[action.scope](this, caller, formValues, filter as unknown as PlainFilter, used, changedField);
+ }[action.scope](this, caller, formValues, filter as unknown as TFilter, used, changedField);
}
private getSearchedField(element: DynamicFormElementOrPage, search: string): DynamicField | null {
diff --git a/packages/datasource-customizer/src/templates.ts b/packages/datasource-customizer/src/templates.ts
index 2c0c324f36..c232afbf61 100644
--- a/packages/datasource-customizer/src/templates.ts
+++ b/packages/datasource-customizer/src/templates.ts
@@ -78,14 +78,52 @@ export type TPartialFlatRow<
N extends TCollectionName = TCollectionName,
> = RecursivePartial;
+/** Operators that require no value */
+type NoValueOperator =
+ | 'Blank'
+ | 'Present'
+ | 'Missing'
+ | 'Today'
+ | 'Yesterday'
+ | 'PreviousMonth'
+ | 'PreviousQuarter'
+ | 'PreviousWeek'
+ | 'PreviousYear'
+ | 'PreviousMonthToDate'
+ | 'PreviousQuarterToDate'
+ | 'PreviousWeekToDate'
+ | 'PreviousYearToDate'
+ | 'Past'
+ | 'Future';
+
+/** Operators that require an array of values */
+type ArrayValueOperator = 'In' | 'NotIn' | 'IncludesAll' | 'IncludesNone';
+
+/** Operators that always require a number value */
+type NumberValueOperator =
+ | 'PreviousXDaysToDate'
+ | 'PreviousXDays'
+ | 'BeforeXHoursAgo'
+ | 'AfterXHoursAgo'
+ | 'LongerThan'
+ | 'ShorterThan';
+
+/** Operators that require a single value matching the field type */
+type SingleValueOperator = Exclude<
+ Operator,
+ NoValueOperator | ArrayValueOperator | NumberValueOperator
+>;
+
export type TConditionTreeLeaf<
S extends TSchema = TSchema,
N extends TCollectionName = TCollectionName,
> = {
- field: TFieldName;
- operator: Operator;
- value?: unknown;
-};
+ [F in TFieldName]:
+ | { field: F; operator: NoValueOperator }
+ | { field: F; operator: ArrayValueOperator; value: TFieldType[] }
+ | { field: F; operator: NumberValueOperator; value: number }
+ | { field: F; operator: SingleValueOperator; value: TFieldType };
+}[TFieldName];
export type TConditionTreeBranch<
S extends TSchema = TSchema,
diff --git a/packages/datasource-customizer/test/collection-customizer.test.ts b/packages/datasource-customizer/test/collection-customizer.test.ts
index a459a7d4a8..57f98708f7 100644
--- a/packages/datasource-customizer/test/collection-customizer.test.ts
+++ b/packages/datasource-customizer/test/collection-customizer.test.ts
@@ -9,7 +9,7 @@ import type { ActionDefinition } from '../src/decorators/actions/types/actions';
import type { WriteDefinition } from '../src/decorators/write/write-replace/types';
import type { ColumnSchema } from '@forestadmin/datasource-toolkit';
-import { ConditionTreeLeaf, MissingFieldError, Sort } from '@forestadmin/datasource-toolkit';
+import { MissingFieldError, Sort } from '@forestadmin/datasource-toolkit';
import * as factories from '@forestadmin/datasource-toolkit/dist/test/__factories__';
import { CollectionCustomizer, DataSourceCustomizer } from '../src';
@@ -639,7 +639,7 @@ describe('Builder > Collection', () => {
it('should add a segment', async () => {
const { dsc, customizer } = await setup();
- const generator = async () => new ConditionTreeLeaf('fieldName', 'Present');
+ const generator = async () => ({ field: 'fieldName', operator: 'Present' } as const);
const self = customizer.addSegment('new segment', generator);
await dsc.getDataSource(logger);
@@ -773,7 +773,8 @@ describe('Builder > Collection', () => {
it('should replace operator on field', async () => {
const { dsc, customizer } = await setup();
- const replacer = async () => new ConditionTreeLeaf('fieldName', 'NotEqual', null);
+ const replacer = async () =>
+ ({ field: 'fieldName', operator: 'NotEqual', value: null } as const);
const self = customizer.replaceFieldOperator('firstName', 'Present', replacer);
await dsc.getDataSource(logger);