Skip to content

Commit

Permalink
refactor: fill in basic types in rules.ts (#3365)
Browse files Browse the repository at this point in the history
* refactor: fill in basic types in rules.ts

* chore: release note

* chore: implement pr feedback

---------

Co-authored-by: Matt Fiddaman <[email protected]>
  • Loading branch information
UnderKoen and matt-fidd authored Oct 8, 2024
1 parent 85b3c57 commit 1485d9c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 29 deletions.
56 changes: 30 additions & 26 deletions packages/loot-core/src/server/accounts/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
ungroupTransaction,
} from '../../shared/transactions';
import { fastSetMerge } from '../../shared/util';
import { RuleConditionEntity } from '../../types/models';
import { RuleConditionEntity, RuleEntity } from '../../types/models';
import { RuleError } from '../errors';
import { Schedule as RSchedule } from '../util/rschedule';

Expand Down Expand Up @@ -87,7 +87,7 @@ function registerHandlebarsHelpers() {

registerHandlebarsHelpers();

function assert(test, type, msg) {
function assert(test: unknown, type: string, msg: string): asserts test {
if (!test) {
throw new RuleError(type, msg);
}
Expand Down Expand Up @@ -793,11 +793,11 @@ export function execActions(actions: Action[], transaction) {
}

export class Rule {
actions;
conditions;
actions: Action[];
conditions: Condition[];
conditionsOp;
id;
stage;
id?: string;
stage: 'pre' | null | 'post';

constructor({
id,
Expand All @@ -807,13 +807,13 @@ export class Rule {
actions,
}: {
id?: string;
stage?;
stage?: 'pre' | null | 'post';
conditionsOp;
conditions;
actions;
}) {
this.id = id;
this.stage = stage;
this.stage = stage ?? null;
this.conditionsOp = conditionsOp;
this.conditions = conditions.map(
c => new Condition(c.op, c.field, c.value, c.options),
Expand All @@ -823,7 +823,7 @@ export class Rule {
);
}

evalConditions(object) {
evalConditions(object): boolean {
if (this.conditions.length === 0) {
return false;
}
Expand Down Expand Up @@ -860,11 +860,11 @@ export class Rule {
return Object.assign({}, object, changes);
}

getId() {
getId(): string | undefined {
return this.id;
}

serialize() {
serialize(): RuleEntity {
return {
id: this.id,
stage: this.stage,
Expand All @@ -876,28 +876,28 @@ export class Rule {
}

export class RuleIndexer {
field;
method;
rules;
field: string;
method?: string;
rules: Map<string, Set<Rule>>;

constructor({ field, method }: { field: string; method?: string }) {
this.field = field;
this.method = method;
this.rules = new Map();
}

getIndex(key) {
getIndex(key: string | null): Set<Rule> {
if (!this.rules.has(key)) {
this.rules.set(key, new Set());
}
return this.rules.get(key);
}

getIndexForValue(value) {
getIndexForValue(value: unknown): Set<Rule> {
return this.getIndex(this.getKey(value) || '*');
}

getKey(value) {
getKey(value: unknown): string | null {
if (typeof value === 'string' && value !== '') {
if (this.method === 'firstchar') {
return value[0].toLowerCase();
Expand All @@ -907,7 +907,7 @@ export class RuleIndexer {
return null;
}

getIndexes(rule) {
getIndexes(rule: Rule): Set<Rule>[] {
const cond = rule.conditions.find(cond => cond.field === this.field);
const indexes = [];

Expand All @@ -930,21 +930,21 @@ export class RuleIndexer {
return indexes;
}

index(rule) {
index(rule: Rule): void {
const indexes = this.getIndexes(rule);
indexes.forEach(index => {
index.add(rule);
});
}

remove(rule) {
remove(rule: Rule): void {
const indexes = this.getIndexes(rule);
indexes.forEach(index => {
index.delete(rule);
});
}

getApplicableRules(object) {
getApplicableRules(object): Set<Rule> {
let indexedRules;
if (this.field in object) {
const key = this.getKey(object[this.field]);
Expand Down Expand Up @@ -977,7 +977,7 @@ const OP_SCORES: Record<RuleConditionEntity['op'], number> = {
hasTags: 0,
};

function computeScore(rule) {
function computeScore(rule: Rule): number {
const initialScore = rule.conditions.reduce((score, condition) => {
if (OP_SCORES[condition.op] == null) {
console.log(`Found invalid operation while ranking: ${condition.op}`);
Expand All @@ -1002,7 +1002,7 @@ function computeScore(rule) {
return initialScore;
}

function _rankRules(rules) {
function _rankRules(rules: Rule[]): Rule[] {
const scores = new Map();
rules.forEach(rule => {
scores.set(rule, computeScore(rule));
Expand All @@ -1026,7 +1026,7 @@ function _rankRules(rules) {
});
}

export function rankRules(rules) {
export function rankRules(rules: Iterable<Rule>): Rule[] {
let pre = [];
let normal = [];
let post = [];
Expand All @@ -1051,7 +1051,7 @@ export function rankRules(rules) {
return pre.concat(normal).concat(post);
}

export function migrateIds(rule, mappings) {
export function migrateIds(rule: Rule, mappings: Map<string, string>): void {
// Go through the in-memory rules and patch up ids that have been
// "migrated" to other ids. This is a little tricky, but a lot
// easier than trying to keep an up-to-date mapping in the db. This
Expand Down Expand Up @@ -1103,7 +1103,11 @@ export function migrateIds(rule, mappings) {
}

// This finds all the rules that reference the `id`
export function iterateIds(rules, fieldName, func) {
export function iterateIds(
rules: Rule[],
fieldName: string,
func: (rule: Rule, id: string) => void | boolean,
): void {
let i;

ruleiter: for (i = 0; i < rules.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ export async function applyActions(
}

export function getRulesForPayee(payeeId) {
const rules = new Set();
const rules = new Set<Rule>();
iterateIds(getRules(), 'payee', (rule, id) => {
if (id === payeeId) {
rules.add(rule);
Expand Down
4 changes: 2 additions & 2 deletions packages/loot-core/src/types/models/rule.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type ScheduleEntity } from './schedule';

export interface NewRuleEntity {
stage: string;
conditionsOp: 'any' | 'and';
stage: 'pre' | null | 'post';
conditionsOp: 'or' | 'and';
conditions: RuleConditionEntity[];
actions: RuleActionEntity[];
tombstone?: boolean;
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/3365.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [UnderKoen]
---

Add more strict types to `account/rules.ts`

0 comments on commit 1485d9c

Please sign in to comment.