onroute-policy-engine 0.1.0 → 0.2.1

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.
Files changed (42) hide show
  1. package/.github/workflows/analysis.yml +68 -0
  2. package/.github/workflows/pipeline.yml +47 -0
  3. package/README.md +50 -49
  4. package/dist/enum/accessory-vehicle-type.d.ts +4 -0
  5. package/dist/enum/accessory-vehicle-type.js +8 -0
  6. package/dist/enum/facts.d.ts +5 -1
  7. package/dist/enum/facts.js +4 -0
  8. package/dist/enum/index.d.ts +2 -0
  9. package/dist/enum/index.js +5 -1
  10. package/dist/enum/permit-app-info.d.ts +8 -2
  11. package/dist/enum/permit-app-info.js +8 -2
  12. package/dist/enum/validation-result-code.d.ts +2 -1
  13. package/dist/enum/validation-result-code.js +1 -0
  14. package/dist/enum/validation-result-type.d.ts +2 -1
  15. package/dist/enum/validation-result-type.js +1 -0
  16. package/dist/enum/vehicle-types.d.ts +4 -0
  17. package/dist/enum/vehicle-types.js +8 -0
  18. package/dist/helper/facts.helper.d.ts +2 -9
  19. package/dist/helper/facts.helper.js +63 -27
  20. package/dist/helper/lists.helper.d.ts +13 -0
  21. package/dist/helper/lists.helper.js +32 -2
  22. package/dist/helper/rules-engine.helper.js +33 -4
  23. package/dist/policy-engine.d.ts +82 -2
  24. package/dist/policy-engine.js +516 -6
  25. package/dist/rule-operator/custom-operators.js +5 -1
  26. package/dist/types/commodity.d.ts +10 -3
  27. package/dist/types/cost-rule.d.ts +4 -0
  28. package/dist/types/cost-rule.js +2 -0
  29. package/dist/types/index.d.ts +4 -2
  30. package/dist/types/permit-type.d.ts +3 -2
  31. package/dist/types/policy-definition.d.ts +2 -1
  32. package/dist/types/range-matrix.d.ts +9 -0
  33. package/dist/types/range-matrix.js +2 -0
  34. package/dist/types/region-size-override.d.ts +3 -3
  35. package/dist/types/self-issuable.d.ts +1 -1
  36. package/dist/types/size-dimension.d.ts +7 -7
  37. package/dist/types/vehicle-type.d.ts +1 -0
  38. package/dist/types/vehicle.d.ts +11 -5
  39. package/dist/validation-result.d.ts +1 -0
  40. package/dist/validation-results.d.ts +5 -0
  41. package/dist/validation-results.js +10 -1
  42. package/package.json +77 -76
