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: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@time-loop/hot-formula-parser",
"version": "4.2.0",
"version": "4.3.0",
"description": "Formula parser",
"type": "commonjs",
"main": "dist/index.js",
Expand Down
13 changes: 5 additions & 8 deletions src/clickup/formulajsProxy.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import * as formulajs from '@formulajs/formulajs';

const hasNil = (...args: unknown[]) =>
args.some((arg) => arg === null || arg === undefined || arg === '' || arg === false);
const nullToZero = (arg: unknown) => (hasNil(arg) ? 0 : arg);
import { hasNil, nilToZero } from './utils';

const overrides = {
DATE: (year: unknown, month: unknown, day: unknown) =>
Expand All @@ -14,11 +11,11 @@ const overrides = {
DAYS360: (startDate: unknown, endDate: unknown, method: unknown) =>
hasNil(startDate, endDate) ? Number.NaN : formulajs.DAYS360(startDate, endDate, method),
EDATE: (startDate: unknown, months: unknown) =>
hasNil(startDate) ? Number.NaN : formulajs.EDATE(startDate, nullToZero(months)),
hasNil(startDate) ? Number.NaN : formulajs.EDATE(startDate, nilToZero(months)),
EOMONTH: (startDate: unknown, months: unknown) =>
hasNil(startDate) ? Number.NaN : formulajs.EOMONTH(startDate, nullToZero(months)),
hasNil(startDate) ? Number.NaN : formulajs.EOMONTH(startDate, nilToZero(months)),
HOUR: (date: unknown) => (hasNil(date) ? Number.NaN : formulajs.HOUR(date)),
INTERVAL: (seconds: unknown) => formulajs.INTERVAL(nullToZero(seconds)),
INTERVAL: (seconds: unknown) => formulajs.INTERVAL(nilToZero(seconds)),
ISOWEEKNUM: (date: unknown) => (hasNil(date) ? Number.NaN : formulajs.ISOWEEKNUM(date)),
MINUTE: (serialNumber: unknown) => (hasNil(serialNumber) ? Number.NaN : formulajs.MINUTE(serialNumber)),
MONTH: (date: unknown) => (hasNil(date) ? Number.NaN : formulajs.MONTH(date)),
Expand All @@ -34,7 +31,7 @@ const overrides = {
YEARFRAC: (startDate: unknown, endDate: unknown, basis: unknown) =>
hasNil(startDate, endDate) ? Number.NaN : formulajs.YEARFRAC(startDate, endDate, basis),
WORKDAY: (startDate: unknown, days: unknown, holidays: unknown) =>
hasNil(startDate) ? Number.NaN : formulajs.WORKDAY(startDate, nullToZero(days), holidays),
hasNil(startDate) ? Number.NaN : formulajs.WORKDAY(startDate, nilToZero(days), holidays),
NETWORKDAYS: (startDate: unknown, endDate: unknown, holidays: unknown) =>
hasNil(startDate, endDate) ? Number.NaN : formulajs.NETWORKDAYS(startDate, endDate, holidays),
};
Expand Down
4 changes: 4 additions & 0 deletions src/clickup/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const hasNil = (...args: unknown[]) =>
args.some((arg) => arg === null || arg === undefined || arg === '' || arg === false);

export const nilToZero = (arg: unknown) => (hasNil(arg) ? 0 : arg);
4 changes: 3 additions & 1 deletion src/evaluate-by-operator/operator/add.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { toNumber } from '../../helper/number';
import { ERROR_VALUE } from '../../error';
import { nilToZero } from '../../clickup/utils';

export const SYMBOL = '+';

export default function func(first, ...rest) {
const result = rest.reduce((acc, value) => acc + toNumber(value), toNumber(first));
// in addition, we convert unset values to zero
const result = rest.reduce((acc, value) => acc + toNumber(nilToZero(value)), toNumber(nilToZero(first)));

if (isNaN(result)) {
throw Error(ERROR_VALUE);
Expand Down
6 changes: 6 additions & 0 deletions src/evaluate-by-operator/operator/divide.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { toNumber } from '../../helper/number';
import { ERROR_DIV_ZERO, ERROR_VALUE } from '../../error';
import { hasNil } from '../../clickup/utils';

export const SYMBOL = '/';

export default function func(first, ...rest) {
if (hasNil(first, ...rest)) {
// some of the arguments are unset, return NaN
return Number.NaN;
}

const result = rest.reduce((acc, value) => acc / Number(toNumber(value)), Number(toNumber(first)));

if (result === Infinity) {
Expand Down
15 changes: 12 additions & 3 deletions src/evaluate-by-operator/operator/minus.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { toNumber } from '../../helper/number';
import { ERROR_VALUE } from '../../error';
import ClickUpConfiguration from '../../clickup.config';
import { ERROR_VALUE } from '../../error';
import { hasNil } from '../../clickup/utils';

export const SYMBOL = '-';

Expand All @@ -10,12 +11,20 @@ export default function func(first, ...rest) {
convertFormulasInNumbers: ClickUpConfiguration.ConvertFormulasInNumbers,
};

if (hasNil(first, ...rest)) {
// some of the arguments are unset, return NaN
return Number.NaN;
}

const result = rest.reduce((acc, value) => {
const subtrahend = toNumber(value, toNumberConfig);
return acc - (subtrahend || 0);
if (Number.isNaN(subtrahend)) {
return Number.NaN;
}
return acc - subtrahend;
}, toNumber(first, toNumberConfig));

if (isNaN(result)) {
if (Number.isNaN(result)) {
throw Error(ERROR_VALUE);
}

Expand Down
6 changes: 6 additions & 0 deletions src/evaluate-by-operator/operator/multiply.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { toNumber } from '../../helper/number';
import { ERROR_VALUE } from '../../error';
import { hasNil } from '../../clickup/utils';

export const SYMBOL = '*';

export default function func(first, ...rest) {
if (hasNil(first, ...rest)) {
// some of the arguments are unset, return NaN
return Number.NaN;
}

const result = rest.reduce((acc, value) => {
const num = toNumber(value);
if (num === undefined) {
Expand Down
6 changes: 6 additions & 0 deletions src/evaluate-by-operator/operator/power.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { toNumber } from '../../helper/number';
import { ERROR_VALUE } from '../../error';
import { hasNil } from '../../clickup/utils';

export const SYMBOL = '^';

export default function func(exp1, exp2) {
if (hasNil(exp1, exp2)) {
// some of the arguments are unset, return NaN
return Number.NaN;
}

const exp1Number = toNumber(exp1);
const exp2Number = toNumber(exp2);
if (exp1Number === undefined || exp2Number === undefined) {
Expand Down
2 changes: 1 addition & 1 deletion src/helper/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function toNumber(
return getNumberOfDaysSinceEpoch(value);
}

return undefined;
return Number.NaN;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions test/unit/evaluate-by-operator/operator/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ describe('add operator', () => {
expect(func(2, undefined)).toBe(2);
expect(func(null, 2)).toBe(2);
expect(func(undefined, 2)).toBe(2);
expect(func(2, '')).toBe(2);
expect(func('', 2)).toBe(2);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(() => func(2, '')).toThrow('VALUE');
expect(() => func('', 2)).toThrow('VALUE');
});

describe('ClickUp Overrides', () => {
Expand Down
12 changes: 6 additions & 6 deletions test/unit/evaluate-by-operator/operator/divide.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ describe('divide operator', () => {
expect(func('2', 8.8)).toBe(0.22727272727272727);
expect(func('2', '-8.8', 6, 0.4)).toBe(-0.0946969696969697);
expect(func(0, 1)).toBe(0);
expect(func(null, 2)).toBe(0);
expect(func(undefined, 2)).toBe(0);
expect(func(null, 2)).toBe(Number.NaN);
expect(func(undefined, 2)).toBe(Number.NaN);
expect(func('', 2)).toBe(Number.NaN);
expect(func(2, '')).toBe(Number.NaN);
expect(func(2, null)).toBe(Number.NaN);
expect(func(2, undefined)).toBe(Number.NaN);
expect(() => func(1, 0)).toThrow('DIV/0');
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('', 2)).toThrow('VALUE');
expect(() => func(2, null)).toThrow('DIV/0');
expect(() => func(2, undefined)).toThrow('DIV/0');
expect(() => func(2, '')).toThrow('VALUE');
});
});
6 changes: 6 additions & 0 deletions test/unit/evaluate-by-operator/operator/minus.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ describe('minus operator', () => {
expect(func('2', 8.8)).toBe(-6.800000000000001);
expect(func('2', '8.8')).toBe(-6.800000000000001);
expect(func('2', '-8.8', 6, 0.4)).toBe(4.4);
expect(func(null, null)).toBe(Number.NaN);
expect(func(null, false)).toBe(Number.NaN);
expect(func(false, false)).toBe(Number.NaN);
expect(func(false, null)).toBe(Number.NaN);
expect(func(null, 'foo')).toBe(Number.NaN);
expect(func('foo', null)).toBe(Number.NaN);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
});
Expand Down
12 changes: 6 additions & 6 deletions test/unit/evaluate-by-operator/operator/multiply.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ describe('multiply operator', () => {
expect(func('2', 8.8)).toBe(17.6);
expect(func('2', '8.8')).toBe(17.6);
expect(func('2', '-8.8', 6, 0.4)).toBe(-42.24000000000001);
expect(func(2, null)).toBe(0);
expect(func(2, undefined)).toBe(0);
expect(func(null, 2)).toBe(0);
expect(func(undefined, 2)).toBe(0);
expect(func(2, null)).toBe(Number.NaN);
expect(func(2, undefined)).toBe(Number.NaN);
expect(func(null, 2)).toBe(Number.NaN);
expect(func(undefined, 2)).toBe(Number.NaN);
expect(func(2, '')).toBe(Number.NaN);
expect(func('', 2)).toBe(Number.NaN);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(() => func(2, '')).toThrow('VALUE');
expect(() => func('', 2)).toThrow('VALUE');
});
});
12 changes: 6 additions & 6 deletions test/unit/evaluate-by-operator/operator/power.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ describe('power operator', () => {
expect(func('2', 8.8)).toBe(445.7218884076158);
expect(func('2', '8.8')).toBe(445.7218884076158);
expect(func('2', '8.8')).toBe(445.7218884076158);
expect(func(2, null)).toBe(1);
expect(func(2, undefined)).toBe(1);
expect(func(null, 2)).toBe(0);
expect(func(undefined, 2)).toBe(0);
expect(func(2, null)).toBe(Number.NaN);
expect(func(2, undefined)).toBe(Number.NaN);
expect(func(null, 2)).toBe(Number.NaN);
expect(func(undefined, 2)).toBe(Number.NaN);
expect(func(2, '')).toBe(Number.NaN);
expect(func('', 2)).toBe(Number.NaN);
expect(() => func('foo', ' ')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(() => func(2, '')).toThrow('VALUE');
expect(() => func('', 2)).toThrow('VALUE');
});
});
Loading