@catalystcrm/policy-calculator 1.0.0 → 5.24.0-dev.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org>
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Policy Calculator
2
+
3
+ A little helper library to be used for calculating various Policy/Contract fields. It have not much dependencies and
4
+ expected to be used both on backend and frontend.
5
+
6
+ ## Dependencies note
7
+
8
+ Since the library is expected to be used on the frontend as well, it should not have other backend-only dependencies from
9
+ `@catalystcrm` npm organization.
@@ -0,0 +1,4 @@
1
+ export declare class CalculatorError extends Error {
2
+ readonly message: string;
3
+ constructor(message: string);
4
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CalculatorError = void 0;
4
+ class CalculatorError extends Error {
5
+ message;
6
+ constructor(message) {
7
+ super();
8
+ this.message = message;
9
+ if (Error.captureStackTrace) {
10
+ Error.captureStackTrace(this, this.constructor);
11
+ }
12
+ this.message = message;
13
+ this.name = this.constructor.name;
14
+ }
15
+ }
16
+ exports.CalculatorError = CalculatorError;
17
+ //# sourceMappingURL=calculator-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculator-error.js","sourceRoot":"","sources":["../../src/field-calculation/calculator-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,eAAgB,SAAQ,KAAK;IACnB;IAArB,YAAqB,OAAe;QAClC,KAAK,EAAE,CAAC;QADW,YAAO,GAAP,OAAO,CAAQ;QAGlC,IAAK,KAAa,CAAC,iBAAiB,EAAE;YACnC,KAAa,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;SAC1D;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACpC,CAAC;CACF;AAXD,0CAWC"}
@@ -0,0 +1,42 @@
1
+ export type PolicyFieldCalculatorInput = {
2
+ amount_full?: string | null;
3
+ net_discount_amount?: string | null;
4
+ net_discount_id?: number | null;
5
+ amount_netto?: string | null;
6
+ special_discount?: string | null;
7
+ stamp_duties?: string | null;
8
+ gross_discount_amount?: string | null;
9
+ gross_discount_id?: number | null;
10
+ amount_brutto?: string | null;
11
+ other_costs?: string | null;
12
+ has_stamp_duties?: boolean | null;
13
+ };
14
+ export declare const PolicyDiscountTypes: {
15
+ GROSS: number;
16
+ NET: number;
17
+ };
18
+ export type PolicyDiscounts = {
19
+ id: number;
20
+ name: string;
21
+ percentage: string;
22
+ discount_type_id: number;
23
+ };
24
+ export type PolicyCalculationConfig = {
25
+ discounts: PolicyDiscounts[];
26
+ STAMP_DUTY_PERCENTAGE: number;
27
+ };
28
+ export type PolicyFieldCalculatorResponse = {
29
+ stamp_duties: string;
30
+ amount_netto: string;
31
+ amount_brutto: string;
32
+ net_discount_amount: string;
33
+ gross_discount_amount: string;
34
+ };
35
+ export type FieldCalculationConfig = {
36
+ policyCalculationConfig: PolicyCalculationConfig;
37
+ };
38
+ export declare class FieldCalculationService {
39
+ private readonly policyCalculationConfig;
40
+ constructor(config: FieldCalculationConfig);
41
+ calculate(input: PolicyFieldCalculatorInput): PolicyFieldCalculatorResponse;
42
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FieldCalculationService = exports.PolicyDiscountTypes = void 0;
7
+ const decimal_js_1 = __importDefault(require("decimal.js"));
8
+ const calculator_error_1 = require("./calculator-error");
9
+ exports.PolicyDiscountTypes = {
10
+ GROSS: 1,
11
+ NET: 2
12
+ };
13
+ class FieldCalculationService {
14
+ policyCalculationConfig;
15
+ constructor(config) {
16
+ this.policyCalculationConfig = config.policyCalculationConfig;
17
+ }
18
+ calculate(input) {
19
+ const amount_full = input.amount_full ? input.amount_full : '0.00';
20
+ const special_discount = input.special_discount ? input.special_discount : '0.00';
21
+ const other_costs = input.other_costs ? input.other_costs : '0.00';
22
+ // manually casting to number because GQL will serialize ids as string
23
+ const net_discount_id = input.net_discount_id && Number(input.net_discount_id);
24
+ const gross_discount_id = input.gross_discount_id && Number(input.gross_discount_id);
25
+ let net_discount_amount = input.net_discount_amount ? input.net_discount_amount : '0.00';
26
+ let amount_netto = input.amount_netto ? input.amount_netto : '0.00';
27
+ let stamp_duties = input.stamp_duties ? input.stamp_duties : '0.00';
28
+ let gross_discount_amount = input.gross_discount_amount ? input.gross_discount_amount : '0.00';
29
+ let amount_brutto = input.amount_brutto ? input.amount_brutto : '0.00';
30
+ // 1. Calculate the net discount if any.
31
+ if (net_discount_id) {
32
+ const netDiscounts = this.policyCalculationConfig.discounts.filter(d => d.discount_type_id === exports.PolicyDiscountTypes.NET);
33
+ const discount = netDiscounts.find(({ id }) => id === net_discount_id);
34
+ if (!discount) {
35
+ throw new calculator_error_1.CalculatorError(`Invalid net discount id for calculation: ${net_discount_id}`);
36
+ }
37
+ const percentage = new decimal_js_1.default(discount.percentage);
38
+ const percentageValue = percentage.dividedBy(100).times(amount_full);
39
+ net_discount_amount = percentageValue.negated().toFixed(2);
40
+ }
41
+ // 2. Calculate the net premium
42
+ const amountNettoDecimal = new decimal_js_1.default(amount_full).add(net_discount_amount);
43
+ amount_netto = amountNettoDecimal.toFixed(2);
44
+ // 2.1 Calculate special discount from net premium
45
+ const specialDiscount = new decimal_js_1.default(special_discount);
46
+ const specialDiscountDecimal = specialDiscount.dividedBy(100).times(amount_netto);
47
+ const special_discount_value = specialDiscountDecimal.toFixed(2);
48
+ // 3. Calculate the gross discount if any
49
+ if (gross_discount_id) {
50
+ const grossDiscounts = this.policyCalculationConfig.discounts.filter(d => d.discount_type_id === exports.PolicyDiscountTypes.GROSS);
51
+ const discount = grossDiscounts.find(({ id }) => id === gross_discount_id);
52
+ if (!discount) {
53
+ throw new calculator_error_1.CalculatorError(`Invalid gross discount id for calculation: ${gross_discount_id}`);
54
+ }
55
+ const percentage = new decimal_js_1.default(discount.percentage);
56
+ const percentageValue = percentage.dividedBy(100).times(amount_netto);
57
+ gross_discount_amount = percentageValue.negated().toFixed(2);
58
+ }
59
+ // 4. Calculate the stamp duties if any
60
+ if (input.has_stamp_duties) {
61
+ const stampPercentage = new decimal_js_1.default(this.policyCalculationConfig.STAMP_DUTY_PERCENTAGE);
62
+ const stampDuties = stampPercentage
63
+ .dividedBy(100)
64
+ .times(new decimal_js_1.default(amount_netto).minus(special_discount_value));
65
+ stamp_duties = stampDuties.toFixed(2);
66
+ }
67
+ // 5. Calculate the gross premium
68
+ const amountBruttoDecimal = new decimal_js_1.default(amount_netto)
69
+ .minus(special_discount_value)
70
+ .add(stamp_duties)
71
+ .add(gross_discount_amount)
72
+ .add(other_costs);
73
+ amount_brutto = amountBruttoDecimal.toFixed(2);
74
+ return {
75
+ stamp_duties,
76
+ amount_netto,
77
+ amount_brutto,
78
+ net_discount_amount,
79
+ gross_discount_amount
80
+ };
81
+ }
82
+ }
83
+ exports.FieldCalculationService = FieldCalculationService;
84
+ //# sourceMappingURL=calculator-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculator-service.js","sourceRoot":"","sources":["../../src/field-calculation/calculator-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export type CalculatorInput = {
2
+ formula: string | null;
3
+ start_date?: Date | string | null;
4
+ end_date?: Date | string | null;
5
+ amount_netto?: string | null;
6
+ amount_brutto?: string | null;
7
+ sum_insured?: string | null;
8
+ partner_commission?: string | null;
9
+ };
10
+ /**
11
+ * @param calculatePrecision number of significant digits during calculation
12
+ * @param outputScale number of decimal digits only at the output result
13
+ */
14
+ export type FormulaCalculatorConfig = {
15
+ calculatePrecision: number;
16
+ outputScale: number;
17
+ };
18
+ export declare class FormulaCalculator {
19
+ private readonly outputScale;
20
+ private readonly mathjs;
21
+ constructor(config: FormulaCalculatorConfig);
22
+ private validateNumeric;
23
+ /**
24
+ * Calculates LZ param value exactly the way Brokerstar does
25
+ */
26
+ private getLZValue;
27
+ /**
28
+ * Function to calculate number of point from given data.
29
+ *
30
+ * The combinvest sales system is based on points, in order to simplify the complex commission
31
+ * distribution. It means sales forces/leads don't get a certain amount of money per product
32
+ * sale, they get points. Also personal, team and company goals are set in points.
33
+ * A point is then equivalent to a certain amount of money, which is different depending
34
+ * on the persons career level.
35
+ *
36
+ * Input data usually is collected from premium (amounts and sums) and policy (start and end dates).
37
+ *
38
+ * Implemented right after Brokerstar's method `Premium.calcFomula` (not a typo here :) )
39
+ * Does not fully support following values: [LS-AHV], [LS-UVG], [LS-BVG]
40
+ */
41
+ calculate(input: CalculatorInput): string;
42
+ /**
43
+ * This method below is here because it uses the same logic as method calculate and the same configs.
44
+ * @param a is string containing decimal
45
+ * @param b is string containing decimal
46
+ * @returns sum of two decimal strings
47
+ */
48
+ sum(a: string, b: string): string;
49
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FormulaCalculator = void 0;
7
+ const decimal_js_1 = require("decimal.js");
8
+ const mathjs_1 = require("mathjs");
9
+ const moment_1 = __importDefault(require("moment"));
10
+ const neverthrow_1 = require("neverthrow");
11
+ const string_1 = require("../utils/string");
12
+ const DAYS_IN_YEAR = 365;
13
+ const MAX_LZ = 100; // Max LZn value used by Brokerstar points calculator
14
+ class FormulaCalculator {
15
+ outputScale;
16
+ mathjs;
17
+ constructor(config) {
18
+ this.outputScale = config.outputScale;
19
+ this.mathjs = (0, mathjs_1.create)(mathjs_1.all);
20
+ this.mathjs.config({ number: 'BigNumber', precision: config.calculatePrecision });
21
+ this.mathjs.import({
22
+ divide(a, b) {
23
+ const result = decimal_js_1.Decimal.div(a, b);
24
+ return result.toString() === 'Infinity' || result.toString() === '-Infinity' ? 0 : result;
25
+ }
26
+ }, { override: true });
27
+ }
28
+ validateNumeric(input) {
29
+ const n = Number(input);
30
+ return !input || Number.isNaN(n) ? (0, neverthrow_1.err)(`"${input}" is not valid number`) : (0, neverthrow_1.ok)(input);
31
+ }
32
+ /**
33
+ * Calculates LZ param value exactly the way Brokerstar does
34
+ */
35
+ getLZValue(start_date, end_date) {
36
+ let LZ = '1';
37
+ if (start_date && end_date && (0, moment_1.default)(start_date).isValid() && (0, moment_1.default)(end_date).isValid()) {
38
+ // getting number of days between start and end
39
+ const daysNumber = new decimal_js_1.Decimal((0, moment_1.default)(end_date).diff((0, moment_1.default)(start_date), 'days'));
40
+ const daysNumberModulo = decimal_js_1.Decimal.abs(daysNumber);
41
+ const yearsNumber = decimal_js_1.Decimal.round(daysNumberModulo.dividedBy(DAYS_IN_YEAR));
42
+ LZ = yearsNumber.valueOf();
43
+ }
44
+ return LZ;
45
+ }
46
+ /**
47
+ * Function to calculate number of point from given data.
48
+ *
49
+ * The combinvest sales system is based on points, in order to simplify the complex commission
50
+ * distribution. It means sales forces/leads don't get a certain amount of money per product
51
+ * sale, they get points. Also personal, team and company goals are set in points.
52
+ * A point is then equivalent to a certain amount of money, which is different depending
53
+ * on the persons career level.
54
+ *
55
+ * Input data usually is collected from premium (amounts and sums) and policy (start and end dates).
56
+ *
57
+ * Implemented right after Brokerstar's method `Premium.calcFomula` (not a typo here :) )
58
+ * Does not fully support following values: [LS-AHV], [LS-UVG], [LS-BVG]
59
+ */
60
+ calculate(input) {
61
+ if (!input.formula) {
62
+ return new decimal_js_1.Decimal('0').toFixed(this.outputScale);
63
+ }
64
+ const numericFormulaProvisionUnitResult = this.validateNumeric(input.formula);
65
+ // if it is just stringified number - returning it
66
+ if (numericFormulaProvisionUnitResult.isOk()) {
67
+ return new decimal_js_1.Decimal(numericFormulaProvisionUnitResult.value).toFixed(this.outputScale);
68
+ }
69
+ const numericAmountNettoResult = this.validateNumeric(input.amount_netto);
70
+ // if this is stringified number of percents
71
+ if (input.formula.includes('%') && numericAmountNettoResult.isOk()) {
72
+ const percentString = input.formula.replace('%', '');
73
+ const multiplier = percentString;
74
+ const points = new decimal_js_1.Decimal(numericAmountNettoResult.value).dividedBy('100').times(multiplier);
75
+ return points.toFixed(this.outputScale);
76
+ }
77
+ // otherwise this is full-featured arithmetic formula like `[BP]*[LZ] - [NP]/8`
78
+ const numericAmountBruttoResult = this.validateNumeric(input.amount_brutto);
79
+ const numericSumInsuredResult = this.validateNumeric(input.sum_insured);
80
+ const numericPartnerCommissionResult = this.validateNumeric(input.partner_commission);
81
+ // calculating numeric replacement values
82
+ const NP = numericAmountNettoResult.unwrapOr('0');
83
+ const BP = numericAmountBruttoResult.unwrapOr('0');
84
+ const VS = numericSumInsuredResult.unwrapOr('0');
85
+ const PC = numericPartnerCommissionResult.unwrapOr('0');
86
+ const LZ = this.getLZValue(input.start_date, input.end_date);
87
+ // These fields are currently not being used, they are tied to BS contact wages.
88
+ // We don't have contact wages on Combinvest
89
+ // and as of 24.10.2022 contact wages is empty on BS production
90
+ // we decided to go with BS default values which is 0
91
+ const LSAHV = '0';
92
+ const LSUVG = '0';
93
+ const LSBVG = '0';
94
+ const replacements = {
95
+ '[NP]': NP,
96
+ '[BP]': BP,
97
+ '[LZ]': LZ,
98
+ '[VS]': VS,
99
+ '[PC]': PC,
100
+ '[LS-AHV]': LSAHV,
101
+ '[LS-UVG]': LSUVG,
102
+ '[LS-BVG]': LSBVG
103
+ };
104
+ // .. and all the LZ1, LZ2...LZ99 replacements too
105
+ for (let i = 1; i < MAX_LZ; i++) {
106
+ const replacement = Number(LZ) < i ? LZ : i.toString();
107
+ replacements[`[LZ${i}]`] = replacement;
108
+ }
109
+ // substituting letter variables with their values. This way substitutedFormulaString is
110
+ // straight arithmetic expression. something like this:
111
+ // '21/9 + 100' or '34' or '9*1-2'
112
+ let substitutedFormulaString = input.formula;
113
+ for (const [key, replacement] of Object.entries(replacements)) {
114
+ substitutedFormulaString = (0, string_1.replaceAll)(substitutedFormulaString, key, `${replacement}`);
115
+ }
116
+ // We want to default to 0 if we can't successfully parse the formula
117
+ const defaultPoints = '0';
118
+ try {
119
+ const value = this.mathjs.evaluate(substitutedFormulaString);
120
+ // checks if the calculated value is actually NaN, then defaults to defaultsPoints(0)
121
+ return Number.isNaN(parseFloat(value))
122
+ ? new decimal_js_1.Decimal(defaultPoints).toFixed(this.outputScale)
123
+ : new decimal_js_1.Decimal(value).toFixed(this.outputScale);
124
+ }
125
+ catch (error) {
126
+ return new decimal_js_1.Decimal(defaultPoints).toFixed(this.outputScale);
127
+ }
128
+ }
129
+ /**
130
+ * This method below is here because it uses the same logic as method calculate and the same configs.
131
+ * @param a is string containing decimal
132
+ * @param b is string containing decimal
133
+ * @returns sum of two decimal strings
134
+ */
135
+ sum(a, b) {
136
+ return new decimal_js_1.Decimal(this.mathjs.evaluate(`${a} + ${b}`)).toFixed(this.outputScale);
137
+ }
138
+ }
139
+ exports.FormulaCalculator = FormulaCalculator;
140
+ //# sourceMappingURL=formula-calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula-calculator.js","sourceRoot":"","sources":["../../src/field-calculation/formula-calculator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { CalculatorError } from './calculator-error';
2
+ export { PolicyFieldCalculatorInput, PolicyCalculationConfig, PolicyFieldCalculatorResponse, FieldCalculationConfig, FieldCalculationService } from './calculator-service';
3
+ export { FormulaCalculator } from './formula-calculator';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormulaCalculator = exports.FieldCalculationService = exports.CalculatorError = void 0;
4
+ var calculator_error_1 = require("./calculator-error");
5
+ Object.defineProperty(exports, "CalculatorError", { enumerable: true, get: function () { return calculator_error_1.CalculatorError; } });
6
+ var calculator_service_1 = require("./calculator-service");
7
+ Object.defineProperty(exports, "FieldCalculationService", { enumerable: true, get: function () { return calculator_service_1.FieldCalculationService; } });
8
+ var formula_calculator_1 = require("./formula-calculator");
9
+ Object.defineProperty(exports, "FormulaCalculator", { enumerable: true, get: function () { return formula_calculator_1.FormulaCalculator; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/field-calculation/index.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,2DAM8B;AAD5B,6HAAA,uBAAuB,OAAA;AAEzB,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA"}
@@ -0,0 +1 @@
1
+ export declare function replaceAll(sourceStr: string, subStr: string, newSubStr: string): string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.replaceAll = void 0;
4
+ function replaceAll(sourceStr, subStr, newSubStr) {
5
+ return sourceStr.split(subStr).join(newSubStr);
6
+ }
7
+ exports.replaceAll = replaceAll;
8
+ //# sourceMappingURL=string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/utils/string.ts"],"names":[],"mappings":";;;AAAA,SAAgB,UAAU,CAAC,SAAiB,EAAE,MAAc,EAAE,SAAiB;IAC7E,OAAO,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACjD,CAAC;AAFD,gCAEC"}
package/package.json CHANGED
@@ -1,10 +1,44 @@
1
1
  {
2
2
  "name": "@catalystcrm/policy-calculator",
3
- "version": "1.0.0",
4
- "description": "Policy calculation module for Catalyst CRM",
5
- "main": "index.js",
6
- "license": "MIT",
7
- "publishConfig": {
8
- "access": "public"
3
+ "version": "5.24.0-dev.11",
4
+ "description": "Collection of utilities to perform policy and premium related calculations",
5
+ "scripts": {
6
+ "test:unit": "mocha --require ts-node/register --exit 'test/unit/**/*.{js,ts}'",
7
+ "test:unit:xunit": "mocha --require ts-node/register --exit --reporter xunit --reporter-options output=../../test-results/unit/policy-calculator.xml --reporter-options suiteName='policy-calculator:unit' 'test/unit/**/*.{js,ts}'",
8
+ "test:acceptance": "mocha --require ts-node/register --extensions js,ts 'test/acceptance/**/*.{js,ts}'",
9
+ "lint": "eslint --report-unused-disable-directives '**/*.{js,ts}'",
10
+ "lint:write": "eslint --report-unused-disable-directives --fix '**/*.{js,ts}'",
11
+ "clean": "rm -rf ./dist",
12
+ "build:release": "npm run clean && tsc -p ./tsconfig.release.json",
13
+ "build": "npm run clean && tsc -p ./tsconfig.release.json"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "decimal.js": "10.4.3",
20
+ "mathjs": "11.8.2",
21
+ "moment": "2.29.4",
22
+ "neverthrow": "5.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/chai": "^4.3.1",
26
+ "@types/chai-subset": "^1.3.3",
27
+ "@types/mocha": "^9.1.1",
28
+ "@typescript-eslint/eslint-plugin": "5.59.0",
29
+ "@typescript-eslint/parser": "5.59.0",
30
+ "chai": "4.3.7",
31
+ "chai-subset": "^1.6.0",
32
+ "eslint": "8.42.0",
33
+ "eslint-config-airbnb-base": "15.0.0",
34
+ "eslint-config-airbnb-typescript": "17.0.0",
35
+ "eslint-config-prettier": "8.8.0",
36
+ "eslint-plugin-import": "2.27.5",
37
+ "eslint-plugin-no-only-tests": "3.3.0",
38
+ "eslint-plugin-prettier": "4.2.1",
39
+ "eslint-plugin-unused-imports": "4.1.4",
40
+ "lint-staged": "^13.0.1",
41
+ "mocha": "10.2.0",
42
+ "prettier": "2.8.8"
9
43
  }
10
44
  }