@@ -0,0 +1,68 @@
1
+ name: Analysis
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
6
+
7
+ concurrency:
8
+ group: ${{ github.workflow }}-${{ github.ref }}
9
+ cancel-in-progress: true
10
+
11
+ jobs:
12
+ validate:
13
+ name: Validate PR
14
+ if: (! github.event.pull_request.draft)
15
+ uses: bcgov/quickstart-openshift-helpers/.github/workflows/.pr-validate.yml@v0.8.1
16
+
17
+ lint:
18
+ name: lint
19
+ if: ${{ ! github.event.pull_request.draft }}
20
+ runs-on: ubuntu-latest # Runs on the latest version of Ubuntu
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4 # Checks out the code from the repository
24
+
25
+ - name: Set up Node.js
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: '20.x'
29
+
30
+ - name: Install dependencies
31
+ run: npm install # Installs project dependencies
32
+
33
+ - name: Lint code
34
+ run: npx eslint . --config .eslintrc.cjs # Run ESLint with the specified config
35
+
36
+
37
+ # https://github.com/marketplace/actions/aqua-security-trivy
38
+ trivy:
39
+ name: Trivy Security Scan
40
+ if: ${{ ! github.event.pull_request.draft }}
41
+ runs-on: ubuntu-22.04
42
+ timeout-minutes: 1
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ - name: Run Trivy vulnerability scanner in repo mode
46
+ uses: aquasecurity/trivy-action@0.24.0
47
+ with:
48
+ format: "sarif"
49
+ output: "trivy-results.sarif"
50
+ ignore-unfixed: true
51
+ scan-type: "fs"
52
+ scanners: "vuln,secret,config"
53
+ severity: "CRITICAL,HIGH"
54
+
55
+ - name: Upload Trivy scan results to GitHub Security tab
56
+ uses: github/codeql-action/upload-sarif@v3
57
+ with:
58
+ sarif_file: "trivy-results.sarif"
59
+
60
+ results:
61
+ name: Analysis Results
62
+ needs: [validate, lint, trivy]
63
+ if: always()
64
+ runs-on: ubuntu-22.04
65
+ steps:
66
+ - if: contains(needs.*.result, 'failure')
67
+ run: echo "At least one job has failed." && exit 1
68
+ - run: echo "Success!"
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: CI/CD Pipleine For Simple Package Publishing
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ packages: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ deploy:
16
+ runs-on: ubuntu-latest
17
+ permissions:
18
+ id-token: write # needed for provenance data generation
19
+
20
+ steps:
21
+ - name: Checkout Code
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Get Next Version
25
+ id: semver
26
+ uses: ietf-tools/semver-action@v1
27
+ with:
28
+ token: ${{ github.token }}
29
+ branch: main
30
+
31
+ - name: Injecting Semver Into Package.json
32
+ run: |
33
+ cat package.json | jq '. + { "version": "${{ steps.semver.outputs.next }}" }' | tee package.json
34
+
35
+ - uses: actions/setup-node@v4
36
+ with:
37
+ node-version: '20.x'
38
+ registry-url: 'https://registry.npmjs.org'
39
+
40
+ - run: npm ci
41
+ - run: tsc
42
+ - run: npm test
43
+
44
+ - name: Publish Package
45
+ run: npm publish --provenance --access public
46
+ env:
47
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md CHANGED
@@ -1,49 +1,50 @@
1
- A JSON-based rules engine to validate onRouteBC permit applications against commercial vehicle policy.
2
-
3
- ## Synopsis
4
- ```orbc-policy-engine``` is a library designed to compare a commercial vehicle permit application against policy expressed in JSON format, and return a list of policy violations as well as other informational policy messages related to the permit.
5
-
6
- ```orbc-policy-engine``` makes use of https://github.com/CacheControl/json-rules-engine for rules engine functionality. Complex rules are modeled by extending the core ```json-rules-engine``` operators and other capabilities.
7
-
8
- ## Usage
9
- ```js
10
- import Policy from 'orbc-policy-engine';
11
-
12
- // Instantiate a new Policy object
13
- // policyConfiguration is a JSON object of type PolicyDefinition
14
- const policy: Policy = new Policy(policyDefinition);
15
-
16
- // Get list of all available permit types (ID and name)
17
- const permitTypes: Map<string, string> = policy.getPermitTypes();
18
-
19
- // Get list of all available commodities (ID and name)
20
- const commodities: Map<string, string> = policy.getCommodities();
21
-
22
- // Get list of all available power unit types
23
- const powerUnits: Map<string, string> = policy.getPowerUnitTypes();
24
-
25
- // Get list of all available trailer types
26
- const trailers: Map<string, string> = policy.getTrailerTypes();
27
-
28
- // Get list of all valid commodities for a given permit type
29
- const commodities: Map<string, string> = policy.getCommodities(permitTypeId);
30
-
31
- // Get list of all vehicle types valid to be added to a configuration,
32
- // by permit type and commodity. Requires supplying the vehicles already
33
- // added to the configuration, or empty array if starting from scratch
34
- const allowableVehicles: Map<string, string> = policy.getAllowableVehicles(
35
- permitTypeId,
36
- commodityId,
37
- currentConfiguration);
38
-
39
- // Validate a permit application against policy
40
- // permitApplication is a JSON object of type PermitApplication
41
- // A PermitApplication is just the standard permitData object wrapped
42
- // in an object with a permitType key. For example:
43
- // {
44
- // permitType: 'TROS',
45
- // permitData: { ... }
46
- // }
47
- const results: ValidationResults = policy.validate(permitApplication);
48
- ```
49
-
1
+ A JSON-based rules engine to validate onRouteBC permit applications against commercial vehicle policy.
2
+
3
+ ## Synopsis
4
+ ```orbc-policy-engine``` is a library designed to compare a commercial vehicle permit application against policy expressed in JSON format, and return a list of policy violations as well as other informational policy messages related to the permit.
5
+
6
+ ```orbc-policy-engine``` makes use of https://github.com/CacheControl/json-rules-engine for rules engine functionality. Complex rules are modeled by extending the core ```json-rules-engine``` operators and other capabilities.
7
+
8
+ ## Usage
9
+ ```js
10
+ import Policy from 'orbc-policy-engine';
11
+
12
+ // Instantiate a new Policy object
13
+ // policyDefinition is a JSON object of type PolicyDefinition
14
+ const policy: Policy = new Policy(policyDefinition);
15
+
16
+ // Get list of all available permit types (ID and name)
17
+ const permitTypes: Map<string, string> = policy.getPermitTypes();
18
+
19
+ // Get list of all available commodities (ID and name)
20
+ const commodities: Map<string, string> = policy.getCommodities();
21
+
22
+ // Get list of all available power unit types
23
+ const powerUnits: Map<string, string> = policy.getPowerUnitTypes();
24
+
25
+ // Get list of all available trailer types
26
+ const trailers: Map<string, string> = policy.getTrailerTypes();
27
+
28
+ // Get list of all valid commodities for a given permit type
29
+ const commodities: Map<string, string> = policy.getCommodities(permitTypeId);
30
+
31
+ // Get list of all vehicle types valid to be added to a configuration,
32
+ // by permit type and commodity. Requires supplying the vehicles already
33
+ // added to the configuration, or empty array if starting from scratch
34
+ const allowableVehicles: Map<string, string> = policy.getNextPermittableVehicles(
35
+ permitTypeId,
36
+ commodityId,
37
+ currentConfiguration);
38
+
39
+ // Validate a permit application against policy
40
+ // permitApplication is a JSON object of type PermitApplication
41
+ // A PermitApplication is the standard permitData object wrapped
42
+ // in an object with a permitType key. For example:
43
+ // {
44
+ // permitType: 'TROS',
45
+ // permitData: { ... }
46
+ // }
47
+ // Note this is an async call due to the reliance on json-rules-engine
48
+ const results: ValidationResults = await policy.validate(permitApplication);
49
+ ```
50
+
@@ -0,0 +1,4 @@
1
+ export declare enum AccessoryVehicleType {
2
+ Booster = "BOOSTER",
3
+ Jeep = "JEEPSRG"
4
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AccessoryVehicleType = void 0;
4
+ var AccessoryVehicleType;
5
+ (function (AccessoryVehicleType) {
6
+ AccessoryVehicleType["Booster"] = "BOOSTER";
7
+ AccessoryVehicleType["Jeep"] = "JEEPSRG";
8
+ })(AccessoryVehicleType || (exports.AccessoryVehicleType = AccessoryVehicleType = {}));
@@ -1,5 +1,9 @@
1
1
  export declare enum PolicyFacts {
2
2
  AllowedVehicles = "allowedVehicles",
3
3
  DaysInPermitYear = "daysInPermitYear",
4
- ValidationDate = "validationDate"
4
+ ValidationDate = "validationDate",
5
+ FixedCost = "fixedCost",
6
+ CostPerMonth = "costPerMonth",
7
+ RangeMatrixCostLookup = "rangeMatrixCostLookup",
8
+ ConfigurationIsValid = "configurationIsValid"
5
9
  }
@@ -6,4 +6,8 @@ var PolicyFacts;
6
6
  PolicyFacts["AllowedVehicles"] = "allowedVehicles";
7
7
  PolicyFacts["DaysInPermitYear"] = "daysInPermitYear";
8
8
  PolicyFacts["ValidationDate"] = "validationDate";
9
+ PolicyFacts["FixedCost"] = "fixedCost";
10
+ PolicyFacts["CostPerMonth"] = "costPerMonth";
11
+ PolicyFacts["RangeMatrixCostLookup"] = "rangeMatrixCostLookup";
12
+ PolicyFacts["ConfigurationIsValid"] = "configurationIsValid";
9
13
  })(PolicyFacts || (exports.PolicyFacts = PolicyFacts = {}));
@@ -1,5 +1,7 @@
1
+ export { AccessoryVehicleType } from './accessory-vehicle-type';
1
2
  export { PolicyFacts } from './facts';
2
3
  export { PermitAppInfo } from './permit-app-info';
3
4
  export { RelativePosition } from './relative-position';
4
5
  export { ValidationResultCode } from './validation-result-code';
5
6
  export { ValidationResultType } from './validation-result-type';
7
+ export { VehicleTypes } from './vehicle-types';
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ValidationResultType = exports.ValidationResultCode = exports.RelativePosition = exports.PermitAppInfo = exports.PolicyFacts = void 0;
3
+ exports.VehicleTypes = exports.ValidationResultType = exports.ValidationResultCode = exports.RelativePosition = exports.PermitAppInfo = exports.PolicyFacts = exports.AccessoryVehicleType = void 0;
4
+ var accessory_vehicle_type_1 = require("./accessory-vehicle-type");
5
+ Object.defineProperty(exports, "AccessoryVehicleType", { enumerable: true, get: function () { return accessory_vehicle_type_1.AccessoryVehicleType; } });
4
6
  var facts_1 = require("./facts");
5
7
  Object.defineProperty(exports, "PolicyFacts", { enumerable: true, get: function () { return facts_1.PolicyFacts; } });
6
8
  var permit_app_info_1 = require("./permit-app-info");
@@ -11,3 +13,5 @@ var validation_result_code_1 = require("./validation-result-code");
11
13
  Object.defineProperty(exports, "ValidationResultCode", { enumerable: true, get: function () { return validation_result_code_1.ValidationResultCode; } });
12
14
  var validation_result_type_1 = require("./validation-result-type");
13
15
  Object.defineProperty(exports, "ValidationResultType", { enumerable: true, get: function () { return validation_result_type_1.ValidationResultType; } });
16
+ var vehicle_types_1 = require("./vehicle-types");
17
+ Object.defineProperty(exports, "VehicleTypes", { enumerable: true, get: function () { return vehicle_types_1.VehicleTypes; } });
@@ -4,7 +4,13 @@
4
4
  * referenced from within source code.
5
5
  */
6
6
  export declare enum PermitAppInfo {
7
- PermitStartDate = "permitData.startDate",
7
+ PermitType = "permitType",
8
+ PermitData = "permitData",
9
+ PermitStartDate = "$.startDate",
8
10
  PermitDateFormat = "YYYY-MM-DD",
9
- CompanyName = "permitData.companyName"
11
+ CompanyName = "$.companyName",
12
+ PermitDuration = "$.permitDuration",
13
+ PowerUnitType = "$.vehicleDetails.vehicleSubType",
14
+ TrailerList = "$.vehicleConfiguration.trailers",
15
+ Commodity = "$.permittedCommodity.commodityType"
10
16
  }
@@ -8,7 +8,13 @@ exports.PermitAppInfo = void 0;
8
8
  */
9
9
  var PermitAppInfo;
10
10
  (function (PermitAppInfo) {
11
- PermitAppInfo["PermitStartDate"] = "permitData.startDate";
11
+ PermitAppInfo["PermitType"] = "permitType";
12
+ PermitAppInfo["PermitData"] = "permitData";
13
+ PermitAppInfo["PermitStartDate"] = "$.startDate";
12
14
  PermitAppInfo["PermitDateFormat"] = "YYYY-MM-DD";
13
- PermitAppInfo["CompanyName"] = "permitData.companyName";
15
+ PermitAppInfo["CompanyName"] = "$.companyName";
16
+ PermitAppInfo["PermitDuration"] = "$.permitDuration";
17
+ PermitAppInfo["PowerUnitType"] = "$.vehicleDetails.vehicleSubType";
18
+ PermitAppInfo["TrailerList"] = "$.vehicleConfiguration.trailers";
19
+ PermitAppInfo["Commodity"] = "$.permittedCommodity.commodityType";
14
20
  })(PermitAppInfo || (exports.PermitAppInfo = PermitAppInfo = {}));
@@ -2,5 +2,6 @@ export declare enum ValidationResultCode {
2
2
  PermitTypeUnknown = "permit-type-unknown",
3
3
  FieldValidationError = "field-validation-error",
4
4
  ConfigurationInvalid = "configuration-invalid",
5
- GeneralResult = "general-result"
5
+ GeneralResult = "general-result",
6
+ CostValue = "cost-value"
6
7
  }
@@ -7,4 +7,5 @@ var ValidationResultCode;
7
7
  ValidationResultCode["FieldValidationError"] = "field-validation-error";
8
8
  ValidationResultCode["ConfigurationInvalid"] = "configuration-invalid";
9
9
  ValidationResultCode["GeneralResult"] = "general-result";
10
+ ValidationResultCode["CostValue"] = "cost-value";
10
11
  })(ValidationResultCode || (exports.ValidationResultCode = ValidationResultCode = {}));
@@ -2,5 +2,6 @@ export declare enum ValidationResultType {
2
2
  Violation = "violation",
3
3
  Requirement = "requirement",
4
4
  Warning = "warning",
5
- Information = "information"
5
+ Information = "information",
6
+ Cost = "cost"
6
7
  }
@@ -7,4 +7,5 @@ var ValidationResultType;
7
7
  ValidationResultType["Requirement"] = "requirement";
8
8
  ValidationResultType["Warning"] = "warning";
9
9
  ValidationResultType["Information"] = "information";
10
+ ValidationResultType["Cost"] = "cost";
10
11
  })(ValidationResultType || (exports.ValidationResultType = ValidationResultType = {}));
@@ -0,0 +1,4 @@
1
+ export declare enum VehicleTypes {
2
+ PowerUnits = "powerUnits",
3
+ Trailers = "trailers"
4
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VehicleTypes = void 0;
4
+ var VehicleTypes;
5
+ (function (VehicleTypes) {
6
+ VehicleTypes["PowerUnits"] = "powerUnits";
7
+ VehicleTypes["Trailers"] = "trailers";
8
+ })(VehicleTypes || (exports.VehicleTypes = VehicleTypes = {}));
@@ -1,15 +1,8 @@
1
1
  import { Engine } from 'json-rules-engine';
2
- import { PermitFacts } from 'onroute-policy-engine/types';
2
+ import { Policy } from '../policy-engine';
3
3
  /**
4
4
  * Adds runtime facts for the validation. For example, adds the
5
5
  * validation date for comparison against startDate of the permit.
6
6
  * @param engine json-rules-engine Engine instance to add facts to.
7
7
  */
8
- export declare function addRuntimeFacts(engine: Engine): void;
9
- /**
10
- * Flattens the permit application, using keys taken from the PermitFacts enum so
11
- * the facts can be used more easily within validation rules.
12
- * @param permitApplication Permit application object to flatten.
13
- * @returns Flattened permit application object for validation.
14
- */
15
- export declare function transformPermitFacts(permitApplication: any): PermitFacts;
8
+ export declare function addRuntimeFacts(engine: Engine, policy: Policy): void;
@@ -3,39 +3,75 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.transformPermitFacts = exports.addRuntimeFacts = void 0;
6
+ exports.addRuntimeFacts = addRuntimeFacts;
7
7
  const dayjs_1 = __importDefault(require("dayjs"));
8
- const flattie_1 = require("flattie");
9
8
  const enum_1 = require("onroute-policy-engine/enum");
10
9
  /**
11
10
  * Adds runtime facts for the validation. For example, adds the
12
11
  * validation date for comparison against startDate of the permit.
13
12
  * @param engine json-rules-engine Engine instance to add facts to.
14
13
  */
15
- function addRuntimeFacts(engine) {
16
- const today = (0, dayjs_1.default)().format(enum_1.PermitAppInfo.PermitDateFormat.toString());
17
- engine.addFact(enum_1.PolicyFacts.ValidationDate.toString(), today);
18
- // Will be either 365 or 366, for use when comparing against
19
- // duration for 1 year permits.
20
- engine.addFact(enum_1.PolicyFacts.DaysInPermitYear.toString(), async function (params, almanac) {
21
- const startDate = await almanac.factValue(enum_1.PermitAppInfo.PermitStartDate.toString());
22
- const dateFrom = (0, dayjs_1.default)(startDate, enum_1.PermitAppInfo.PermitDateFormat.toString());
23
- return dateFrom.diff(dateFrom.add(1, 'year'), 'day');
14
+ function addRuntimeFacts(engine, policy) {
15
+ const today = (0, dayjs_1.default)().format(enum_1.PermitAppInfo.PermitDateFormat);
16
+ engine.addFact(enum_1.PolicyFacts.ValidationDate, today);
17
+ /**
18
+ * Add runtime fact for number of days in the permit year.
19
+ * Will be either 365 or 366, for use when comparing against
20
+ * duration for 1 year permits.
21
+ */
22
+ engine.addFact(enum_1.PolicyFacts.DaysInPermitYear, async function (params, almanac) {
23
+ const startDate = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.PermitStartDate);
24
+ const dateFrom = (0, dayjs_1.default)(startDate, enum_1.PermitAppInfo.PermitDateFormat);
25
+ const daysInPermitYear = dateFrom.add(1, 'year').diff(dateFrom, 'day');
26
+ return daysInPermitYear;
27
+ });
28
+ /**
29
+ * Adds a runtime fact specifying whether the vehicle configuration
30
+ * in the permit application is valid for the permit type and
31
+ * commodity. Will return true or false.
32
+ */
33
+ engine.addFact(enum_1.PolicyFacts.ConfigurationIsValid.toString(), async function (params, almanac) {
34
+ const powerUnit = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.PowerUnitType);
35
+ const trailerList = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.TrailerList);
36
+ let fullVehicleConfiguration = [];
37
+ fullVehicleConfiguration.push(powerUnit);
38
+ fullVehicleConfiguration = fullVehicleConfiguration.concat(trailerList.map((t) => t.vehicleSubType));
39
+ const permitType = await almanac.factValue(enum_1.PermitAppInfo.PermitType);
40
+ const commodity = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.Commodity);
41
+ let isValid;
42
+ try {
43
+ isValid = policy.isConfigurationValid(permitType, commodity, fullVehicleConfiguration);
44
+ }
45
+ catch (e) {
46
+ console.log(`Error validating vehicle configuration: '{e.message}'`);
47
+ isValid = false;
48
+ }
49
+ return isValid;
50
+ });
51
+ /**
52
+ * Add runtime fact for a fixed permit cost, the cost supplied
53
+ * as a parameter.
54
+ */
55
+ engine.addFact(enum_1.PolicyFacts.FixedCost.toString(), async function (params) {
56
+ return params.cost;
57
+ });
58
+ /**
59
+ * Add runtime fact for cost per month, where month is defined by
60
+ * policy as a 30 day period or portion thereof, except in the
61
+ * case of a full year in which case it is 12 months.
62
+ */
63
+ engine.addFact(enum_1.PolicyFacts.CostPerMonth.toString(), async function (params, almanac) {
64
+ const duration = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.PermitDuration);
65
+ const daysInPermitYear = await almanac.factValue(enum_1.PolicyFacts.DaysInPermitYear.toString());
66
+ let months = Math.floor(duration / 30);
67
+ const extraDays = duration % 30;
68
+ if (extraDays > 0 && duration !== daysInPermitYear) {
69
+ // Add an extra month for a partial month unless it is
70
+ // a full year. Note this does not handle the case where 2
71
+ // or more years duration is specified, since that is not
72
+ // a valid permit and does not warrant considetation.
73
+ months++;
74
+ }
75
+ return months * params.cost;
24
76
  });
25
77
  }
26
- exports.addRuntimeFacts = addRuntimeFacts;
27
- /**
28
- * Flattens the permit application, using keys taken from the PermitFacts enum so
29
- * the facts can be used more easily within validation rules.
30
- * @param permitApplication Permit application object to flatten.
31
- * @returns Flattened permit application object for validation.
32
- */
33
- function transformPermitFacts(permitApplication) {
34
- // Flatten the permit application so all properties can be accessed
35
- // by key
36
- const permitFacts = (0, flattie_1.flattie)(permitApplication);
37
- // Add the app itself as a fact to be used by more complex rules
38
- permitFacts.app = permitApplication;
39
- return permitFacts;
40
- }
41
- exports.transformPermitFacts = transformPermitFacts;
@@ -9,3 +9,16 @@ import { IdentifiedObject } from 'onroute-policy-engine/types';
9
9
  * @returns Map of object ID to object name.
10
10
  */
11
11
  export declare function extractIdentifiedObjects(objects: Array<IdentifiedObject>, filter?: Array<string>): Map<string, string>;
12
+ /**
13
+ * Intersects two maps containing string id and string description to
14
+ * return a new map containing those entries common to both.
15
+ * This only checks that the keys are common, not the values. If the
16
+ * values are different, this returns the value from the first map.
17
+ * If any values in the first map are null or undefined, these will
18
+ * be replaced with empty string.
19
+ * @param first The first map
20
+ * @param second The second map
21
+ * @returns New map containing entries common to both input maps
22
+ */
23
+ export declare function intersectIdMaps(first: Map<string, string>, second: Map<string, string>): Map<string, string>;
24
+ export declare function getIdFromName(list: Array<IdentifiedObject>, name: string): string | null;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractIdentifiedObjects = void 0;
3
+ exports.extractIdentifiedObjects = extractIdentifiedObjects;
4
+ exports.intersectIdMaps = intersectIdMaps;
5
+ exports.getIdFromName = getIdFromName;
4
6
  /**
5
7
  * Extracts a map containing just the ID and name of each of the supplied
6
8
  * identified objects.
@@ -19,4 +21,32 @@ function extractIdentifiedObjects(objects, filter) {
19
21
  });
20
22
  return objectMap;
21
23
  }
22
- exports.extractIdentifiedObjects = extractIdentifiedObjects;
24
+ /**
25
+ * Intersects two maps containing string id and string description to
26
+ * return a new map containing those entries common to both.
27
+ * This only checks that the keys are common, not the values. If the
28
+ * values are different, this returns the value from the first map.
29
+ * If any values in the first map are null or undefined, these will
30
+ * be replaced with empty string.
31
+ * @param first The first map
32
+ * @param second The second map
33
+ * @returns New map containing entries common to both input maps
34
+ */
35
+ function intersectIdMaps(first, second) {
36
+ var _a;
37
+ const combinedMap = new Map();
38
+ for (const key in first.keys()) {
39
+ if (second.has(key)) {
40
+ combinedMap.set(key, (_a = first.get(key)) !== null && _a !== void 0 ? _a : '');
41
+ }
42
+ }
43
+ return combinedMap;
44
+ }
45
+ function getIdFromName(list, name) {
46
+ let id = null;
47
+ const identifiedObject = list.find((i) => i.name == name);
48
+ if (identifiedObject) {
49
+ id = identifiedObject.id;
50
+ }
51
+ return id;
52
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRulesEngines = void 0;
3
+ exports.getRulesEngines = getRulesEngines;
4
4
  const json_rules_engine_1 = require("json-rules-engine");
5
5
  const custom_operators_1 = require("../rule-operator/custom-operators");
6
6
  const enum_1 = require("onroute-policy-engine/enum");
@@ -11,7 +11,10 @@ const enum_1 = require("onroute-policy-engine/enum");
11
11
  * @returns json-rules-engine Engine instance.
12
12
  */
13
13
  function getEngine(policyDefinition) {
14
- const engine = new json_rules_engine_1.Engine();
14
+ const engine = new json_rules_engine_1.Engine([], {
15
+ replaceFactsInEventParams: true,
16
+ allowUndefinedFacts: true,
17
+ });
15
18
  custom_operators_1.CustomOperators.forEach((o) => engine.addOperator(o));
16
19
  policyDefinition.commonRules.forEach((r) => engine.addRule(r));
17
20
  return engine;
@@ -27,9 +30,36 @@ function getRulesEngines(policy) {
27
30
  var _a, _b;
28
31
  const engineMap = new Map();
29
32
  (_b = (_a = policy.policyDefinition) === null || _a === void 0 ? void 0 : _a.permitTypes) === null || _b === void 0 ? void 0 : _b.forEach((permitType) => {
30
- var _a;
33
+ var _a, _b;
31
34
  const engine = getEngine(policy.policyDefinition);
32
35
  (_a = permitType.rules) === null || _a === void 0 ? void 0 : _a.forEach((r) => engine.addRule(r));
36
+ // Convert the cost definitions into proper rules so the
37
+ // results can be added to the validation run. This takes advantage
38
+ // of the replaceFactsInEventParams option for the json-rules-engine
39
+ // Engine object.
40
+ (_b = permitType.costRules) === null || _b === void 0 ? void 0 : _b.forEach((c) => {
41
+ const costRule = {
42
+ conditions: {
43
+ all: [
44
+ {
45
+ fact: c.fact,
46
+ params: c.params,
47
+ operator: 'greaterThanInclusive',
48
+ value: 0,
49
+ },
50
+ ],
51
+ },
52
+ event: {
53
+ type: 'cost',
54
+ params: {
55
+ message: 'Calculated permit cost',
56
+ code: 'cost-value',
57
+ cost: c,
58
+ },
59
+ },
60
+ };
61
+ engine.addRule(costRule);
62
+ });
33
63
  let allowedVehicles;
34
64
  if (permitType.allowedVehicles && permitType.allowedVehicles.length > 0) {
35
65
  allowedVehicles = permitType.allowedVehicles;
@@ -44,4 +74,3 @@ function getRulesEngines(policy) {
44
74
  });
45
75
  return engineMap;
46
76
  }
47
- exports.getRulesEngines = getRulesEngines;