From 30685f3667b13cd561cd5228463d86b7d41c6f0a Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 03:26:41 +0200 Subject: [PATCH 01/11] ubt --- .DS_Store | Bin 0 -> 8196 bytes docs/customruleguide.md | 4 +- package-lock.json | 185 +- package.json | 5 +- readme.md | 6 +- src/index.ts | 5 + src/main/libs/ParseFlows.ts | 24 + src/main/libs/ScanFlows.ts | 2 +- src/main/models/Flow.ts | 58 +- src/main/models/FlowElementConnector.ts | 4 +- src/main/models/FlowNode.ts | 14 +- src/main/models/FlowResource.ts | 2 +- src/main/models/FlowVariable.ts | 4 +- src/main/rules/APIVersion.ts | 4 +- tests/.DS_Store | Bin 0 -> 6148 bytes tests/ParsingTest.test.ts | 14 + tests/xmlfiles/Copy_API_Name.flow-meta.xml | 60 + .../Copy_API_Name_Fixed.flow-meta.xml | 60 + .../DML_Statement_In_A_Loop.flow-meta.xml | 105 + ...ML_Statement_In_A_Loop_Fixed.flow-meta.xml | 143 + .../Duplicate_DML_Operation.flow-meta.xml | 112 + ...uplicate_DML_Operation_Fixed.flow-meta.xml | 112 + .../FlowNamingConvention.flow-meta.xml | 62 + ...Flow_Naming_Convention_Fixed.flow-meta.xml | 62 + tests/xmlfiles/Hardcoded_Id.flow-meta.xml | 83 + .../xmlfiles/Hardcoded_Id_Fixed.flow-meta.xml | 156 + .../Missing_Error_Handler.flow-meta.xml | 46 + .../Missing_Error_Handler_Fixed.flow-meta.xml | 66 + .../Missing_Flow_Description.flow-meta.xml | 57 + ...ssing_Flow_Description_Fixed.flow-meta.xml | 58 + .../Missing_Null_Handler.flow-meta.xml | 89 + .../Missing_Null_Handler_Fixed.flow-meta.xml | 138 + .../Outdated_API_Version.flow-meta.xml | 45 + .../Outdated_API_Version_Fixed.flow-meta.xml | 46 + .../SOQL_Query_In_A_Loop.flow-meta.xml | 117 + .../SOQL_Query_In_A_Loop_Fixed.flow-meta.xml | 110 + .../Unconnected_Element.flow-meta.xml | 73 + .../Unconnected_Element_Fixed.flow-meta.xml | 59 + yarn.lock | 3094 ++++++----------- 39 files changed, 3144 insertions(+), 2140 deletions(-) create mode 100644 .DS_Store create mode 100644 src/main/libs/ParseFlows.ts create mode 100644 tests/.DS_Store create mode 100644 tests/ParsingTest.test.ts create mode 100644 tests/xmlfiles/Copy_API_Name.flow-meta.xml create mode 100644 tests/xmlfiles/Copy_API_Name_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/DML_Statement_In_A_Loop.flow-meta.xml create mode 100644 tests/xmlfiles/DML_Statement_In_A_Loop_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Duplicate_DML_Operation.flow-meta.xml create mode 100644 tests/xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/FlowNamingConvention.flow-meta.xml create mode 100644 tests/xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Hardcoded_Id.flow-meta.xml create mode 100644 tests/xmlfiles/Hardcoded_Id_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Error_Handler.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Error_Handler_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Flow_Description.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Null_Handler.flow-meta.xml create mode 100644 tests/xmlfiles/Missing_Null_Handler_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Outdated_API_Version.flow-meta.xml create mode 100644 tests/xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/SOQL_Query_In_A_Loop.flow-meta.xml create mode 100644 tests/xmlfiles/SOQL_Query_In_A_Loop_Fixed.flow-meta.xml create mode 100644 tests/xmlfiles/Unconnected_Element.flow-meta.xml create mode 100644 tests/xmlfiles/Unconnected_Element_Fixed.flow-meta.xml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5c610eb885351dac0a3de9b93a4d87fb7d5b97ab GIT binary patch literal 8196 zcmeHMT}&KR6u#d8?Tk!eK-$vkWEatbl%~*<)WfiRTa9nVpGF@{l%&DL#GeNfe_k|JO-%IMxwE7|c{8TkxyilX z+;i?Z!#(qzxqAl27&`MtD`T~cF_}6?t(=C-G_L1;Rg*$V2_eXyG0*l2U1{4*uUZ=k zq6kD0h$0Y0Ac{Z~fh!{dbY}A=uW{}RZ8Sy^h$3)RMu5K`;?y}NLYx;EygFzIN&v!A z5(ka0sSXHi;vptNoEI3Fl21`RAT&i-VnCRaKF*gDCPJJSD9jmzIYW47gcS;cyOUi! zSk90T7>!W`q6n;x0I%K4n9oe+(RfMyUXo1D+Lq_Hw0r@nq_k|^dRe)qT-~6LjE;>@ zsFPZC!7}IiXMM|cyt~buM>wffdNb}^Z^m^Fv)q|RVHO;@^;EMJ8XN< zI$@Hm(#zyr+dkxa7I!l?>YK-Wu3M!V9rxUv-xW9;waC9%rR6zcU*?Qgey1sIC(aUH)Z5_>9{&B5dmc>2l^m;{mOTNdTKcvq!xJM(< z=yiI7EKhKGSI(qSh}9;&SZKkDrff3IcBaXKP=0^!zDTQ)NNS4yQCcEO3iW#mQPQDo()0X zlj{?^1>foujp0R+e?g4v6D?w{(7Rt}yI7JPU{fr|9%LukDfS{e!_KmE>_he`yTHC= z-?5+BFYF@wjs1x-lw%`wY(pb%MiX|U4STQ`N%Y|$`Y{0mCZ;iiEDD&zah$*-cpOjQ zNj!z8aT?FzdAxv^@jBkXn|K%R;{$wz^SFSo@I8LOkN6cA@jL#IN~H}_g;XikNlnsr zsaa~55>l@;AWcY9k|j1Eg@+Qmx46Mjem~*z?3xu{$E4Gj&#qX{9e4KLbp>bFVg=8q zYil-c+8n>BX=fW{*%IpnNsGL^lmnB9(@qh*^=_wLVjSW){n8()2KW#nFRe6E0 zuDd~vX=RipV!Ew?rt2s}#B_UeET&16m}1(}8dJ3rN;@U6EpLvg;pHv+R8=db^b?xf zb(*qp($PsycrwZV6s zg0u&glNR4DCv9Oc=h&_@P0}LGmm5U0|7ZmG*-x#O*Z=8.0" + } + }, + "node_modules/@oozcitak/infra": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz", + "integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==", + "dependencies": { + "@oozcitak/util": "8.3.8" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@oozcitak/url": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz", + "integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==", + "dependencies": { + "@oozcitak/infra": "1.0.8", + "@oozcitak/util": "8.3.8" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/@oozcitak/util": { + "version": "8.3.8", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz", + "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==", + "engines": { + "node": ">=8.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -210,6 +259,11 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/path-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/path-browserify/-/path-browserify-1.0.2.tgz", + "integrity": "sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA==" + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -572,7 +626,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -674,26 +727,6 @@ "node": "*" } }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -706,18 +739,6 @@ "node": ">= 6" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -1040,6 +1061,38 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1146,6 +1199,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1285,8 +1343,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/string-width": { "version": "4.2.3", @@ -1519,6 +1576,26 @@ "node": ">=0.8.0" } }, + "node_modules/tslint/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/tslint/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1655,6 +1732,40 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xmlbuilder2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz", + "integrity": "sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==", + "dependencies": { + "@oozcitak/dom": "1.15.10", + "@oozcitak/infra": "1.0.8", + "@oozcitak/util": "8.3.8", + "js-yaml": "3.14.1" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/xmlbuilder2/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/xmlbuilder2/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 4d2ce3d..156db5a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "@types/chai": "^4.2.21", "@types/mocha": "^9.0.0", "@types/node": "^20.4.5", - "@types/path-browserify": "^1", "chai": "^4.3.4", "logging": "^3.3.0", "mocha": "^9.1.1", @@ -25,6 +24,8 @@ }, "packageManager": "yarn@4.1.1", "dependencies": { - "path-browserify": "^1.0.1" + "@types/path-browserify": "^1.0.2", + "path-browserify": "^1.0.1", + "xmlbuilder2": "^3.1.1" } } diff --git a/readme.md b/readme.md index 095aa38..2e14e2c 100644 --- a/readme.md +++ b/readme.md @@ -104,13 +104,13 @@ Follow these steps to set up your development environment: ```bash cd lightning-flow-scanner-core - yarn install + npm install ``` 3. **Build**: Compile the TypeScript source files into JavaScript using the TypeScript compiler: ```bash - yarn build + npm run build ``` This command generates the compiled JavaScript files in the `out` directory. @@ -118,7 +118,7 @@ Follow these steps to set up your development environment: 4. **Run Tests**: Ensure the module functions correctly by running the test suites: ```bash - yarn test + npm run test ``` This command uses Mocha to run tests located in the `tests` directory and provides feedback on the module's functionality. diff --git a/src/index.ts b/src/index.ts index 11c26b6..499f3be 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import {IRuleDefinition} from './main/interfaces/IRuleDefinition'; import { IRulesConfig } from './main/interfaces/IRulesConfig'; import { FixFlows } from './main/libs/FixFlows'; import { GetRuleDefinitions } from './main/libs/GetRuleDefinitions'; +import { ParseFlows } from './main/libs/ParseFlows'; import { ScanFlows } from './main/libs/ScanFlows'; import {Flow} from './main/models/Flow'; import {ResultDetails} from './main/models/ResultDetails'; @@ -17,6 +18,10 @@ export function getRules(ruleNames?: string[]): IRuleDefinition[] { } } +export function parse(selectedUris: any): Promise { + return ParseFlows(selectedUris); +} + export function scan(flows: Flow[], ruleOptions?: IRulesConfig): ScanResult[] { let scanResults: ScanResult[]; diff --git a/src/main/libs/ParseFlows.ts b/src/main/libs/ParseFlows.ts new file mode 100644 index 0000000..7689068 --- /dev/null +++ b/src/main/libs/ParseFlows.ts @@ -0,0 +1,24 @@ +import p from "path-browserify"; +import { Flow } from '../models/Flow'; +import * as fs from 'fs'; +import { convert } from 'xmlbuilder2'; + +export async function ParseFlows(selectedUris: string[]) { + + let parsedFlows: Flow[] = []; + for (let uri of selectedUris) { + try { + let content = await fs.readFileSync(p.normalize(uri)); + let xmlString = content.toString(); + const flowObj = convert(xmlString, { format: 'object' }); + parsedFlows.push(new Flow( + { + 'path': uri, + xmldata: flowObj + })); + } catch (e) { + // todo catch error + } + } + return parsedFlows; +} diff --git a/src/main/libs/ScanFlows.ts b/src/main/libs/ScanFlows.ts index 3192037..0313beb 100644 --- a/src/main/libs/ScanFlows.ts +++ b/src/main/libs/ScanFlows.ts @@ -22,7 +22,7 @@ export function ScanFlows( const ruleResults: core.RuleResult[] = []; for (const rule of selectedRules) { try { - if (rule.supportedTypes.includes(flow.type[0])) { + if (rule.supportedTypes.includes(flow.type)) { let config = undefined; if ( ruleOptions && diff --git a/src/main/models/Flow.ts b/src/main/models/Flow.ts index adbdbee..d591b2c 100644 --- a/src/main/models/Flow.ts +++ b/src/main/models/Flow.ts @@ -46,7 +46,7 @@ export class Flow { 'isAdditionalPermissionRequiredToRun', 'migratedFromWorkflowRuleName', 'triggerOrder', - 'Environments', + 'environments', 'segment' ]; private flowNodes = [ @@ -76,6 +76,8 @@ export class Flow { flowName = flowName.split('.')[0] } this.name = flowName; + + // todo fix if(args.xmldata && args.xmldata.Flow){ this.xmldata = args.xmldata.Flow; } else if(args.xmldata){ @@ -96,36 +98,48 @@ export class Flow { this.type = this.xmldata.processType; const allNodes: (FlowVariable | FlowNode | FlowMetadata)[] = []; for (const nodeType in this.xmldata) { - const nodesOfType = this.xmldata[nodeType]; // skip xmlns url - if (nodeType == '$') { - this.root = nodesOfType; - continue; - } + // if (nodeType == "@xmlns") { + // continue; + // } if (this.flowMetadata.includes(nodeType)) { - for (const node of nodesOfType) { + let data = this.xmldata[nodeType]; + if (Array.isArray(data)) { + for (const node of data) { + allNodes.push(new FlowMetadata(nodeType, data[node])); + } + } else { allNodes.push(new FlowMetadata( nodeType, - node + this.xmldata[nodeType] )); } } else if (this.flowVariables.includes(nodeType)) { - for (const node of nodesOfType) { - allNodes.push( - new FlowVariable(node.name, nodeType, node) - ); + let data = this.xmldata[nodeType]; + if (Array.isArray(data)) { + for (const node of data) { + allNodes.push(new FlowVariable(data[node].name, nodeType, data[node])); + } + } else { + allNodes.push(new FlowVariable(data.name, nodeType, data)); } } else if (this.flowNodes.includes(nodeType)) { - for (const node of nodesOfType) { - allNodes.push( - new FlowNode(node.name, nodeType, node) - ); + let data = this.xmldata[nodeType]; + if (Array.isArray(data)) { + for (const node of data) { + allNodes.push(new FlowNode(data[node].name, nodeType, data[node])); + } + } else { + allNodes.push(new FlowNode(data.name, nodeType, data)); } } else if (this.flowResources.includes(nodeType)) { - for (const node of nodesOfType) { - allNodes.push( - new FlowResource(node.name, nodeType, node) - ); + let data = this.xmldata[nodeType]; + if (Array.isArray(data)) { + for (const node of data) { + allNodes.push(new FlowResource(data[node].name, nodeType, data[node])); + } + } else { + allNodes.push(new FlowResource(data.name, nodeType, data)); } } } @@ -137,14 +151,14 @@ export class Flow { let start = ''; const flowElements: FlowNode[] = this.elements.filter(node => node instanceof FlowNode) as FlowNode[]; if (this.startElementReference) { - start = this.startElementReference[0]; + start = this.startElementReference; } else if(flowElements.find(n => { return n.subtype === 'start'; })){ let startElement = flowElements.find(n => { return n.subtype === 'start'; }); - start = startElement.connectors[0].reference; + start = startElement.connectors['reference']; } return start; } diff --git a/src/main/models/FlowElementConnector.ts b/src/main/models/FlowElementConnector.ts index c6f9a9b..31d4284 100644 --- a/src/main/models/FlowElementConnector.ts +++ b/src/main/models/FlowElementConnector.ts @@ -14,8 +14,8 @@ export class FlowElementConnector{ this.childName = args.childName ? args.childName : undefined; this.childOf = args.childOf ? args.childOf : undefined; - if(element && element[0] && element[0].targetReference && element[0].targetReference[0]){ - this.reference = element[0].targetReference[0]; + if(element && element['targetReference']){ + this.reference = element['targetReference']; } } } diff --git a/src/main/models/FlowNode.ts b/src/main/models/FlowNode.ts index 69104d9..5d5f4b1 100644 --- a/src/main/models/FlowNode.ts +++ b/src/main/models/FlowNode.ts @@ -10,13 +10,13 @@ export class FlowNode extends FlowElement { constructor(name: string, subtype: string, element: object) { super('node', subtype, element); - this.name = (subtype === 'start' ? 'flowstart' : name[0]); + this.name = (subtype === 'start' ? 'flowstart' : name); const connectors = this.getConnectors(subtype, element); - if (connectors.length > 0 && connectors[0] !== undefined) { + if (connectors !== undefined && connectors.length > 0) { this.connectors = connectors; } - this.locationX = element["locationX"][0]; - this.locationY = element["locationY"][0]; + this.locationX = element["locationX"]; + this.locationY = element["locationY"]; } private getConnectors(subtype, element) { @@ -31,7 +31,7 @@ export class FlowNode extends FlowElement { if (asyncElement.connector) { connectors.push( new FlowElementConnector('connector', asyncElement.connector, { - childName: asyncElement?.name?.[0] ?? 'AsyncAfterCommit', + childName: asyncElement?.name ?? 'AsyncAfterCommit', childOf: 'rules' }) ) @@ -48,7 +48,7 @@ export class FlowNode extends FlowElement { if (rule.connector) { connectors.push( new FlowElementConnector('connector', rule.connector, { - childName: rule.name[0], + childName: rule.name, childOf: 'rules' }) ); @@ -95,7 +95,7 @@ export class FlowNode extends FlowElement { if (waitEvent.connector) { connectors.push( new FlowElementConnector('connector', waitEvent.connector, { - childName: waitEvent.name[0], + childName: waitEvent.name, childOf: 'rules' }) ); diff --git a/src/main/models/FlowResource.ts b/src/main/models/FlowResource.ts index 29fd9c8..f297f20 100644 --- a/src/main/models/FlowResource.ts +++ b/src/main/models/FlowResource.ts @@ -6,6 +6,6 @@ export class FlowResource extends FlowElement { constructor(name: string, subtype: string, element: object) { super('resource', subtype, element); - this.name = name[0]; + this.name = name; } } diff --git a/src/main/models/FlowVariable.ts b/src/main/models/FlowVariable.ts index 1b455f3..7e57c59 100644 --- a/src/main/models/FlowVariable.ts +++ b/src/main/models/FlowVariable.ts @@ -7,7 +7,7 @@ export class FlowVariable extends FlowElement { constructor(name: string, subtype: string, element: object) { super('variable', subtype, element); - this.name = name[0]; - this.dataType = element["dataType"][0]; + this.name = name; + this.dataType = element["dataType"]; } } diff --git a/src/main/rules/APIVersion.ts b/src/main/rules/APIVersion.ts index efa8680..77ad1f5 100644 --- a/src/main/rules/APIVersion.ts +++ b/src/main/rules/APIVersion.ts @@ -18,8 +18,8 @@ export class APIVersion extends RuleCommon implements core.IRuleDefinition { public execute(flow: core.Flow, options?: { expression: string }): core.RuleResult { let flowAPIVersionNumber: number; - if (flow.xmldata.apiVersion && flow.xmldata.apiVersion[0]) { - const flowAPIVersion = flow.xmldata.apiVersion[0]; + if (flow.xmldata.apiVersion) { + const flowAPIVersion = flow.xmldata.apiVersion; flowAPIVersionNumber = +flowAPIVersion; } if (flowAPIVersionNumber) { diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..000a841fbb24ebc2ea302826e57a29a5a2bb649c GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8-BN@c6nb3nTClZ66fdFH7cim+mD-S~!8BW%)(WMNv%Zi|;`2DO zy8%mc@FZeqVDrt+&+g6#*&oIj@6CcXV-90XKttrH6bPCNT_qcg$n_Wzi&@B0f1ZvD z2KtL8T)SYeYy>NRVBgm7$I1uahd+*^blPft@>037wOtieQ5SdKlbUql&*2Lca!Rf`|IUXhI&5+4~cP%>>b9e`3t*#eulEf-`1Ye$)#}g6* z!~iis3~UYq_6!j9%_*5GB?gFrA2NXZgM^0YTFeaUtph%IeMWx;5e0O7OCU;%uEoqC zctE&G1vIJLJ~6mS2fMU!uEortNoQQo4CC0D^T!LGO^d$y}fmH^|rt9GO ze-6J);Uj-Fg?hvQG4RhA;FZ4D??F-aY+Wl4&squX9vTY9WvGCFzH$kG4(=lj?KFOg aI>fmaGlMt^+I2c0T?8~C^dSa*fq^d|>rEg4 literal 0 HcmV?d00001 diff --git a/tests/ParsingTest.test.ts b/tests/ParsingTest.test.ts new file mode 100644 index 0000000..9f7de25 --- /dev/null +++ b/tests/ParsingTest.test.ts @@ -0,0 +1,14 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src' + +describe('Parsing Flows', () => { + let flow: core.Flow; + + it(' should have a result ', async () => { + const flows = await core.parse(['/Users/rubenhalman/Projects/lightning-flow-scanner-core/tests/xmlfiles/Unused_Variable_Fixed.flow-meta.xml']); + + expect(flows[0].name).to.equal("Unused_Variable_Fixed"); + }); + +}); diff --git a/tests/xmlfiles/Copy_API_Name.flow-meta.xml b/tests/xmlfiles/Copy_API_Name.flow-meta.xml new file mode 100644 index 0000000..943e9ee --- /dev/null +++ b/tests/xmlfiles/Copy_API_Name.flow-meta.xml @@ -0,0 +1,60 @@ + + + 51.0 + This flow demonstrates a violation of the rule "Copy API Name". + Default + Copy API Name {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + Copy_1_of_mockscreen + + 176 + 242 + true + true + true + true + true + + + mockscreen + + 176 + 134 + true + true + true + + Copy_1_of_mockscreen + + true + true + + + 50 + 0 + + mockscreen + + + Active + diff --git a/tests/xmlfiles/Copy_API_Name_Fixed.flow-meta.xml b/tests/xmlfiles/Copy_API_Name_Fixed.flow-meta.xml new file mode 100644 index 0000000..8cf2a06 --- /dev/null +++ b/tests/xmlfiles/Copy_API_Name_Fixed.flow-meta.xml @@ -0,0 +1,60 @@ + + + 51.0 + This flow demonstrates how to resolve a violation of the rule "Copy API Name". + Default + Fix: Copy API Name {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + mockscreen + + 176 + 134 + true + true + true + + second_mockscreen + + true + true + + + second_mockscreen + + 176 + 242 + true + true + true + true + true + + + 50 + 0 + + mockscreen + + + Active + diff --git a/tests/xmlfiles/DML_Statement_In_A_Loop.flow-meta.xml b/tests/xmlfiles/DML_Statement_In_A_Loop.flow-meta.xml new file mode 100644 index 0000000..097f99c --- /dev/null +++ b/tests/xmlfiles/DML_Statement_In_A_Loop.flow-meta.xml @@ -0,0 +1,105 @@ + + + + a Case failed to create automatically. Please examine its details manually. + create_case_manually + + 528 + 350 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + createCase.OwnerId + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + This flow demonstrates a violation of the rule "DML Statement In A Loop". + Default + DML Statements In A Loop {!$Flow.CurrentDateTime} + + + an example loop + aLoop + + 176 + 134 + Accounts + Asc + + createNewCase + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + creates a new case + createNewCase + + 264 + 242 + + aLoop + + + create_case_manually + + createCase + + + 50 + 0 + + aLoop + + + Active + + A collection of Accounts + Accounts + SObject + true + true + true + Account + + + createCase + SObject + false + false + false + Case + + + a task + task + SObject + false + false + false + Task + + diff --git a/tests/xmlfiles/DML_Statement_In_A_Loop_Fixed.flow-meta.xml b/tests/xmlfiles/DML_Statement_In_A_Loop_Fixed.flow-meta.xml new file mode 100644 index 0000000..7eb0d86 --- /dev/null +++ b/tests/xmlfiles/DML_Statement_In_A_Loop_Fixed.flow-meta.xml @@ -0,0 +1,143 @@ + + + + create_case_manually + + 440 + 542 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + aLoop.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + + Assigns values to newCase variable. + createNewCaseAssignment + + 264 + 242 + + newCase.AccountId + Assign + + aLoop.Id + + + + newCase.OwnerId + Assign + + aLoop.OwnerId + + + + newCases + Add + + newCase + + + + aLoop + + + This flow demonstrates how to resolve a violation of the rule "DML Statement In A Loop". + Default + DML Statement In A Loop Fixed {!$Flow.CurrentDateTime} + + + an example loop + aLoop + + 176 + 134 + Accounts + Asc + + createNewCaseAssignment + + + insert_cases + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + insert_cases + + 176 + 434 + + create_case_manually + + newCases + + + 50 + 0 + + aLoop + + + Active + + A collection of Accounts + Accounts + SObject + true + true + true + Account + + + newCase + SObject + false + false + false + Case + + + Collection of New Cases + newCases + SObject + true + false + false + Case + + + a task + task + SObject + false + false + false + Task + + diff --git a/tests/xmlfiles/Duplicate_DML_Operation.flow-meta.xml b/tests/xmlfiles/Duplicate_DML_Operation.flow-meta.xml new file mode 100644 index 0000000..2ce2539 --- /dev/null +++ b/tests/xmlfiles/Duplicate_DML_Operation.flow-meta.xml @@ -0,0 +1,112 @@ + + + + create_account_manually + + 440 + 350 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + This flow demonstrates a violation of the rule "Duplicate DML Operation". + Default + Duplicate DML Operation {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + createAccount + + 176 + 242 + + mock_screen_2 + + + create_account_manually + + + Name + + account_name + + + Account + true + + + mock_screen_1 + + 176 + 134 + true + true + true + + createAccount + + + account_name + String + account name + InputField + false + + true + true + + + mock_screen_2 + + 176 + 350 + true + true + true + true + true + + + 50 + 0 + + mock_screen_1 + + + Active + + Account + SObject + false + false + false + Account + + diff --git a/tests/xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml b/tests/xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml new file mode 100644 index 0000000..6abc715 --- /dev/null +++ b/tests/xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml @@ -0,0 +1,112 @@ + + + + create_account_manually + + 440 + 350 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + This flow demonstrates how to resolve a violation of the rule "Duplicate DML Operation". + Default + Duplicate DML Operation Fixed {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + createAccount + + 176 + 242 + + mock_screen_2 + + + create_account_manually + + + Name + + account_name + + + Account + true + + + mock_screen_1 + + 176 + 134 + true + true + true + + createAccount + + + account_name + String + account name + InputField + false + + true + true + + + mock_screen_2 + + 176 + 350 + false + true + true + true + true + + + 50 + 0 + + mock_screen_1 + + + Active + + Account + SObject + false + false + false + Account + + diff --git a/tests/xmlfiles/FlowNamingConvention.flow-meta.xml b/tests/xmlfiles/FlowNamingConvention.flow-meta.xml new file mode 100644 index 0000000..f9e588b --- /dev/null +++ b/tests/xmlfiles/FlowNamingConvention.flow-meta.xml @@ -0,0 +1,62 @@ + + + 58.0 + + isAccountsProvided + + 176 + 134 + Default Outcome + + NotNull + and + + Accounts + IsNull + + false + + + + + + This flow demonstrates a violation of the rule "Flow Naming Convention". + Default + Flow Naming Convention {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + isAccountsProvided + + + Active + + Accounts + SObject + true + true + false + Account + + diff --git a/tests/xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml b/tests/xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml new file mode 100644 index 0000000..68d7fa3 --- /dev/null +++ b/tests/xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml @@ -0,0 +1,62 @@ + + + 58.0 + + isAccountsProvided + + 176 + 134 + Default Outcome + + NotNull + and + + Accounts + IsNull + + false + + + + + + This flow demonstrates how to resolve a violation of the rule "Flow Naming Convention". + Default + Fix: Flow Naming Convention {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + isAccountsProvided + + + Active + + Accounts + SObject + true + true + false + Account + + diff --git a/tests/xmlfiles/Hardcoded_Id.flow-meta.xml b/tests/xmlfiles/Hardcoded_Id.flow-meta.xml new file mode 100644 index 0000000..c9eff64 --- /dev/null +++ b/tests/xmlfiles/Hardcoded_Id.flow-meta.xml @@ -0,0 +1,83 @@ + + + + create_account_manually + + 440 + 242 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + This flow demonstrates a violation of the rule "Hardcoded Id". + Default + Hardcoded Ids] {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + create_Test_Account + + 176 + 134 + + create_account_manually + + + Name + + Test Account + + + + OwnerId + + 005Dn000006GuG4IAK + + + Account + true + + + 50 + 0 + + create_Test_Account + + + Active + + Account + SObject + false + false + false + Account + + diff --git a/tests/xmlfiles/Hardcoded_Id_Fixed.flow-meta.xml b/tests/xmlfiles/Hardcoded_Id_Fixed.flow-meta.xml new file mode 100644 index 0000000..5b0f173 --- /dev/null +++ b/tests/xmlfiles/Hardcoded_Id_Fixed.flow-meta.xml @@ -0,0 +1,156 @@ + + + + create_account_manually + + 314 + 458 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + + create_task + + 842 + 242 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + + CheckIfUserIsFound + + 314 + 242 + Default Outcome + + userfound + and + + UserId.Id + IsNull + + false + + + + create_Test_Account + + + + + This flow demonstrates how to resolve a violation of the rule "Hardcoded Id". + Default + Fix: Hardcoded Id {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + create_Test_Account + + 50 + 350 + + create_account_manually + + + Name + + Test Account + + + + OwnerId + + UserId.Id + + + Account + true + + + getUserId + + 314 + 134 + false + + CheckIfUserIsFound + + + create_task + + and + + Name + EqualTo + + Acme + + + Account + + UserId.Id + OwnerId + + + + 188 + 0 + + getUserId + + + Active + + Account + SObject + false + false + false + Account + + + UserId + SObject + false + false + false + User + + diff --git a/tests/xmlfiles/Missing_Error_Handler.flow-meta.xml b/tests/xmlfiles/Missing_Error_Handler.flow-meta.xml new file mode 100644 index 0000000..b2f2d34 --- /dev/null +++ b/tests/xmlfiles/Missing_Error_Handler.flow-meta.xml @@ -0,0 +1,46 @@ + + + + log_call + + 176 + 134 + LogACall + quickAction + CurrentTransaction + LogACall + 1 + + 58.0 + This flow demonstrates a violation of the rule "Missing Error Handler". + Default + Missing Error Handler {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + log_call + + + Active + diff --git a/tests/xmlfiles/Missing_Error_Handler_Fixed.flow-meta.xml b/tests/xmlfiles/Missing_Error_Handler_Fixed.flow-meta.xml new file mode 100644 index 0000000..7bd40db --- /dev/null +++ b/tests/xmlfiles/Missing_Error_Handler_Fixed.flow-meta.xml @@ -0,0 +1,66 @@ + + + + dosomethingelse + + 440 + 242 + NewTask + quickAction + CurrentTransaction + + OwnerId + + $User.Id + + + NewTask + 1 + + + log_call + + 176 + 134 + LogACall + quickAction + + dosomethingelse + + CurrentTransaction + LogACall + 1 + + 58.0 + This flow demonstrates how to resolve a violation of the rule "Missing Error Handler". + Default + Fix: Missing Error Handler {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + log_call + + + Active + diff --git a/tests/xmlfiles/Missing_Flow_Description.flow-meta.xml b/tests/xmlfiles/Missing_Flow_Description.flow-meta.xml new file mode 100644 index 0000000..2ecc7e6 --- /dev/null +++ b/tests/xmlfiles/Missing_Flow_Description.flow-meta.xml @@ -0,0 +1,57 @@ + + + 58.0 + + do_Anything + + 176 + 134 + + text + Assign + + new text + + + + Default + Missing Flow Description {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + do_Anything + + + Active + + text + String + false + false + false + + any text + + + diff --git a/tests/xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml b/tests/xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml new file mode 100644 index 0000000..632a3c6 --- /dev/null +++ b/tests/xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml @@ -0,0 +1,58 @@ + + + 58.0 + + do_Anything + + 176 + 134 + + text + Assign + + new text + + + + This flow demonstrates how to resolve a violation of the rule "Missing Flow Description". + Default + Missing Flow Description Fixed {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 50 + 0 + + do_Anything + + + Active + + text + String + false + false + false + + any text + + + diff --git a/tests/xmlfiles/Missing_Null_Handler.flow-meta.xml b/tests/xmlfiles/Missing_Null_Handler.flow-meta.xml new file mode 100644 index 0000000..55d0399 --- /dev/null +++ b/tests/xmlfiles/Missing_Null_Handler.flow-meta.xml @@ -0,0 +1,89 @@ + + + + something_went_wrong + + 440 + 242 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + + Assign_New_Account_Name + + 176 + 242 + + GetAnAccount.Name + Assign + + Test + + + + This flow demonstrates a violation of the rule "Missing Null Handler". + Default + Missing Null Handlers {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + GetAnAccount + + 176 + 134 + false + + Assign_New_Account_Name + + + something_went_wrong + + and + + Name + EqualTo + + Acme + + + true + Account + true + + + 50 + 0 + + GetAnAccount + + + Active + diff --git a/tests/xmlfiles/Missing_Null_Handler_Fixed.flow-meta.xml b/tests/xmlfiles/Missing_Null_Handler_Fixed.flow-meta.xml new file mode 100644 index 0000000..6882dfc --- /dev/null +++ b/tests/xmlfiles/Missing_Null_Handler_Fixed.flow-meta.xml @@ -0,0 +1,138 @@ + + + + review_error + + 264 + 350 + FeedItem.NewTaskFromFeedItem + quickAction + + Assign_New_Account_Name + + + true + something_went_wrong + + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + + something_went_wrong + + 792 + 242 + FeedItem.NewTaskFromFeedItem + quickAction + CurrentTransaction + + contextId + + $User.Id + + + FeedItem.NewTaskFromFeedItem + 1 + + 58.0 + + Assign_New_Account_Name + + 176 + 590 + + GetAnAccount.Name + Assign + + Test + + + + + ifNotNull + + 176 + 242 + + review_error + + Default Outcome + + notNull + and + + GetAnAccount + IsNull + + false + + + + Assign_New_Account_Name + + + + + This flow demonstrates how to resolve a violation of the rule "Missing Null Handler". + Default + Fix: Missing null handlers {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + GetAnAccount + + 176 + 134 + false + + ifNotNull + + + something_went_wrong + + and + + Name + EqualTo + + Acme + + + true + Account + true + + + 50 + 0 + + GetAnAccount + + + Active + diff --git a/tests/xmlfiles/Outdated_API_Version.flow-meta.xml b/tests/xmlfiles/Outdated_API_Version.flow-meta.xml new file mode 100644 index 0000000..ad15a0b --- /dev/null +++ b/tests/xmlfiles/Outdated_API_Version.flow-meta.xml @@ -0,0 +1,45 @@ + + + This flow demonstrates a violation of the rule "Outdated API Version". + Default + Outdated API Version {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + mockscreen + + 176 + 134 + true + true + true + true + true + + + 50 + 0 + + mockscreen + + + Active + diff --git a/tests/xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml b/tests/xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml new file mode 100644 index 0000000..796795a --- /dev/null +++ b/tests/xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml @@ -0,0 +1,46 @@ + + + 58.0 + This flow demonstrates how to resolve a violation of the rule "Outdated API Version". + Default + Outdated API Version Fixed {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + mockscreen + + 176 + 134 + true + true + true + true + true + + + 50 + 0 + + mockscreen + + + Active + diff --git a/tests/xmlfiles/SOQL_Query_In_A_Loop.flow-meta.xml b/tests/xmlfiles/SOQL_Query_In_A_Loop.flow-meta.xml new file mode 100644 index 0000000..a69ae55 --- /dev/null +++ b/tests/xmlfiles/SOQL_Query_In_A_Loop.flow-meta.xml @@ -0,0 +1,117 @@ + + + + dosomethingelse + + 704 + 350 + NewCase + quickAction + CurrentTransaction + NewCase + 1 + + 58.0 + + notnull + + 352 + 350 + + true + dosomethingelse + + Default Outcome + + notnulln + and + + SOQL_Query_Example + IsNull + + false + + + + aLoop + + + + + This flow demonstrates a violation of the rule "SOQL Query In A Loop". + Default + SOQL Query In A Loop {!$Flow.CurrentDateTime} + + + an example loop + aLoop + + 176 + 134 + Accounts + Asc + + SOQL_Query_Example + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + SOQL_Query_Example + + 352 + 242 + false + + notnull + + + dosomethingelse + + and + + Industry + EqualTo + + None + + + true + Account + true + + + 50 + 0 + + aLoop + + + Active + + A collection of Accounts + Accounts + SObject + true + true + true + Account + + diff --git a/tests/xmlfiles/SOQL_Query_In_A_Loop_Fixed.flow-meta.xml b/tests/xmlfiles/SOQL_Query_In_A_Loop_Fixed.flow-meta.xml new file mode 100644 index 0000000..9f089db --- /dev/null +++ b/tests/xmlfiles/SOQL_Query_In_A_Loop_Fixed.flow-meta.xml @@ -0,0 +1,110 @@ + + + + dosomethingelse + + 440 + 434 + NewCase + quickAction + CurrentTransaction + NewCase + 1 + + 58.0 + + notnull + + 176 + 434 + Default Outcome + + notnulln + and + + SOQL_Query_Example + IsNull + + false + + + + + + This flow demonstrates how to resolve a violation of the rule "SOQL Query In A Loop". + Default + Fix: SOQL Query In A Loop {!$Flow.CurrentDateTime} + + + an example loop + aLoop + + 176 + 134 + Accounts + Asc + + SOQL_Query_Example + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + SOQL_Query_Example + + 176 + 326 + false + + notnull + + + dosomethingelse + + and + + Industry + EqualTo + + None + + + true + Account + true + + + 50 + 0 + + aLoop + + + Active + + A collection of Accounts + Accounts + SObject + true + true + true + Account + + diff --git a/tests/xmlfiles/Unconnected_Element.flow-meta.xml b/tests/xmlfiles/Unconnected_Element.flow-meta.xml new file mode 100644 index 0000000..be3963b --- /dev/null +++ b/tests/xmlfiles/Unconnected_Element.flow-meta.xml @@ -0,0 +1,73 @@ + + + 58.0 + + example assignment + getCurrentTime + + 656 + 182 + + currentTime + Assign + + $Flow.CurrentDateTime + + + + + example assignment (unused) + unused_assignment + + 835 + 177 + + currentTime + Assign + + $Flow.InterviewStartTime + + + + This flow demonstrates a violation of the rule "Unconnected Element". + Default + Unconnected Element {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + FREE_FORM_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 530 + 48 + + getCurrentTime + + + Active + + currentTime + DateTime + false + false + false + + $Flow.CurrentDateTime + + + diff --git a/tests/xmlfiles/Unconnected_Element_Fixed.flow-meta.xml b/tests/xmlfiles/Unconnected_Element_Fixed.flow-meta.xml new file mode 100644 index 0000000..19fe757 --- /dev/null +++ b/tests/xmlfiles/Unconnected_Element_Fixed.flow-meta.xml @@ -0,0 +1,59 @@ + + + 58.0 + + example assignment + getCurrentTime + + 656 + 182 + + currentTime + Assign + + $Flow.CurrentDateTime + + + + This flow demonstrates how to resolve a violation of the rule "Unconnected Element". + Default + Unconnected Element Fixed {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + FREE_FORM_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + 530 + 48 + + getCurrentTime + + + Active + + currentTime + DateTime + false + false + false + + $Flow.CurrentDateTime + + + diff --git a/yarn.lock b/yarn.lock index 79c6d54..964ddae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,2059 +1,1035 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@babel/code-frame@npm:^7.0.0": - version: 7.14.5 - resolution: "@babel/code-frame@npm:7.14.5" - dependencies: - "@babel/highlight": "npm:^7.14.5" - checksum: 10c0/6dd398ce8d7981f78236c1d02878b32f9d4ab953bcc6bae3fa472370f61c4f45a2db188ea5560e3615d8bdd44c1c69bb3c21997a19d57607183f864e73539946 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/helper-validator-identifier@npm:7.14.5" - checksum: 10c0/b80e89eb3609f2b6fb8f7baaf988a1840d317e84e479c64d5e903eb9cf3d4fd1ee7f98bbaa8b0402cbc34cc2ec443fbdbce7022e07db26ed3a81ab542b552f3f - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/highlight@npm:7.14.5" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.14.5" - chalk: "npm:^2.0.0" - js-tokens: "npm:^4.0.0" - checksum: 10c0/b9d16895e4bf780d69504c7cc8a9871dc668bcd1851c4a7a7f039f34ba5bb1f04efc4ad6b79112496c7896d541a4d38efa02e7d8be8fb0a1f352097cff8ba79d - languageName: node - linkType: hard - -"@cspotcode/source-map-consumer@npm:0.8.0": - version: 0.8.0 - resolution: "@cspotcode/source-map-consumer@npm:0.8.0" - checksum: 10c0/44428e50f896df065c3a22d6bddeac344f3e31af57cbc2ddf753a95addcabbe685d92e534f4dcde0cabbbcfbc122d1cb957785b36344d54c422b781a8d1a2a01 - languageName: node - linkType: hard - -"@cspotcode/source-map-support@npm:0.6.1": - version: 0.6.1 - resolution: "@cspotcode/source-map-support@npm:0.6.1" - dependencies: - "@cspotcode/source-map-consumer": "npm:0.8.0" - checksum: 10c0/f5432af7de60ed490a3222e1ff97ef351084e65d71aa4eb40677cf055ed38cd4b28fb465e33efd8ad60518c2bb3779f9539886b1f303cd1fc5e91c0de5b1f2e6 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@npmcli/agent@npm:^2.0.0": - version: 2.2.1 - resolution: "@npmcli/agent@npm:2.2.1" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.1" - checksum: 10c0/38ee5cbe8f3cde13be916e717bfc54fd1a7605c07af056369ff894e244c221e0b56b08ca5213457477f9bc15bca9e729d51a4788829b5c3cf296b3c996147f76 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@tsconfig/node10@npm:^1.0.7": - version: 1.0.8 - resolution: "@tsconfig/node10@npm:1.0.8" - checksum: 10c0/d400f7b5c02acd74620f892c0f41cea39e7c1b5f7f272ad6f127f4b1fba23346b2d8e30d272731a733675494145f6aa74f9faf050390c034c7c553123ab979b3 - languageName: node - linkType: hard - -"@tsconfig/node12@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node12@npm:1.0.9" - checksum: 10c0/fc1fb68a89d8a641953036d23d95fe68f69f74d37a499db20791b09543ad23afe7ae9ee0840eea92dd470bdcba69eef6f1ed3fe90ba64d763bcd3f738e364597 - languageName: node - linkType: hard - -"@tsconfig/node14@npm:^1.0.0": - version: 1.0.1 - resolution: "@tsconfig/node14@npm:1.0.1" - checksum: 10c0/abd4e27d9ad712e1e229716a3dbf35d5cbb580d624a82d67414e7606cefd85d502e58800a2ab930d46a428fcfcb199436283b1a88e47d738ca1a5f7fd022ee74 - languageName: node - linkType: hard - -"@tsconfig/node16@npm:^1.0.2": - version: 1.0.2 - resolution: "@tsconfig/node16@npm:1.0.2" - checksum: 10c0/d402706562444a173d48810d13fdf866c78f1b876ed8962eeac6c7cddf4e29e8aaa06dc28093219e3e9eb6316799cf4d9a7acba62c6a4e215ee0c94d83f9081f - languageName: node - linkType: hard - -"@types/chai@npm:^4.2.21": - version: 4.2.21 - resolution: "@types/chai@npm:4.2.21" - checksum: 10c0/254cd6e15afcb3640083c4dbe93fc127ff8d4cafb0214c2538996a24fd2c77181a34c27ea0603f8e2229de8d567d888d353e760a9b3e90a3c3842c945d917e3d - languageName: node - linkType: hard - -"@types/mocha@npm:^9.0.0": - version: 9.0.0 - resolution: "@types/mocha@npm:9.0.0" - checksum: 10c0/82501aa1453ffe204d94f0a975e2ff266bfe38fb66a788a6c1fd72db3b7707534fb28f60b99eee128b22df7efa2b3064c57e749ec5f142d294854bb43f3da82d - languageName: node - linkType: hard - -"@types/node@npm:^20.4.5": - version: 20.4.5 - resolution: "@types/node@npm:20.4.5" - checksum: 10c0/ed414b8fea1b462cb7444464e18cf0786a11def8b863bcca52b0466992d04f701422f9fc3c33e0601444bfdbf9e18d8f4b163d35902758495b51e635b09fee64 - languageName: node - linkType: hard - -"@types/path-browserify@npm:^1": - version: 1.0.2 - resolution: "@types/path-browserify@npm:1.0.2" - checksum: 10c0/4140970d1d171760a63e2be7ae050e12b7035e99205d190f12b039c0afb5dc975352a913a7fde0997e38e74102f3496c73f49128c126492ca5d1498a0f1a5206 - languageName: node - linkType: hard - -"@ungap/promise-all-settled@npm:1.1.2": - version: 1.1.2 - resolution: "@ungap/promise-all-settled@npm:1.1.2" - checksum: 10c0/7f9862bae3b6ce30675783428933be1738dca278901a6bcb55c29b8f54c08863ec8e6a7c884119877d90336501c33b7cfda36355ec7af4d703f65f54cb768913 - languageName: node - linkType: hard - -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 - languageName: node - linkType: hard - -"acorn-walk@npm:^8.1.1": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 10c0/dbe92f5b2452c93e960c5594e666dd1fae141b965ff2cb4a1e1d0381e3e4db4274c5ce4ffa3d681a86ca2a8d4e29d5efc0670a08e23fd2800051ea387df56ca2 - languageName: node - linkType: hard - -"acorn@npm:^8.4.1": - version: 8.5.0 - resolution: "acorn@npm:8.5.0" - bin: - acorn: bin/acorn - checksum: 10c0/a0cd0009d215df0c5a6c69ea40a5e784114f1b89d5649d663264ccbb855d4c6b6da6936fed607078b7d681bd8d8f2e730dad25931edbdef709bc4b520c0caa80 - languageName: node - linkType: hard - -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": - version: 7.1.0 - resolution: "agent-base@npm:7.1.0" - dependencies: - debug: "npm:^4.3.4" - checksum: 10c0/fc974ab57ffdd8421a2bc339644d312a9cca320c20c3393c9d8b1fd91731b9bbabdb985df5fc860f5b79d81c3e350daa3fcb31c5c07c0bb385aafc817df004ce - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 - languageName: node - linkType: hard - -"ansi-colors@npm:4.1.1": - version: 4.1.1 - resolution: "ansi-colors@npm:4.1.1" - checksum: 10c0/6086ade4336b4250b6b25e144b83e5623bcaf654d3df0c3546ce09c9c5ff999cb6a6f00c87e802d05cf98aef79d92dc76ade2670a2493b8dcb80220bec457838 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 - languageName: node - linkType: hard - -"ansi-styles@npm:^2.2.1": - version: 2.2.1 - resolution: "ansi-styles@npm:2.2.1" - checksum: 10c0/7c68aed4f1857389e7a12f85537ea5b40d832656babbf511cc7ecd9efc52889b9c3e5653a71a6aade783c3c5e0aa223ad4ff8e83c27ac8a666514e6c79068cab - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: "npm:^1.9.0" - checksum: 10c0/ece5a8ef069fcc5298f67e3f4771a663129abd174ea2dfa87923a2be2abf6cd367ef72ac87942da00ce85bd1d651d4cd8595aebdb1b385889b89b205860e977b - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac - languageName: node - linkType: hard - -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 10c0/070ff801a9d236a6caa647507bdcc7034530604844d64408149a26b9e87c2f97650055c0f049abd1efc024b334635c01f29e0b632b371ac3f26130f4cf65997a - languageName: node - linkType: hard - -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: "npm:~1.0.2" - checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de - languageName: node - linkType: hard - -"argparse@npm:^2.0.1": - version: 2.0.1 - resolution: "argparse@npm:2.0.1" - checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e - languageName: node - linkType: hard - -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: 10c0/d73d8b897238a2d3ffa5f59c0241870043aa7471335e89ea5e1ff48edb7c2d0bb471517a3e4c5c3f4c043615caa2717b5f80a5e61e07503d51dc85cb848e665d - languageName: node - linkType: hard - -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: "npm:^1.0.0" - concat-map: "npm:0.0.1" - checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" - dependencies: - fill-range: "npm:^7.0.1" - checksum: 10c0/321b4d675791479293264019156ca322163f02dc06e3c4cab33bb15cd43d80b51efef69b0930cfde3acd63d126ebca24cd0544fa6f261e093a0fb41ab9dda381 - languageName: node - linkType: hard - -"browser-stdout@npm:1.3.1": - version: 1.3.1 - resolution: "browser-stdout@npm:1.3.1" - checksum: 10c0/c40e482fd82be872b6ea7b9f7591beafbf6f5ba522fe3dade98ba1573a1c29a11101564993e4eb44e5488be8f44510af072df9a9637c739217eb155ceb639205 - languageName: node - linkType: hard - -"builtin-modules@npm:^1.1.1": - version: 1.1.1 - resolution: "builtin-modules@npm:1.1.1" - checksum: 10c0/58d72ea7f59db3c2ae854e1058d85b226f75ff7386d0f71d628e25a600383fc6652af218e20ba2361925c605a4144590ceb890dfdca298fdf8f3d040c0591a23 - languageName: node - linkType: hard - -"cacache@npm:^18.0.0": - version: 18.0.2 - resolution: "cacache@npm:18.0.2" - dependencies: - "@npmcli/fs": "npm:^3.1.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10c0/7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc - languageName: node - linkType: hard - -"camelcase@npm:^6.0.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 - languageName: node - linkType: hard - -"chai@npm:^4.3.4": - version: 4.3.4 - resolution: "chai@npm:4.3.4" - dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.2" - deep-eql: "npm:^3.0.1" - get-func-name: "npm:^2.0.0" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.0.5" - checksum: 10c0/e8be63a3ce412cc35f0209799c96b1f67397c4829489bd1604f9639f291b697f9a8c1ee129f5d502663332691950b278d2be7e8f19d753b86ea1876e99771a8e - languageName: node - linkType: hard - -"chalk@npm:^2.0.0, chalk@npm:^2.3.0": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: "npm:^3.2.1" - escape-string-regexp: "npm:^1.0.5" - supports-color: "npm:^5.3.0" - checksum: 10c0/e6543f02ec877732e3a2d1c3c3323ddb4d39fbab687c23f526e25bd4c6a9bf3b83a696e8c769d078e04e5754921648f7821b2a2acfd16c550435fd630026e073 - languageName: node - linkType: hard - -"chalk@npm:^4.1.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - -"check-error@npm:^1.0.2": - version: 1.0.2 - resolution: "check-error@npm:1.0.2" - checksum: 10c0/c58ac4d6a92203209a61d025568198c073f101691eb6247f999266e1d1e3ab3af2bbe0a41af5008c1f1b95446ec7831e6ba91f03816177f2da852f316ad7921d - languageName: node - linkType: hard - -"chokidar@npm:3.5.3": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" - dependencies: - anymatch: "npm:~3.1.2" - braces: "npm:~3.0.2" - fsevents: "npm:~2.3.2" - glob-parent: "npm:~5.1.2" - is-binary-path: "npm:~2.1.0" - is-glob: "npm:~4.0.1" - normalize-path: "npm:~3.0.0" - readdirp: "npm:~3.6.0" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1 - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 - languageName: node - linkType: hard - -"cliui@npm:^7.0.2": - version: 7.0.4 - resolution: "cliui@npm:7.0.4" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.0" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/6035f5daf7383470cef82b3d3db00bec70afb3423538c50394386ffbbab135e26c3689c41791f911fa71b62d13d3863c712fdd70f0fbdffd938a1e6fd09aac00 - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: "npm:1.1.3" - checksum: 10c0/5ad3c534949a8c68fca8fbc6f09068f435f0ad290ab8b2f76841b9e6af7e0bb57b98cb05b0e19fe33f5d91e5a8611ad457e5f69e0a484caad1f7487fd0e8253c - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 10c0/566a3d42cca25b9b3cd5528cd7754b8e89c0eb646b7f214e8e2eaddb69994ac5f0557d9c175eb5d8f0ad73531140d9c47525085ee752a91a2ab15ab459caf6d6 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"commander@npm:^2.12.1": - version: 2.20.3 - resolution: "commander@npm:2.20.3" - checksum: 10c0/74c781a5248c2402a0a3e966a0a2bba3c054aad144f5c023364be83265e796b20565aa9feff624132ff629aa64e16999fa40a743c10c12f7c61e96a794b99288 - languageName: node - linkType: hard - -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f - languageName: node - linkType: hard - -"create-require@npm:^1.1.0": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 - languageName: node - linkType: hard - -"debug@npm:4.3.3": - version: 4.3.3 - resolution: "debug@npm:4.3.3" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/31873df69ff7036ce4f4158dcd6f71cd399b834ab1efbf23383f660822d28c7e29442fa83d34ccdd2f5201ff69eb494f0c7e8c01ecd314f0207bb631bb048ac0 - languageName: node - linkType: hard - -"debug@npm:^4.3.1": - version: 4.3.2 - resolution: "debug@npm:4.3.2" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/3cc408070bcee066ee9b2a4f3a9c40f53728919ec7c7ff568f7c3a75b0723cb5a8407191a63495be4e10669e99b0ff7f26ec70e10b025da1898cdce4876d96ca - languageName: node - linkType: hard - -"decamelize@npm:^4.0.0": - version: 4.0.0 - resolution: "decamelize@npm:4.0.0" - checksum: 10c0/e06da03fc05333e8cd2778c1487da67ffbea5b84e03ca80449519b8fa61f888714bbc6f459ea963d5641b4aa98832130eb5cd193d90ae9f0a27eee14be8e278d - languageName: node - linkType: hard - -"deep-eql@npm:^3.0.1": - version: 3.0.1 - resolution: "deep-eql@npm:3.0.1" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 10c0/80b33c1c7713b3d5db89e6b5e9b22050f39c8a88e12a015616da8391e013988790d045a5c612b0c6dc43cc4bec51eadbe0fcf6075cc9717f8f56efdb305b6e6f - languageName: node - linkType: hard - -"diff@npm:5.0.0": - version: 5.0.0 - resolution: "diff@npm:5.0.0" - checksum: 10c0/08c5904779bbababcd31f1707657b1ad57f8a9b65e6f88d3fb501d09a965d5f8d73066898a7d3f35981f9e4101892c61d99175d421f3b759533213c253d91134 - languageName: node - linkType: hard - -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: 10c0/81b91f9d39c4eaca068eb0c1eb0e4afbdc5bb2941d197f513dd596b820b956fef43485876226d65d497bebc15666aa2aa82c679e84f65d5f2bfbf14ee46e32c1 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: 10c0/afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d - languageName: node - linkType: hard - -"escape-string-regexp@npm:4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371 - languageName: node - linkType: hard - -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 - languageName: node - linkType: hard - -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" - dependencies: - to-regex-range: "npm:^5.0.1" - checksum: 10c0/7cdad7d426ffbaadf45aeb5d15ec675bbd77f7597ad5399e3d2766987ed20bda24d5fac64b3ee79d93276f5865608bb22344a26b9b1ae6c4d00bd94bf611623f - languageName: node - linkType: hard - -"find-up@npm:5.0.0": - version: 5.0.0 - resolution: "find-up@npm:5.0.0" - dependencies: - locate-path: "npm:^6.0.0" - path-exists: "npm:^4.0.0" - checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a - languageName: node - linkType: hard - -"flat@npm:^5.0.2": - version: 5.0.2 - resolution: "flat@npm:5.0.2" - bin: - flat: cli.js - checksum: 10c0/f178b13482f0cd80c7fede05f4d10585b1f2fdebf26e12edc138e32d3150c6ea6482b7f12813a1091143bad52bb6d3596bca51a162257a21163c0ff438baa5fe - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" - dependencies: - cross-spawn: "npm:^7.0.0" - signal-exit: "npm:^4.0.1" - checksum: 10c0/9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: 10c0/60b74b2407e1942e1ed7f8c284f8ef714d0689dcfce5319985a5b7da3fc727f40b4a59ec72dc55aa83365ad7b8fa4fac3a30d93c850a2b452f29ae03dbc10a1e - languageName: node - linkType: hard - -"get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"get-func-name@npm:^2.0.0": - version: 2.0.0 - resolution: "get-func-name@npm:2.0.0" - checksum: 10c0/ed8791f7ba92cfd747259dff7ec8b6cc42734cebd031fb58c99a6e71d24d3532d84b46ad7806cafad6ad21784dd04ae1808a002d2b21001425e21f5f394c34e7 - languageName: node - linkType: hard - -"glob-parent@npm:~5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: "npm:^4.0.1" - checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee - languageName: node - linkType: hard - -"glob@npm:7.2.0": - version: 7.2.0 - resolution: "glob@npm:7.2.0" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.0.4" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/478b40e38be5a3d514e64950e1e07e0ac120585add6a37c98d0ed24d72d9127d734d2a125786073c8deb687096e84ae82b641c441a869ada3a9cc91b68978632 - languageName: node - linkType: hard - -"glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d - languageName: node - linkType: hard - -"glob@npm:^7.1.1": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.0.4" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/173245e6f9ccf904309eb7ef4a44a11f3bf68e9e341dff5a28b5db0dd7123b7506daf41497f3437a0710f57198187b758c2351eeaabce4d16935e956920da6a4 - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"growl@npm:1.10.5": - version: 1.10.5 - resolution: "growl@npm:1.10.5" - checksum: 10c0/a6a8f4df1269ac321f9e41c310552f3568768160942b6c9a7c116fcff1e3921f6a48fb7520689660412f7d1e5d46f76214e05406b23eee9e213830fdc2f772fe - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 10c0/1c6c83b14b8b1b3c25b0727b8ba3e3b647f99e9e6e13eb7322107261de07a4c1be56fc0d45678fc376e09772a3a1642ccdaf8fc69bdf123b6c086598397ce473 - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 - languageName: node - linkType: hard - -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: "npm:^1.1.1" - checksum: 10c0/e1da0d2bd109f116b632f27782cf23182b42f14972ca9540e4c5aa7e52647407a0a4a76937334fddcb56befe94a3494825ec22b19b51f5e5507c3153fd1a5e1b - languageName: node - linkType: hard - -"he@npm:1.2.0": - version: 1.2.0 - resolution: "he@npm:1.2.0" - bin: - he: bin/he - checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" - dependencies: - agent-base: "npm:^7.0.2" - debug: "npm:4" - checksum: 10c0/bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: "npm:^2.0.0" - checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 - languageName: node - linkType: hard - -"is-core-module@npm:^2.2.0": - version: 2.4.0 - resolution: "is-core-module@npm:2.4.0" - dependencies: - has: "npm:^1.0.3" - checksum: 10c0/7df2fceca99f8b711e386a86217f6d9d21aac31d86ae2461225ff8b6b148e2a7a444cb64635fe702e56e7f75eb43e4f0b16d83595c28a131664da093fbfa4de7 - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: "npm:^2.1.1" - checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a - languageName: node - linkType: hard - -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 - languageName: node - linkType: hard - -"is-plain-obj@npm:^2.1.0": - version: 2.1.0 - resolution: "is-plain-obj@npm:2.1.0" - checksum: 10c0/e5c9814cdaa627a9ad0a0964ded0e0491bfd9ace405c49a5d63c88b30a162f1512c069d5b80997893c4d0181eadc3fed02b4ab4b81059aba5620bfcdfdeb9c53 - languageName: node - linkType: hard - -"is-unicode-supported@npm:^0.1.0": - version: 0.1.0 - resolution: "is-unicode-supported@npm:0.1.0" - checksum: 10c0/00cbe3455c3756be68d2542c416cab888aebd5012781d6819749fefb15162ff23e38501fe681b3d751c73e8ff561ac09a5293eba6f58fdf0178462ce6dcb3453 - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^2.3.5": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 - languageName: node - linkType: hard - -"js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed - languageName: node - linkType: hard - -"js-yaml@npm:4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: "npm:^2.0.1" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f - languageName: node - linkType: hard - -"js-yaml@npm:^3.13.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"lightning-flow-scanner-core@workspace:.": - version: 0.0.0-use.local - resolution: "lightning-flow-scanner-core@workspace:." - dependencies: - "@types/chai": "npm:^4.2.21" - "@types/mocha": "npm:^9.0.0" - "@types/node": "npm:^20.4.5" - "@types/path-browserify": "npm:^1" - chai: "npm:^4.3.4" - logging: "npm:^3.3.0" - mocha: "npm:^9.1.1" - path-browserify: "npm:^1.0.1" - ts-node: "npm:^10.2.1" - tslint: "npm:^6.1.3" - typescript: "npm:^4.3.4" - languageName: unknown - linkType: soft - -"locate-path@npm:^6.0.0": - version: 6.0.0 - resolution: "locate-path@npm:6.0.0" - dependencies: - p-locate: "npm:^5.0.0" - checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 - languageName: node - linkType: hard - -"log-symbols@npm:4.1.0": - version: 4.1.0 - resolution: "log-symbols@npm:4.1.0" - dependencies: - chalk: "npm:^4.1.0" - is-unicode-supported: "npm:^0.1.0" - checksum: 10c0/67f445a9ffa76db1989d0fa98586e5bc2fd5247260dafb8ad93d9f0ccd5896d53fb830b0e54dade5ad838b9de2006c826831a3c528913093af20dff8bd24aca6 - languageName: node - linkType: hard - -"logging@npm:^3.3.0": - version: 3.3.0 - resolution: "logging@npm:3.3.0" - dependencies: - chalk: "npm:^4.1.0" - debug: "npm:^4.3.1" - nicely-format: "npm:^1.1.0" - checksum: 10c0/a8c50f32c008c7cb76eb82c1217735d503f186d2725c3155fc2660f0ed0707f6ec660dd4c834eba14ea542c11809793ce327b034b944a911380a2ffd2fbffc9c - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.2.0 - resolution: "lru-cache@npm:10.2.0" - checksum: 10c0/c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 - languageName: node - linkType: hard - -"make-error@npm:^1.1.1": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: 10c0/171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f - languageName: node - linkType: hard - -"make-fetch-happen@npm:^13.0.0": - version: 13.0.0 - resolution: "make-fetch-happen@npm:13.0.0" - dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" - http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10c0/43b9f6dcbc6fe8b8604cb6396957c3698857a15ba4dbc38284f7f0e61f248300585ef1eb8cc62df54e9c724af977e45b5cdfd88320ef7f53e45070ed3488da55 - languageName: node - linkType: hard - -"minimatch@npm:4.2.1": - version: 4.2.1 - resolution: "minimatch@npm:4.2.1" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/a2381bc5fc4f4290b6659b01ba0e492d369fbf890c8eef828a9b17bbaa46bb0853db0709e436abfbe6e45620cbe191e9f9bc1dcf86d19de491b68e37c079a51c - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac - languageName: node - linkType: hard - -"minimist@npm:^1.2.5": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 10c0/6c7370a6dfd257bf18222da581ba89a5eaedca10e158781232a8b5542a90547540b4b9b7e7f490e4cda43acfbd12e086f0453728ecf8c19e0ef6921bc5958ac5 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 - languageName: node - linkType: hard - -"mkdirp@npm:^0.5.3": - version: 0.5.5 - resolution: "mkdirp@npm:0.5.5" - dependencies: - minimist: "npm:^1.2.5" - bin: - mkdirp: bin/cmd.js - checksum: 10c0/4469faeeba703bc46b7cdbe3097d6373747a581eb8b556ce41c8fd25a826eb3254466c6522ba823c2edb0b6f0da7beb91cf71f040bc4e361534a3e67f0994bd0 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf - languageName: node - linkType: hard - -"mocha@npm:^9.1.1": - version: 9.2.2 - resolution: "mocha@npm:9.2.2" - dependencies: - "@ungap/promise-all-settled": "npm:1.1.2" - ansi-colors: "npm:4.1.1" - browser-stdout: "npm:1.3.1" - chokidar: "npm:3.5.3" - debug: "npm:4.3.3" - diff: "npm:5.0.0" - escape-string-regexp: "npm:4.0.0" - find-up: "npm:5.0.0" - glob: "npm:7.2.0" - growl: "npm:1.10.5" - he: "npm:1.2.0" - js-yaml: "npm:4.1.0" - log-symbols: "npm:4.1.0" - minimatch: "npm:4.2.1" - ms: "npm:2.1.3" - nanoid: "npm:3.3.1" - serialize-javascript: "npm:6.0.0" - strip-json-comments: "npm:3.1.1" - supports-color: "npm:8.1.1" - which: "npm:2.0.2" - workerpool: "npm:6.2.0" - yargs: "npm:16.2.0" - yargs-parser: "npm:20.2.4" - yargs-unparser: "npm:2.0.0" - bin: - _mocha: bin/_mocha - mocha: bin/mocha - checksum: 10c0/eabc92c7d8fd5fe4a70b52bc88b902f8f640728e0985fabc5b25ca22f1f97b7b791c904150c4518003f705310d7f739392e9fdc53162a69372e6620511210e79 - languageName: node - linkType: hard - -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc - languageName: node - linkType: hard - -"ms@npm:2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"nanoid@npm:3.3.1": - version: 3.3.1 - resolution: "nanoid@npm:3.3.1" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/1034d71e438490e620bfc2419bb203e7dccbc122fd2e62a6101227b50d08992fdc114de197e77604c419dbcf4f41b142e6ff61d0516db4d24cd32f9bbc390f6b - languageName: node - linkType: hard - -"negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 - languageName: node - linkType: hard - -"nicely-format@npm:^1.1.0": - version: 1.1.0 - resolution: "nicely-format@npm:1.1.0" - dependencies: - ansi-styles: "npm:^2.2.1" - esutils: "npm:^2.0.2" - checksum: 10c0/fcf46a472af60d894be98083b1ec28e647295ba48a7ea1c566e713f1adf2c1994e2c3440f9d89c1242fa256c553d2fa2ce6cf1d6966a6610e0ef9ef4e93f4340 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 10.0.1 - resolution: "node-gyp@npm:10.0.1" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^3.0.0" - semver: "npm:^7.3.5" - tar: "npm:^6.1.2" - which: "npm:^4.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/abddfff7d873312e4ed4a5fb75ce893a5c4fb69e7fcb1dfa71c28a6b92a7f1ef6b62790dffb39181b5a82728ba8f2f32d229cf8cbe66769fe02cea7db4a555aa - languageName: node - linkType: hard - -"nopt@npm:^7.0.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" - dependencies: - abbrev: "npm:^2.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff - languageName: node - linkType: hard - -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 - languageName: node - linkType: hard - -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: "npm:^0.1.0" - checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a - languageName: node - linkType: hard - -"p-locate@npm:^5.0.0": - version: 5.0.0 - resolution: "p-locate@npm:5.0.0" - dependencies: - p-limit: "npm:^3.0.2" - checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a - languageName: node - linkType: hard - -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 - languageName: node - linkType: hard - -"path-browserify@npm:^1.0.1": - version: 1.0.1 - resolution: "path-browserify@npm:1.0.1" - checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 - languageName: node - linkType: hard - -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b - languageName: node - linkType: hard - -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.6": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" - dependencies: - lru-cache: "npm:^9.1.1 || ^10.0.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/e5dc78a7348d25eec61ab166317e9e9c7b46818aa2c2b9006c507a6ff48c672d011292d9662527213e558f5652ce0afcc788663a061d8b59ab495681840c0c1e - languageName: node - linkType: hard - -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be - languageName: node - linkType: hard - -"proc-log@npm:^3.0.0": - version: 3.0.0 - resolution: "proc-log@npm:3.0.0" - checksum: 10c0/f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"randombytes@npm:^2.1.0": - version: 2.1.0 - resolution: "randombytes@npm:2.1.0" - dependencies: - safe-buffer: "npm:^5.1.0" - checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 - languageName: node - linkType: hard - -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: "npm:^2.2.1" - checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b - languageName: node - linkType: hard - -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"resolve@npm:^1.3.2": - version: 1.20.0 - resolution: "resolve@npm:1.20.0" - dependencies: - is-core-module: "npm:^2.2.0" - path-parse: "npm:^1.0.6" - checksum: 10c0/d2c99e3bfbfd1f5aa4d134fa893b0157b923d6bfdc36563cb126995982ebfd0d93d901f851e4577897580f7c87d9a62d307b811422009fd3d2a8ed0571c2eabb - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.3.2#optional!builtin": - version: 1.20.0 - resolution: "resolve@patch:resolve@npm%3A1.20.0#optional!builtin::version=1.20.0&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.2.0" - path-parse: "npm:^1.0.6" - checksum: 10c0/b6a5345d1f015cebba11dffa6a1982b39fe9ef42ed86ed832e51bd01c10817666df6d7b11579bc88664f5d57f2a5fe073a7f46b4e72a3efe7ed0cb450ee786da - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"safe-buffer@npm:^5.1.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^5.3.0": - version: 5.7.2 - resolution: "semver@npm:5.7.2" - bin: - semver: bin/semver - checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 - languageName: node - linkType: hard - -"semver@npm:^7.3.5": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: "npm:^6.0.0" - bin: - semver: bin/semver.js - checksum: 10c0/fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 - languageName: node - linkType: hard - -"serialize-javascript@npm:6.0.0": - version: 6.0.0 - resolution: "serialize-javascript@npm:6.0.0" - dependencies: - randombytes: "npm:^2.1.0" - checksum: 10c0/73104922ef0a919064346eea21caab99de1a019a1f5fb54a7daa7fcabc39e83b387a2a363e52a889598c3b1bcf507c4b2a7b26df76e991a310657af20eea2e7c - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.1": - version: 8.0.2 - resolution: "socks-proxy-agent@npm:8.0.2" - dependencies: - agent-base: "npm:^7.0.2" - debug: "npm:^4.3.4" - socks: "npm:^2.7.1" - checksum: 10c0/a842402fc9b8848a31367f2811ca3cd14c4106588b39a0901cd7a69029998adfc6456b0203617c18ed090542ad0c24ee4e9d4c75a0c4b75071e214227c177eb7 - languageName: node - linkType: hard - -"socks@npm:^2.7.1": - version: 2.8.1 - resolution: "socks@npm:2.8.1" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb - languageName: node - linkType: hard - -"ssri@npm:^10.0.0": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"strip-json-comments@npm:3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd - languageName: node - linkType: hard - -"supports-color@npm:8.1.1": - version: 8.1.1 - resolution: "supports-color@npm:8.1.1" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89 - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: "npm:^3.0.0" - checksum: 10c0/6ae5ff319bfbb021f8a86da8ea1f8db52fac8bd4d499492e30ec17095b58af11f0c55f8577390a749b1c4dde691b6a0315dab78f5f54c9b3d83f8fb5905c1c05 - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 - languageName: node - linkType: hard - -"tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: "npm:^7.0.0" - checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 - languageName: node - linkType: hard - -"ts-node@npm:^10.2.1": - version: 10.2.1 - resolution: "ts-node@npm:10.2.1" - dependencies: - "@cspotcode/source-map-support": "npm:0.6.1" - "@tsconfig/node10": "npm:^1.0.7" - "@tsconfig/node12": "npm:^1.0.7" - "@tsconfig/node14": "npm:^1.0.0" - "@tsconfig/node16": "npm:^1.0.2" - acorn: "npm:^8.4.1" - acorn-walk: "npm:^8.1.1" - arg: "npm:^4.1.0" - create-require: "npm:^1.1.0" - diff: "npm:^4.0.1" - make-error: "npm:^1.1.1" - yn: "npm:3.1.1" - peerDependencies: - "@swc/core": ">=1.2.50" - "@swc/wasm": ">=1.2.50" - "@types/node": "*" - typescript: ">=2.7" - peerDependenciesMeta: - "@swc/core": - optional: true - "@swc/wasm": - optional: true - bin: - ts-node: dist/bin.js - ts-node-cwd: dist/bin-cwd.js - ts-node-script: dist/bin-script.js - ts-node-transpile-only: dist/bin-transpile.js - ts-script: dist/bin-script-deprecated.js - checksum: 10c0/15755a09a97797036aed3672a9551a441958271c3e77a99714b41db3fcfc5829ae22aac3365d48bcf94f88a78c5cc8e3e2cd13240d948d19b7aa1a47f210bfe3 - languageName: node - linkType: hard - -"tslib@npm:^1.13.0, tslib@npm:^1.8.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 - languageName: node - linkType: hard - -"tslint@npm:^6.1.3": - version: 6.1.3 - resolution: "tslint@npm:6.1.3" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - builtin-modules: "npm:^1.1.1" - chalk: "npm:^2.3.0" - commander: "npm:^2.12.1" - diff: "npm:^4.0.1" - glob: "npm:^7.1.1" - js-yaml: "npm:^3.13.1" - minimatch: "npm:^3.0.4" - mkdirp: "npm:^0.5.3" - resolve: "npm:^1.3.2" - semver: "npm:^5.3.0" - tslib: "npm:^1.13.0" - tsutils: "npm:^2.29.0" - peerDependencies: - typescript: ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - bin: - tslint: bin/tslint - checksum: 10c0/04717de06d187ee46ffa99e28af80f1b5a2edbec051e32b43ca681da625a61e94e5eb9ebb638fafe07975fb3536760ffd772f76c57134db723a9ecff6aeac380 - languageName: node - linkType: hard - -"tsutils@npm:^2.29.0": - version: 2.29.0 - resolution: "tsutils@npm:2.29.0" - dependencies: - tslib: "npm:^1.8.1" - peerDependencies: - typescript: ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - checksum: 10c0/e37794513526dbf1cf960414d0a65b956ad319dbc93171bccfe08e3fece1eea35b4e130153f41d917a0f28ecac04f3ca78e9a99c4bddc64a5f225925abc0cf14 - languageName: node - linkType: hard - -"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 10c0/8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd - languageName: node - linkType: hard - -"typescript@npm:^4.3.4": - version: 4.3.4 - resolution: "typescript@npm:4.3.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/05e116885c639a9bdbd65ad4020c8954f619c02124c6db79d3d36a360e7a9399472844936beee005fe623dfaab2123aeb12e332b53e388d2fd15296abad1143f - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^4.3.4#optional!builtin": - version: 4.3.4 - resolution: "typescript@patch:typescript@npm%3A4.3.4#optional!builtin::version=4.3.4&hash=dba6d9" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/90273a7286e851fcf44a33ceaadd50b56463efeded329274b04f25b332ae6501d2e21700cb12bda7425c0c2708f1cd08186c936b4d493f82df4352340f9bdb06 - languageName: node - linkType: hard - -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f - languageName: node - linkType: hard - -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 - languageName: node - linkType: hard - -"which@npm:2.0.2, which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a - languageName: node - linkType: hard - -"workerpool@npm:6.2.0": - version: 6.2.0 - resolution: "workerpool@npm:6.2.0" - checksum: 10c0/67821b2d1d9e493ba0c395a458fbd3090be97943f98826bdb7b3ca4b9480caea1659c2c0c44c4edd6178ed89919eef598c687c9c81639d8217e913c52d3fff1b - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yargs-parser@npm:20.2.4": - version: 20.2.4 - resolution: "yargs-parser@npm:20.2.4" - checksum: 10c0/08dc341f0b9f940c2fffc1d1decf3be00e28cabd2b578a694901eccc7dcd10577f10c6aa1b040fdd9a68b2042515a60f18476543bccacf9f3ce2c8534cd87435 - languageName: node - linkType: hard - -"yargs-parser@npm:^20.2.2": - version: 20.2.9 - resolution: "yargs-parser@npm:20.2.9" - checksum: 10c0/0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 - languageName: node - linkType: hard - -"yargs-unparser@npm:2.0.0": - version: 2.0.0 - resolution: "yargs-unparser@npm:2.0.0" - dependencies: - camelcase: "npm:^6.0.0" - decamelize: "npm:^4.0.0" - flat: "npm:^5.0.2" - is-plain-obj: "npm:^2.1.0" - checksum: 10c0/a5a7d6dc157efa95122e16780c019f40ed91d4af6d2bac066db8194ed0ec5c330abb115daa5a79ff07a9b80b8ea80c925baacf354c4c12edd878c0529927ff03 - languageName: node - linkType: hard - -"yargs@npm:16.2.0": - version: 16.2.0 - resolution: "yargs@npm:16.2.0" - dependencies: - cliui: "npm:^7.0.2" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.0" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^20.2.2" - checksum: 10c0/b1dbfefa679848442454b60053a6c95d62f2d2e21dd28def92b647587f415969173c6e99a0f3bab4f1b67ee8283bf735ebe3544013f09491186ba9e8a9a2b651 - languageName: node - linkType: hard - -"yn@npm:3.1.1": - version: 3.1.1 - resolution: "yn@npm:3.1.1" - checksum: 10c0/0732468dd7622ed8a274f640f191f3eaf1f39d5349a1b72836df484998d7d9807fbea094e2f5486d6b0cd2414aad5775972df0e68f8604db89a239f0f4bf7443 - languageName: node - linkType: hard - -"yocto-queue@npm:^0.1.0": - version: 0.1.0 - resolution: "yocto-queue@npm:0.1.0" - checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f - languageName: node - linkType: hard +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== + dependencies: + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@oozcitak/dom@1.15.10": + version "1.15.10" + resolved "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz" + integrity sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ== + dependencies: + "@oozcitak/infra" "1.0.8" + "@oozcitak/url" "1.0.4" + "@oozcitak/util" "8.3.8" + +"@oozcitak/infra@1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz" + integrity sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg== + dependencies: + "@oozcitak/util" "8.3.8" + +"@oozcitak/url@1.0.4": + version "1.0.4" + resolved "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz" + integrity sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw== + dependencies: + "@oozcitak/infra" "1.0.8" + "@oozcitak/util" "8.3.8" + +"@oozcitak/util@8.3.8": + version "8.3.8" + resolved "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz" + integrity sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ== + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/chai@^4.2.21": + version "4.3.14" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz" + integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== + +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node@*", "@types/node@^20.4.5": + version "20.11.30" + resolved "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz" + integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== + dependencies: + undici-types "~5.26.4" + +"@types/path-browserify@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@types/path-browserify/-/path-browserify-1.0.2.tgz" + integrity sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA== + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1: + version "8.11.3" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^4.3.4: + version "4.4.1" + resolved "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" + +chalk@^2.3.0: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +commander@^2.12.1: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +debug@^4.3.1: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@4.3.3: + version "4.3.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.1: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@3.14.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +logging@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/logging/-/logging-3.3.0.tgz" + integrity sha512-Hnmu3KlGTbXMVS7ONjBpnjjiF9cBlK5qsmj77sOcqRkNpvO9ouUGPKe2PmBCWWYpKAbxb96b08cYEv4hiBk3lQ== + dependencies: + chalk "^4.1.0" + debug "^4.3.1" + nicely-format "^1.1.0" + +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^0.5.3: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mocha@^9.1.1: + version "9.2.2" + resolved "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.3" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "4.2.1" + ms "2.1.3" + nanoid "3.3.1" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.2.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== + +nicely-format@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/nicely-format/-/nicely-format-1.1.0.tgz" + integrity sha512-nZk4ea8ZeH6KKpfzhopC7sC0KeN2+QZQIxp2jvElndkyXuM3pJqB8I4fTypkWCyeKBJRLdQ1h/O2L48lS6S6gg== + dependencies: + ansi-styles "^2.2.1" + esutils "^2.0.2" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve@^1.3.2: + version "1.22.8" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^5.3.0: + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-node@^10.2.1: + version "10.9.2" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.13.0, tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslint@^6.1.3: + version "6.1.3" + resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz" + integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== + dependencies: + "@babel/code-frame" "^7.0.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^4.0.1" + glob "^7.1.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + mkdirp "^0.5.3" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.13.0" + tsutils "^2.29.0" + +tsutils@^2.29.0: + version "2.29.0" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +typescript@^4.3.4, "typescript@>=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev", "typescript@>=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev", typescript@>=2.7: + version "4.9.5" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +which@2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xmlbuilder2@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz" + integrity sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw== + dependencies: + "@oozcitak/dom" "1.15.10" + "@oozcitak/infra" "1.0.8" + "@oozcitak/util" "8.3.8" + js-yaml "3.14.1" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^20.2.2, yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 5292b3d7331b6f27fdafba3a3217d033ea89da41 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 11:52:03 +0200 Subject: [PATCH 02/11] core parse --- src/main/libs/ParseFlows.ts | 3 +- src/main/models/Flow.ts | 146 ++++++++++++++++----------------- src/main/models/FlowNode.ts | 33 ++++---- src/main/rules/AutoLayout.ts | 8 +- src/main/rules/InactiveFlow.ts | 2 +- tests/APIVersion.test.ts | 35 +++----- tests/CopyAPIName.test.ts | 29 +++---- 7 files changed, 121 insertions(+), 135 deletions(-) diff --git a/src/main/libs/ParseFlows.ts b/src/main/libs/ParseFlows.ts index 7689068..d505561 100644 --- a/src/main/libs/ParseFlows.ts +++ b/src/main/libs/ParseFlows.ts @@ -8,7 +8,8 @@ export async function ParseFlows(selectedUris: string[]) { let parsedFlows: Flow[] = []; for (let uri of selectedUris) { try { - let content = await fs.readFileSync(p.normalize(uri)); + let normalizedURI = p.normalize(uri); + let content = await fs.readFileSync(normalizedURI); let xmlString = content.toString(); const flowObj = convert(xmlString, { format: 'object' }); parsedFlows.push(new Flow( diff --git a/src/main/models/Flow.ts b/src/main/models/Flow.ts index d591b2c..670544b 100644 --- a/src/main/models/Flow.ts +++ b/src/main/models/Flow.ts @@ -1,12 +1,11 @@ -import {FlowNode} from './FlowNode'; -import { FlowMetadata } from './FlowMetadata'; -import {FlowElement} from './FlowElement'; -import {FlowVariable} from './FlowVariable'; +import { FlowNode } from "./FlowNode"; +import { FlowMetadata } from "./FlowMetadata"; +import { FlowElement } from "./FlowElement"; +import { FlowVariable } from "./FlowVariable"; import p from "path-browserify"; -import { FlowResource } from './FlowResource'; +import { FlowResource } from "./FlowResource"; export class Flow { - public label: string; public xmldata; public name?: string; @@ -23,71 +22,68 @@ export class Flow { public startReference; private flowVariables = [ - 'choices', - 'constants', - 'dynamicChoiceSets', - 'formulas', - 'variables' + "choices", + "constants", + "dynamicChoiceSets", + "formulas", + "variables", ]; - private flowResources = ['textTemplates', 'stages']; + private flowResources = ["textTemplates", "stages"]; private flowMetadata = [ - 'description', - 'apiVersion', - 'processMetadataValues', - 'processType', - 'interviewLabel', - 'label', - 'status', - 'runInMode', - 'startElementReference', - 'isTemplate', - 'fullName', - 'timeZoneSidKey', - 'isAdditionalPermissionRequiredToRun', - 'migratedFromWorkflowRuleName', - 'triggerOrder', - 'environments', - 'segment' + "description", + "apiVersion", + "processMetadataValues", + "processType", + "interviewLabel", + "label", + "status", + "runInMode", + "startElementReference", + "isTemplate", + "fullName", + "timeZoneSidKey", + "isAdditionalPermissionRequiredToRun", + "migratedFromWorkflowRuleName", + "triggerOrder", + "environments", + "segment", ]; private flowNodes = [ - 'actionCalls', - 'apexPluginCalls', - 'assignments', - 'collectionProcessors', - 'decisions', - 'loops', - 'orchestratedStages', - 'recordCreates', - 'recordDeletes', - 'recordLookups', - 'recordUpdates', - 'recordRollbacks', - 'screens', - 'start', - 'steps', - 'subflows', - 'waits' + "actionCalls", + "apexPluginCalls", + "assignments", + "collectionProcessors", + "decisions", + "loops", + "orchestratedStages", + "recordCreates", + "recordDeletes", + "recordLookups", + "recordUpdates", + "recordRollbacks", + "screens", + "start", + "steps", + "subflows", + "waits", ]; - constructor(args :{path: string, xmldata: any}) { + constructor(args: { path: string; xmldata: any }) { this.fsPath = p.resolve(args.path); let flowName = p.basename(p.basename(this.fsPath), p.extname(this.fsPath)); - if (flowName.includes('.')) { - flowName = flowName.split('.')[0] + if (flowName.includes(".")) { + flowName = flowName.split(".")[0]; } this.name = flowName; - - // todo fix - if(args.xmldata && args.xmldata.Flow){ + if (args.xmldata && args.xmldata.Flow) { this.xmldata = args.xmldata.Flow; - } else if(args.xmldata){ + } else if (args.xmldata) { this.xmldata = args.xmldata; } this.preProcessNodes(); } public preProcessNodes() { - this.label = this.xmldata.label; this.interviewLabel = this.xmldata.interviewLabel; this.processType = this.xmldata.processType; @@ -102,41 +98,39 @@ export class Flow { // if (nodeType == "@xmlns") { // continue; // } + let data = this.xmldata[nodeType]; if (this.flowMetadata.includes(nodeType)) { - let data = this.xmldata[nodeType]; if (Array.isArray(data)) { for (const node of data) { allNodes.push(new FlowMetadata(nodeType, data[node])); } } else { - allNodes.push(new FlowMetadata( - nodeType, - this.xmldata[nodeType] - )); + allNodes.push(new FlowMetadata(nodeType, this.xmldata[nodeType])); } } else if (this.flowVariables.includes(nodeType)) { - let data = this.xmldata[nodeType]; if (Array.isArray(data)) { for (const node of data) { - allNodes.push(new FlowVariable(data[node].name, nodeType, data[node])); + allNodes.push( + new FlowVariable(data[node].name, nodeType, data[node]) + ); } } else { allNodes.push(new FlowVariable(data.name, nodeType, data)); } } else if (this.flowNodes.includes(nodeType)) { - let data = this.xmldata[nodeType]; if (Array.isArray(data)) { for (const node of data) { - allNodes.push(new FlowNode(data[node].name, nodeType, data[node])); + allNodes.push(new FlowNode(node.name, nodeType, node)); } } else { allNodes.push(new FlowNode(data.name, nodeType, data)); } } else if (this.flowResources.includes(nodeType)) { - let data = this.xmldata[nodeType]; if (Array.isArray(data)) { for (const node of data) { - allNodes.push(new FlowResource(data[node].name, nodeType, data[node])); + allNodes.push( + new FlowResource(data[node].name, nodeType, data[node]) + ); } } else { allNodes.push(new FlowResource(data.name, nodeType, data)); @@ -148,20 +142,22 @@ export class Flow { } private findStart() { - let start = ''; - const flowElements: FlowNode[] = this.elements.filter(node => node instanceof FlowNode) as FlowNode[]; + let start = ""; + const flowElements: FlowNode[] = this.elements.filter( + (node) => node instanceof FlowNode + ) as FlowNode[]; if (this.startElementReference) { start = this.startElementReference; - } else if(flowElements.find(n => { - return n.subtype === 'start'; - })){ - let startElement = flowElements.find(n => { - return n.subtype === 'start'; + } else if ( + flowElements.find((n) => { + return n.subtype === "start"; + }) + ) { + let startElement = flowElements.find((n) => { + return n.subtype === "start"; }); - start = startElement.connectors['reference']; + start = startElement.connectors[0]["reference"]; } return start; } - } - diff --git a/src/main/models/FlowNode.ts b/src/main/models/FlowNode.ts index 5d5f4b1..f7ddee7 100644 --- a/src/main/models/FlowNode.ts +++ b/src/main/models/FlowNode.ts @@ -8,13 +8,12 @@ export class FlowNode extends FlowElement { public locationX: string; public locationY: string; - constructor(name: string, subtype: string, element: object) { + constructor(provName: string, subtype: string, element: object) { super('node', subtype, element); - this.name = (subtype === 'start' ? 'flowstart' : name); + let nodeName = subtype === 'start' ? 'flowstart' : provName; + this.name = nodeName; const connectors = this.getConnectors(subtype, element); - if (connectors !== undefined && connectors.length > 0) { - this.connectors = connectors; - } + this.connectors = connectors; this.locationX = element["locationX"]; this.locationY = element["locationY"]; } @@ -56,20 +55,24 @@ export class FlowNode extends FlowElement { } return connectors; } else if (subtype === 'assignments') { - return [new FlowElementConnector('connector', element.connector, {})]; + return element.connector ? [new FlowElementConnector('connector', element.connector, {})] : []; } else if (subtype === 'loops') { - return [ - new FlowElementConnector( + const connectors = []; + if(element.nextValueConnector){ + connectors.push(new FlowElementConnector( 'nextValueConnector', element.nextValueConnector, {} - ), - new FlowElementConnector( + )) + } + if(element.noMoreValuesConnector){ + connectors.push(new FlowElementConnector( 'noMoreValuesConnector', element.noMoreValuesConnector, {} - ) - ]; + )) + } + return connectors; } else if (subtype === 'actionCalls') { const connectors = []; if (element.connector) { @@ -139,11 +142,11 @@ export class FlowNode extends FlowElement { } return connectors; } else if (subtype === 'subflows') { - return [new FlowElementConnector('connector', element.connector, {})]; + return element.connector ? [new FlowElementConnector('connector', element.connector, {})] : []; } else if (subtype === 'screens') { - return [new FlowElementConnector('connector', element.connector, {})]; + return element.connector ? [new FlowElementConnector('connector', element.connector, {})] : []; } else { - return [new FlowElementConnector('connector', element.connector, {})]; + return element.connector ? [new FlowElementConnector('connector', element.connector, {})] : []; } } } \ No newline at end of file diff --git a/src/main/rules/AutoLayout.ts b/src/main/rules/AutoLayout.ts index 6c208e9..7dc0a94 100644 --- a/src/main/rules/AutoLayout.ts +++ b/src/main/rules/AutoLayout.ts @@ -17,12 +17,12 @@ export class AutoLayout extends RuleCommon implements core.IRuleDefinition { public execute(flow: core.Flow, options?: { expression: string }): core.RuleResult { - if (flow.xmldata.processMetadataValues && flow.xmldata.processMetadataValues[0]) { + if (flow.xmldata.processMetadataValues) { - const CanvasMode = flow.xmldata.processMetadataValues.find(mdv => mdv.name[0] === 'CanvasMode'); - const AutoLayout = CanvasMode.value[0] && typeof CanvasMode.value[0] === 'object' && 'stringValue' in CanvasMode.value[0] && Array.isArray(CanvasMode.value[0].stringValue) && CanvasMode.value[0].stringValue[0] === "AUTO_LAYOUT_CANVAS"; + const CanvasMode = flow.xmldata.processMetadataValues.find(mdv => mdv.name === 'CanvasMode'); + const AutoLayout = CanvasMode.value && typeof CanvasMode.value === 'object' && 'stringValue' in CanvasMode.value && Array.isArray(CanvasMode.value.stringValue) && CanvasMode.value.stringValue === "AUTO_LAYOUT_CANVAS"; return (!AutoLayout ? - new core.RuleResult(this, [new core.ResultDetails(new core.FlowAttribute(CanvasMode.value[0]?.stringValue[0], "CanvasMode", '!== AUTO_LAYOUT_CANVAS'))]) : + new core.RuleResult(this, [new core.ResultDetails(new core.FlowAttribute(CanvasMode.value?.stringValue, "CanvasMode", '!== AUTO_LAYOUT_CANVAS'))]) : new core.RuleResult(this, [])); } } diff --git a/src/main/rules/InactiveFlow.ts b/src/main/rules/InactiveFlow.ts index b95abeb..72fe7bf 100644 --- a/src/main/rules/InactiveFlow.ts +++ b/src/main/rules/InactiveFlow.ts @@ -10,7 +10,7 @@ export class InactiveFlow extends RuleCommon implements core.IRuleDefinition { description: 'Like cleaning out your closet: deleting unused flows is essential. Inactive flows can still cause trouble, like accidentally deleting records during testing, or being activated as subflows within parent flows.', supportedTypes: core.FlowType.allTypes(), docRefs: [], - isConfigurable: true, + isConfigurable: false, autoFixable: false }, ); diff --git a/tests/APIVersion.test.ts b/tests/APIVersion.test.ts index f947c10..a223831 100644 --- a/tests/APIVersion.test.ts +++ b/tests/APIVersion.test.ts @@ -1,17 +1,15 @@ import { assert, expect } from 'chai'; import 'mocha'; import * as core from '../src' -import Hidenav from './testfiles/hidenav.json'; -import Api58 from './testfiles/api58test.json'; +import * as path from 'path-browserify'; describe('APIVersion', () => { - let flow: core.Flow; + let example_uri = path.join(__dirname, './xmlfiles/Outdated_API_Version.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml'); - it(' should have a result when attribute is missing', () => { - flow = new core.Flow({ - path: './testfiles/CreateANewAccount.flow-meta.xml', - xmldata: Hidenav, - }); + it('should have a result when attribute is missing', async () => { + + let flows = await core.parse([example_uri]) const ruleConfig = { rules: { @@ -22,17 +20,14 @@ describe('APIVersion', () => { } }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('APIVersion'); expect(results[0].ruleResults[0].occurs).to.equal(true); }); - it('should have a result when below configured threshold', () => { - flow = new core.Flow({ - path: './testfiles/api58test.flow-meta.xml', - xmldata: Api58, - }); + it('should have a result when below configured threshold', async () => { + let flows = await core.parse([example_uri]) const ruleConfig = { rules: { @@ -44,19 +39,15 @@ describe('APIVersion', () => { } }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('APIVersion'); expect(results[0].ruleResults[0].occurs).to.equal(true); }); - it('should have no result when version is meeting threshold', () => { + it('should have no result when version is meeting threshold', async () => { - flow = new core.Flow({ - path: './testfiles/api58test.flow-meta.xml', - xmldata: Api58, - }); - + let flows = await core.parse([fixed_uri]) const ruleConfig = { rules: { @@ -67,7 +58,7 @@ describe('APIVersion', () => { } }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('APIVersion'); expect(results[0].ruleResults[0].occurs).to.equal(false); diff --git a/tests/CopyAPIName.test.ts b/tests/CopyAPIName.test.ts index 4ca7c2e..118404b 100644 --- a/tests/CopyAPIName.test.ts +++ b/tests/CopyAPIName.test.ts @@ -1,17 +1,15 @@ import { assert, expect } from 'chai'; import 'mocha'; import * as core from '../src'; -import CreateANewAccountWithChild from './testfiles/CreateANewAccountWithChild.json'; -import CreateANewAccountWithCopy from './testfiles/CreateANewAccountWithCopy.json'; +import * as path from 'path-browserify'; describe('CopyAPIName ', () => { - let flow: core.Flow; + + let example_uri = path.join(__dirname, './xmlfiles/Copy_API_Name.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Copy_API_Name_Fixed.flow-meta.xml'); - it('CopyAPIName should have no result', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: CreateANewAccountWithChild, - }); + it('CopyAPIName should have a result', async () => { + let flows = await core.parse([example_uri]) const ruleConfig = { rules: { @@ -21,18 +19,15 @@ describe('CopyAPIName ', () => { }, }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('CopyAPIName'); - expect(results[0].ruleResults[0].occurs).to.equal(false); + expect(results[0].ruleResults[0].occurs).to.equal(true); }); - it('CopyAPIName should have no result', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: CreateANewAccountWithCopy, - }); + it('CopyAPIName should have no result', async () => { + let flows = await core.parse([fixed_uri]) const ruleConfig = { rules: { @@ -42,10 +37,10 @@ describe('CopyAPIName ', () => { }, }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('CopyAPIName'); - expect(results[0].ruleResults[0].occurs).to.equal(true); + expect(results[0].ruleResults[0].occurs).to.equal(false); }); }); \ No newline at end of file From de78d2a7c6af44bad005f1661788a17ac667f35e Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 14:39:24 +0200 Subject: [PATCH 03/11] readd tests --- .DS_Store | Bin 8196 -> 8196 bytes src/index.ts | 13 +- src/main/libs/FixFlows.ts | 7 +- src/main/libs/ParseFlows.ts | 24 ++-- src/main/models/Flow.ts | 18 +-- src/main/models/ParsedFlow.ts | 15 +++ tests/.DS_Store | Bin 6148 -> 8196 bytes tests/AutoLayout.test.ts | 53 -------- tests/Config.test.ts | 171 ------------------------- tests/DMLStatementInLoop.test.ts | 30 ----- tests/DuplicateDMLOperation.test.ts | 191 ---------------------------- tests/FlowDescription.test.ts | 27 ++-- tests/FlowName.test.ts | 38 +++--- tests/HardcodedId.test.ts | 24 ---- tests/InactiveFlow.test.ts | 36 ------ tests/MissingFaultPath.test.ts | 32 ----- tests/MissingNullHandler.test.ts | 95 -------------- tests/ParsingTest.test.ts | 14 -- tests/SOQLQueryInLoop.test.ts | 30 ----- tests/UnconnectedElement.test.ts | 42 ------ tests/UnusedVariable.test.ts | 50 -------- 21 files changed, 75 insertions(+), 835 deletions(-) create mode 100644 src/main/models/ParsedFlow.ts delete mode 100644 tests/AutoLayout.test.ts delete mode 100644 tests/Config.test.ts delete mode 100644 tests/DMLStatementInLoop.test.ts delete mode 100644 tests/DuplicateDMLOperation.test.ts delete mode 100644 tests/HardcodedId.test.ts delete mode 100644 tests/InactiveFlow.test.ts delete mode 100644 tests/MissingFaultPath.test.ts delete mode 100644 tests/MissingNullHandler.test.ts delete mode 100644 tests/ParsingTest.test.ts delete mode 100644 tests/SOQLQueryInLoop.test.ts delete mode 100644 tests/UnconnectedElement.test.ts delete mode 100644 tests/UnusedVariable.test.ts diff --git a/.DS_Store b/.DS_Store index 5c610eb885351dac0a3de9b93a4d87fb7d5b97ab..c62731e02efece879ae1b047e8d851dc5b158620 100644 GIT binary patch delta 255 zcmZp1XmOa}&(FfZz`)4BAi%&-oK#+1urY2ee?3Tym7# zGK)(L46ZRUF|)9;v2(Cy7CR*tMT2-D`T03XFm_^6SY~Q@ynu*v zeqKppW?pI$SVLw?Do{yGcxGNoez{YAX { +export function parse(selectedUris: any): Promise { return ParseFlows(selectedUris); } -export function scan(flows: Flow[], ruleOptions?: IRulesConfig): ScanResult[] { + +export function scan(parsedFlows: ParsedFlow[], ruleOptions?: IRulesConfig): ScanResult[] { + + let flows: Flow[] = []; + for(let flow of parsedFlows){ + if(!flow.errorMessage && flow.flow){ + flows.push(flow.flow); + } + } let scanResults: ScanResult[]; if (ruleOptions?.rules && Object.entries(ruleOptions.rules).length > 0) { scanResults = ScanFlows(flows, ruleOptions); diff --git a/src/main/libs/FixFlows.ts b/src/main/libs/FixFlows.ts index d0d8826..e4e593b 100644 --- a/src/main/libs/FixFlows.ts +++ b/src/main/libs/FixFlows.ts @@ -29,9 +29,8 @@ export function FixFlows(flow: core.Flow, ruleResults: core.RuleResult[]): core. } ); let xmldata = BuildFlow(nodesToBuild); - const newFlow = new core.Flow({ - 'path': flow.fsPath, - 'xmldata': xmldata - }); + const newFlow = new core.Flow( + flow.fsPath, xmldata + ); return newFlow; } diff --git a/src/main/libs/ParseFlows.ts b/src/main/libs/ParseFlows.ts index d505561..b7619fb 100644 --- a/src/main/libs/ParseFlows.ts +++ b/src/main/libs/ParseFlows.ts @@ -1,25 +1,21 @@ import p from "path-browserify"; -import { Flow } from '../models/Flow'; -import * as fs from 'fs'; -import { convert } from 'xmlbuilder2'; +import { Flow } from "../models/Flow"; +import * as fs from "fs"; +import { convert } from "xmlbuilder2"; +import { ParsedFlow } from "../models/ParsedFlow"; -export async function ParseFlows(selectedUris: string[]) { - - let parsedFlows: Flow[] = []; +export async function ParseFlows(selectedUris: string[]): Promise { + let parseResults: ParsedFlow[] = []; for (let uri of selectedUris) { try { let normalizedURI = p.normalize(uri); let content = await fs.readFileSync(normalizedURI); let xmlString = content.toString(); - const flowObj = convert(xmlString, { format: 'object' }); - parsedFlows.push(new Flow( - { - 'path': uri, - xmldata: flowObj - })); + const flowObj = convert(xmlString, { format: "object" }); + parseResults.push(new ParsedFlow(uri, new Flow(uri, flowObj))); } catch (e) { - // todo catch error + parseResults.push(new ParsedFlow(uri, undefined, e.errorMessage)); } } - return parsedFlows; + return parseResults; } diff --git a/src/main/models/Flow.ts b/src/main/models/Flow.ts index 670544b..cb3f365 100644 --- a/src/main/models/Flow.ts +++ b/src/main/models/Flow.ts @@ -68,19 +68,19 @@ export class Flow { "waits", ]; - constructor(args: { path: string; xmldata: any }) { - this.fsPath = p.resolve(args.path); + constructor(path: string, data?: any) { + this.fsPath = p.resolve(path); let flowName = p.basename(p.basename(this.fsPath), p.extname(this.fsPath)); if (flowName.includes(".")) { flowName = flowName.split(".")[0]; } this.name = flowName; - if (args.xmldata && args.xmldata.Flow) { - this.xmldata = args.xmldata.Flow; - } else if (args.xmldata) { - this.xmldata = args.xmldata; + if(data){ + if (data.Flow) { + this.xmldata = data.Flow; + } else this.xmldata = data; + this.preProcessNodes(); } - this.preProcessNodes(); } public preProcessNodes() { @@ -104,8 +104,10 @@ export class Flow { for (const node of data) { allNodes.push(new FlowMetadata(nodeType, data[node])); } + for (const node of data) { + } } else { - allNodes.push(new FlowMetadata(nodeType, this.xmldata[nodeType])); + allNodes.push(new FlowMetadata(nodeType, data)); } } else if (this.flowVariables.includes(nodeType)) { if (Array.isArray(data)) { diff --git a/src/main/models/ParsedFlow.ts b/src/main/models/ParsedFlow.ts new file mode 100644 index 0000000..00664de --- /dev/null +++ b/src/main/models/ParsedFlow.ts @@ -0,0 +1,15 @@ +import { Flow } from "./Flow"; + +export class ParsedFlow { + public uri: string; + public flow: Flow | undefined; + public errorMessage?: string; + + constructor(uri: string, flow: Flow, errorMessage?: string) { + this.uri = uri; + this.flow = flow; + if (errorMessage) { + this.errorMessage = errorMessage; + } + } +} diff --git a/tests/.DS_Store b/tests/.DS_Store index 000a841fbb24ebc2ea302826e57a29a5a2bb649c..663532c3e566b2e1f0ac94dd76da38423c07469f 100644 GIT binary patch literal 8196 zcmeHMU2GIp6u#fIz>FQ}Pzw}vvRhXH%Mw~>_z4=e?G~;46uK?_1KQo4fsV}1l%3rz zP|@m>ioEz>h!~9zMtw1A5HP+N;}6jX6Ky1znE3Nx;?Ijl)Wk&3ojXgQKk@7$TQWsISV-lsJw;8YR?=`&_Ao0-hZjCrHe zc882G0$~Kg2!s&`BM?U5Mu-5tvw4$edG8BpIEE1jBk;eB0KXri)HzKAbV5-7>Y%|d z0f_Pvz;86CI>6V71~d`S2|;~TvMH(u1gZ#137*C+w=*OJ4aYD7VFac}fTxelj<6h6?gy@}-!rzGA=&xNsBL+L#>OuoRaDNIJ5Qb` zSIPTQBkowLkS-Lx)^vW5uex2=&Xnir%pS`e8`5gqT&Iw>95e4LScXYk_V!wi;f}Ss zMaS@b-INf>imVK2b>rjfHa5ni&CN~6L=JS07A)8C_LzB(=#W)+QppX4QUIrX**lA(*?7|wo}$IlX%r$Ht*W@F4wcTnf|_ld8EK) z(?op(o|`YU`NsMzvM+XNMbGRq$*5H_lVsY{puDzVN#xFztJiM0C(+)qvumDg@`NNPC92!*3>OscH8Z`K6Q85 zN?$Q!9WGjhqgqUs#ToT_Owrzw_Zswv>~IZk(eNdDy}m-02RXkjZ_+5(YJ(nEw6xsq zk;lTs8nsE$Jf-^(J%6Fvtge?eL+P>88PgW5P3mS@+otrEM9>AZR^1{ieOWh`BWFCp zYt@soc0u0H58j^k3Z0{-LuYf>w$|%?`&?`-T0=F0flR8tI`-FptcZh1xuxvGOF}U4Mrf(dJODh~@GXw46(MB9^P- zk%%TydWvOZQ$*D&DESm$w<;b{gXzXis;X5|5(>$^IxShSXlW%QJf-C81@4d8=j;;u zhW$+7{u`B0P=|V~z-j{X7PJtc+p(1Zy&EZXqX+vjj0~~_?;KnlMjjp>!o!%rqj<~* z_eng1Q+U>g_)7%vSMVwU{0z?G9M0oyyoXOPiA(r)3Us$$3tfCS6Ld?dykoo0L6Vgr zf34b0wyF^R)baYiefHn~Z!)h#cftsS5x6=6s7$7kt;Ct_*5kEyl=?7r-uS)=L46e( y_!iFh%Wf1h|2OD@en}!tczJ`DH8>K*Ed+3`|g(1w;cmAfrLHF>H?KnZpbK DExHnW diff --git a/tests/AutoLayout.test.ts b/tests/AutoLayout.test.ts deleted file mode 100644 index 6161e43..0000000 --- a/tests/AutoLayout.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import Hidenav from './testfiles/hidenav.json'; -import Api58 from './testfiles/api58test.json'; - -describe('Autolayout', () => { - let flow: core.Flow; - - it(' should have a result when CanvasMode is set to FREE_FORM_CANVAS', () => { - flow = new core.Flow({ - path: './testfiles/Hidenav.flow-meta.xml', - xmldata: Hidenav, - }); - const ruleConfig = { - rules: - { - AutoLayout: - { - severity: 'error' - }, - } - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults.find((res) => res.ruleName === 'AutoLayout')); - - }); - - it('should not have result when autolayout is configured', () => { - - flow = new core.Flow({ - path: './testfiles/Api58.flow-meta.xml', - xmldata: Api58, - }); - - const ruleConfig = { - rules: - { - AutoLayout: - { - severity: 'error' - }, - } - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); - - }); -}); diff --git a/tests/Config.test.ts b/tests/Config.test.ts deleted file mode 100644 index bb1e77e..0000000 --- a/tests/Config.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import unconnectedElement from './testfiles/UnconnectedElement.json'; -import Hidenav from './testfiles/hidenav.json'; -import flawed from './testfiles/flawedflow.json'; - -describe('Rule Configurations ', () => { - - let flow2: core.Flow; - - it(' should use default when no configuration is provided', () => { - flow2 = new core.Flow({ - path: './testfiles/unconnectedElement.flow-meta.xml', - xmldata: unconnectedElement, - }); - const results: core.ScanResult[] = core.scan([flow2], undefined); - const rules = core.getRules(); - expect(results[0].ruleResults.length).to.equal(rules.length); - }); - - it(' should return errormessage when file seems corrupt', () => { - flow2 = new core.Flow({ - path: './testfiles/flawed.flow-meta.xml', - xmldata: flawed, - }); - const results: core.ScanResult[] = core.scan([flow2], undefined); - expect(results[0].ruleResults[0].errorMessage); - }); - - - it(' should use default when no rules are specified', () => { - flow2 = new core.Flow({ - path: './testfiles/unconnectedElement.flow-meta.xml', - xmldata: unconnectedElement, - }); - const ruleConfig = { - rules: - { - - }, - exceptions: - { - CreateANewAccountWithChild: - {"DuplicateDMLOperation":["ViewAccountId"]} - } - }; - const results: core.ScanResult[] = core.scan([flow2], ruleConfig); - const rules = core.getRules(); - expect(results[0].ruleResults.length).to.equal(rules.length); - }); - - it('incorrect rule severity configurations are defaulted', () => { - flow2 = new core.Flow({ - path: './testfiles/unconnectedElement.flow-meta.xml', - xmldata: unconnectedElement, - }); - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'errorr', - } - } - }; - const results: core.ScanResult[] = core.scan([flow2], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - }); - - - it('incorrect rule configurations are skipped', () => { - flow2 = new core.Flow({ - path: './testfiles/unconnectedElement.flow-meta.xml', - xmldata: unconnectedElement, - }); - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'error', - }, - MissingNullHandler2: - { - severity: 'error', - } - }, - exceptions: - { - CreateANewAccountWithChild: - {"DuplicateDMLOperation":["ViewAccountId"]} - } - }; - const results: core.ScanResult[] = core.scan([flow2], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - }); - - it('Multiple Expressions are individually checked', () => { - flow2 = new core.Flow({ - path: './testfiles/Async_OnlyTransaction.flow-meta.xml', - xmldata: unconnectedElement, - }); - const ruleConfig = { - rules: { - APIVersion: { - severity: "error", - expression: ">50", - }, - CopyAPIName: { - severity: "error", - }, - DMLStatementInLoop: { - severity: "error", - }, - DuplicateDMLOperation: { - severity: "error", - }, - FlowDescription: { - severity: "error", - }, - FlowName: { - severity: "error", - expression: "[A-Za-z0-9]+_[A-Za-z0-9]+", - }, - HardcodedId: { - severity: "error", - }, - MissingFaultPath: { - severity: "error", - }, - MissingNullHandler: { - severity: "error", - }, - SOQLQueryInLoop: { - severity: "error", - }, - UnconnectedElement: { - severity: "error", - }, - UnusedVariable: { - severity: "error", - }, - }, - }; - const results: core.ScanResult[] = core.scan([flow2], ruleConfig); - expect(results[0].ruleResults.find((r) => r.ruleName === 'FlowName')?.occurs).to.equal(false); - }); - - it(' should give result', () => { - flow2 = new core.Flow({ - path: './testfiles/NewAccountName.flow-meta.xml', - xmldata: Hidenav, - }); - const ruleConfig = { - rules: - { - CustomNamingConvention: - { - severity: 'error', - path: './src/data/CustomRuleExample.ts' - } - } - }; - - const results: core.ScanResult[] = core.scan([flow2], ruleConfig); - expect(results[0].ruleResults[0].occurs).to.equal(true); - }); - - -}); \ No newline at end of file diff --git a/tests/DMLStatementInLoop.test.ts b/tests/DMLStatementInLoop.test.ts deleted file mode 100644 index 3252e5b..0000000 --- a/tests/DMLStatementInLoop.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src'; -import dmlstatementsinaloop from './testfiles/DMLStatementInALoop_Demo.json'; -import dmlstatementsinaloopfixed from './testfiles/DMLStatementInALoop_Demo_Fixed.json'; - -describe('DMLStatementInLoop ', () => { - let flow: core.Flow; - - it('there should be one result for the rule DMLStatementInLoop', () => { - flow = new core.Flow({ - path: './testfiles/DML_statements_in_a_loop.flow', - xmldata: dmlstatementsinaloop, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults[0].ruleName).to.equal("DMLStatementInLoop"); - }); - - it('there should be no result for the rule DMLStatementInLoop', () => { - flow = new core.Flow({ - path: './testfiles/DML_statements_in_a_loop_fixed.flow', - xmldata: dmlstatementsinaloopfixed, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); - }); -}); \ No newline at end of file diff --git a/tests/DuplicateDMLOperation.test.ts b/tests/DuplicateDMLOperation.test.ts deleted file mode 100644 index d37faaa..0000000 --- a/tests/DuplicateDMLOperation.test.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import CreateANewAccountWithChild from './testfiles/CreateANewAccountWithChild.json'; -import AssignTaskOwner from './testfiles/AssignTaskOwner.json'; -import createANewAccount from './testfiles/CreateANewAccount.json'; -import UnconnectedScreensWithDuplicateDML from './testfiles/UnconnectedScreensWithDuplicateDML.json'; -import CreateANewAccountImproved from './testfiles/CreateANewAccountImproved.json'; -import Hidenav from './testfiles/hidenav.json'; - -describe('DuplicateDMLOperation ', () => { - let flow: core.Flow; - - it('should have 1 result in a flow with a DML statement inbetween screens ', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: createANewAccount, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: { - severity: 'error', - }, - }, - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - expect(results[0].ruleResults[0].details.length).to.equal(1); - }); - - it('should have 2 results in a flow with 2 DML statements inbetween screens', () => { - flow = new core.Flow({ - path: './testfiles/CreateANewAccountWithChild.flow-meta.xml', - xmldata: CreateANewAccountWithChild, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: { - severity: 'error', - }, - }, - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - expect(results[0].ruleResults[0].details.length).to.equal(2); - }); - - it('should have 1 result when 1 is specied as exception in a flow with 2 DML statements inbetween screens', () => { - flow = new core.Flow({ - path: './testfiles/CreateANewAccountWithChild.flow-meta.xml', - xmldata: CreateANewAccountWithChild, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: - { - severity: 'error', - }, - }, - exceptions: - { - CreateANewAccountWithChild: - {"DuplicateDMLOperation":["ViewAccountId"]} - } - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - expect(results[0].ruleResults[0].details.length).to.equal(1); - }); - - it('should have no results when all are specied as exception in a flow with 2 DML statements inbetween screens', () => { - flow = new core.Flow({ - path: './testfiles/CreateANewAccountWithChild.flow-meta.xml', - xmldata: CreateANewAccountWithChild, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: - { - severity: 'error', - }, - FlowDescription: - { - severity: 'error', - } - } - , - exceptions: - { - CreateANewAccountWithChild: - { "DuplicateDMLOperation": ["ViewAccountId", "ViewAccountId_0"] } - } - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - const ruleResult = results[0].ruleResults.find( - (result) => result.ruleName === 'DuplicateDMLOperation' - ); - expect(ruleResult?.occurs).to.be.false; - - const ruleResul2 = results[0].ruleResults.find( - (result) => result.ruleName === 'FlowDescription' - ); - expect(ruleResul2?.occurs).to.be.true; - }); - - it('should have no results in a random flow without screens', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: AssignTaskOwner, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: { - severity: 'error', - }, - }, - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults[0].occurs).to.equal(false); - }); - - it('should have no result in a flow with dmls and unconnected screens', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: UnconnectedScreensWithDuplicateDML, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: { - severity: 'error', - }, - }, - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - expect(results[0].ruleResults[0].details.length).to.equal(0); - }); - - it('should have no result when restrictions to the navigation are implemented', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: CreateANewAccountImproved, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: { - severity: 'error', - }, - }, - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - expect(results[0].ruleResults[0].details.length).to.equal(0); - }); - - it('A screen flow with a DML statements between where the screen after the DML hides the navigation should have no result', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: Hidenav, - }); - const ruleConfig = { - rules: - { - DuplicateDMLOperation: - { - severity: 'error', - }, - } - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('DuplicateDMLOperation'); - }); -}); - diff --git a/tests/FlowDescription.test.ts b/tests/FlowDescription.test.ts index 6c6c271..cf7797d 100644 --- a/tests/FlowDescription.test.ts +++ b/tests/FlowDescription.test.ts @@ -1,18 +1,15 @@ import { assert, expect } from 'chai'; import 'mocha'; import * as core from '../src' -import missingFlowDescription from './testfiles/MissingFlowDescription_Demo.json'; -import CreateANewAccount from './testfiles/CreateANewAccount.json'; - +import * as path from 'path-browserify'; + describe('FlowDescription', () => { - let flow: core.Flow; + let example_uri = path.join(__dirname, './xmlfiles/Missing_Flow_Description.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml'); - it(' should return a result when a flow is missing a description', () => { + it('should return a result when missing a description', async () => { - flow = new core.Flow({ - path: './testfiles/Missing_Flow_Description.flow', - xmldata: missingFlowDescription, - }); + let flows = await core.parse([example_uri]); const ruleConfig = { rules: { @@ -22,17 +19,15 @@ describe('FlowDescription', () => { }, }; - const results: core.ScanResult[] = core.scan([flow]); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); expect(occurringResults.length).to.equal(1); expect(occurringResults[0].ruleName).to.equal("FlowDescription"); }); - it('FlowDescription should have no result', () => { - flow = new core.Flow({ - path: 'anypath', - xmldata: CreateANewAccount, - }); + it('should have no result when provided a description', async () => { + + let flows = await core.parse([fixed_uri]); const ruleConfig = { rules: { @@ -42,7 +37,7 @@ describe('FlowDescription', () => { }, }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('FlowDescription'); diff --git a/tests/FlowName.test.ts b/tests/FlowName.test.ts index ac2807b..56a9f35 100644 --- a/tests/FlowName.test.ts +++ b/tests/FlowName.test.ts @@ -1,19 +1,15 @@ import { assert, expect } from 'chai'; import 'mocha'; import * as core from '../src' -import unconnectedElement from './testfiles/UnconnectedElement.json'; -import Hidenav from './testfiles/hidenav.json'; -import FlowNamingConvention from './testfiles/FlowNamingConvention_Demo.json'; +import * as path from 'path-browserify'; describe('FlowName', () => { - let flow: core.Flow; + let example_uri = path.join(__dirname, './xmlfiles/FlowNamingConvention.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml'); - it('should have no result', () => { + it('should have no result', async () => { - flow = new core.Flow({ - path: './testfiles/Async_OnlyTransaction.flow-meta.xml', - xmldata: unconnectedElement, - }); + let flows = await core.parse([example_uri]); const ruleConfig = { rules: { @@ -25,17 +21,14 @@ describe('FlowName', () => { } }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('FlowName'); expect(results[0].ruleResults[0].occurs).to.equal(false); }); - it('should have no result when defined as exception', () => { - flow = new core.Flow({ - path: './testfiles/AAAA.flow-meta.xml', - xmldata: Hidenav, - }); + it('should have no result when defined as exception', async () => { + let flows = await core.parse([example_uri]); const ruleConfig = { rules: { @@ -48,22 +41,21 @@ describe('FlowName', () => { exceptions: { AAAA: - {"FlowName":["AAAA"]} + {"FlowName":["FlowNamingConvention"]} } }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('FlowName'); expect(results[0].ruleResults[0].occurs).to.equal(false); }); - it('should have a result', () => { - flow = new core.Flow({ - path: './testfiles/FlowNamingConvention.flow', - xmldata: FlowNamingConvention, - }); - const results: core.ScanResult[] = core.scan([flow]); + it('should have a result when provided', async () => { + + let flows = await core.parse([fixed_uri]); + + const results: core.ScanResult[] = core.scan(flows); const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); expect(occurringResults.length).to.equal(1); expect(occurringResults[0].ruleName).to.equal("FlowName"); diff --git a/tests/HardcodedId.test.ts b/tests/HardcodedId.test.ts deleted file mode 100644 index bda21ce..0000000 --- a/tests/HardcodedId.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src'; -import hardcodedids from './testfiles/HardcodedID_Demo.json'; - -describe('In the Hardcoded_Ids flow', () => { - let flow: core.Flow; - - before('arrange', () => { - // ARRANGE - flow = new core.Flow({ - path: './testfiles/Hardcoded_Ids.flow', - xmldata: hardcodedids, - }); - }); - - it('there should be one result for the rule HardcodedIds', () => { - - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults[0].ruleName).to.equal("HardcodedId"); - }); -}); \ No newline at end of file diff --git a/tests/InactiveFlow.test.ts b/tests/InactiveFlow.test.ts deleted file mode 100644 index 9020e0e..0000000 --- a/tests/InactiveFlow.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src'; -import obsolete from './testfiles/ObsoleteFlow_Demo.json'; -import active from './testfiles/ActiveFlow_Demo.json'; - -describe('In the ObsoleteFlow flow', () => { - let obsoleteflow, activeflow: core.Flow; - - before('arrange', () => { - // ARRANGE - obsoleteflow = new core.Flow({ - path: './testfiles/ObsoleteFlow_Demo.flow', - xmldata: obsolete, - }); - activeflow = new core.Flow({ - path: './testfiles/ActiveFlow_Demo.flow', - xmldata: active, - }); - }); - - it('there should be one result for the rule InactiveFlow', () => { - - const results: core.ScanResult[] = core.scan([obsoleteflow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults[0].ruleName).to.equal("InactiveFlow"); - }); - - it('there should be no results for an active flow', () => { - - const results: core.ScanResult[] = core.scan([activeflow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); - }); -}); \ No newline at end of file diff --git a/tests/MissingFaultPath.test.ts b/tests/MissingFaultPath.test.ts deleted file mode 100644 index 199cdc8..0000000 --- a/tests/MissingFaultPath.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src'; -import missingerrorhandler from './testfiles/missingerrorhandler.json'; -import missingerrorhandler_fixed from './testfiles/missingerrorhandler_fixed.json'; - -describe('In the Missing_error_handlers flow', () => { - let flow: core.Flow; - - it('there should be one result for the rule MissingFaultPath', () => { - flow = new core.Flow({ - path: './testfiles/Missing_error_handlers.flow-meta.flow', - xmldata: missingerrorhandler, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults[0].ruleName).to.equal("MissingFaultPath"); - }); - -it('Should have no result', () => { - - flow = new core.Flow({ - path: './testfiles/Missing_Error_Handler_Fixed.flow-meta.flow', - xmldata: missingerrorhandler_fixed, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); -}); - -}); \ No newline at end of file diff --git a/tests/MissingNullHandler.test.ts b/tests/MissingNullHandler.test.ts deleted file mode 100644 index 637038a..0000000 --- a/tests/MissingNullHandler.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import CreateANewAccountWithChildFixed from './testfiles/MissingNullHandler_Fixed.json'; -import CreateANewAccountWithChild from './testfiles/MissingNullHandler.json'; -import cv from './testfiles/cv.json'; -import taskbs from './testfiles/taskbs.json'; - -describe('MissingNullHandler ', () => { - let flow: core.Flow; - - it(' should return a result when null handlers are implemented', () => { - flow = new core.Flow({ - path: './testfiles/tc.flow-meta.xml', - xmldata: CreateANewAccountWithChild, - }); - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'error', - }, - } - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler') - expect(results[0].ruleResults[0].occurs).to.equal(true); - }); - - it(' should return no result when null handlers are implemented', () => { - - flow = new core.Flow({ - path: './testfiles/tc.flow-meta.xml', - xmldata: CreateANewAccountWithChildFixed, - }); - - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'error', - }, - } - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler') - expect(results[0].ruleResults[0].occurs).to.equal(false); - }); - - it('when opt XX ', () => { - flow = new core.Flow({ - path: './testfiles/CreateANewAccountWithChild.flow-meta.xml', - xmldata: cv, - }); - - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'error', - }, - } - }; - - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults.length).to.equal(1); - expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler'); - expect(results[0].ruleResults[0].occurs).to.equal(false); - }); - - it('When scustom variable assignments include null handlers', () => { - - flow = new core.Flow({ - path: './testfiles/CreateANewAccountWithChild.flow-meta.xml', - xmldata: taskbs, - }); - - const ruleConfig = { - rules: - { - MissingNullHandler: - { - severity: 'error', - }, - } - }; - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler') - expect(results[0].ruleResults[0].occurs).to.equal(true); - }); - -}); diff --git a/tests/ParsingTest.test.ts b/tests/ParsingTest.test.ts deleted file mode 100644 index 9f7de25..0000000 --- a/tests/ParsingTest.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' - -describe('Parsing Flows', () => { - let flow: core.Flow; - - it(' should have a result ', async () => { - const flows = await core.parse(['/Users/rubenhalman/Projects/lightning-flow-scanner-core/tests/xmlfiles/Unused_Variable_Fixed.flow-meta.xml']); - - expect(flows[0].name).to.equal("Unused_Variable_Fixed"); - }); - -}); diff --git a/tests/SOQLQueryInLoop.test.ts b/tests/SOQLQueryInLoop.test.ts deleted file mode 100644 index 90dad74..0000000 --- a/tests/SOQLQueryInLoop.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { assert, expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import SOQLQueryInALoop_Demo from './testfiles/SOQLQueryInALoop_Demo.json'; -import SOQLQueryInALoop_Demo_Fixed from './testfiles/SOQLQueryInALoop_Demo_Fixed.json'; - -describe('SOQLQueryInLoop ', () => { - let flow: core.Flow; - - it('there should be one result for the rule SOQLQueryInLoop', () => { - flow = new core.Flow({ - path: './testfiles/SOQL_Query_In_Loop_Demo.flow', - xmldata: SOQLQueryInALoop_Demo, - }); - const results: core.ScanResult[] = core.scan([flow]); - const SOQLQueryInLoop = results[0].ruleResults.find((rule) => rule.occurs && rule.ruleName === 'SOQLQueryInLoop'); - expect(SOQLQueryInLoop?.occurs).to.equal(true); - }); - - it('there should be no result for the rule SOQLQueryInLoop', () => { - - flow = new core.Flow({ - path: './testfiles/SOQLQueryInALoop_Demo_Fixed.flow', - xmldata: SOQLQueryInALoop_Demo_Fixed, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults).not.include("SOQLQueryInLoop"); - }); -}); \ No newline at end of file diff --git a/tests/UnconnectedElement.test.ts b/tests/UnconnectedElement.test.ts deleted file mode 100644 index 659270f..0000000 --- a/tests/UnconnectedElement.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import unconnectedElement from './testfiles/UnconnectedElement.json'; -import asyncAfterCommitOnly from './testfiles/AsyncAfterCommitOnly.json'; -import waitForOnly from './testfiles/WaitForOnly.json'; - - -describe('In the unconnected element flow', () => { - let flow: core.Flow; - - it('there should be consideration for async elements', () => { - flow = new core.Flow({ - path: './testfiles/Async_AfterCommitOnly.flow', - xmldata: asyncAfterCommitOnly, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); - }); - - it('there should consideration for async wait paths', () => { - flow = new core.Flow({ - path: './testfiles/Async_AfterCommitOnly.flow', - xmldata: waitForOnly, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.find((res) => res.ruleName === 'UnconnectedElement')); - }); - - it('there should be checks for unconnected element', () => { - flow = new core.Flow({ - path: './testfiles/Async_AfterCommitOnly.flow', - xmldata: unconnectedElement, - }); - const results: core.ScanResult[] = core.scan([flow]); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.find((res) => res.ruleName === 'UnconnectedElement')); - }); -}); - diff --git a/tests/UnusedVariable.test.ts b/tests/UnusedVariable.test.ts deleted file mode 100644 index 0ac553a..0000000 --- a/tests/UnusedVariable.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { expect } from 'chai'; -import 'mocha'; -import * as core from '../src' -import SendEmailFlow from './testfiles/SendEmailFlow.json'; -import unusedvariable from './testfiles/unusedvariable.json'; - -describe('UnusedVariable Rule', () => { - let flow: core.Flow; - - - it('there should be a result for unused variables', () => { - const ruleConfig = { - rules: - { - UnusedVariable: - { - severity: 'error', - }, - } - }; - flow = new core.Flow({ - path: './testfiles/UnusedVariable.flow', - xmldata: unusedvariable, - }); - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - }); - - it('there should be no result for variables used in text elements', () => { - const ruleConfig = { - rules: - { - UnusedVariable: - { - severity: 'error', - }, - } - }; - flow = new core.Flow({ - path: './testfiles/SendEmailFlow.flow', - xmldata: SendEmailFlow, - }); - const results: core.ScanResult[] = core.scan([flow], ruleConfig); - const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(0); - }); - -}); - From 585f0a801162a461a8e74d110a48541d882865aa Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 15:18:01 +0200 Subject: [PATCH 04/11] add nametest --- src/main/models/FlowElementConnector.ts | 2 +- src/main/models/FlowNode.ts | 75 +++++++++++++++++-------- tests/FlowName.test.ts | 23 +++++--- 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/main/models/FlowElementConnector.ts b/src/main/models/FlowElementConnector.ts index 31d4284..7a80d60 100644 --- a/src/main/models/FlowElementConnector.ts +++ b/src/main/models/FlowElementConnector.ts @@ -6,7 +6,7 @@ export class FlowElementConnector{ public alias:string; public reference:string; public childName:string; - public childOf:string; + public childOf:boolean; constructor(type:string, element:object, args){ this.type = type; diff --git a/src/main/models/FlowNode.ts b/src/main/models/FlowNode.ts index f7ddee7..a8bc131 100644 --- a/src/main/models/FlowNode.ts +++ b/src/main/models/FlowNode.ts @@ -22,35 +22,61 @@ export class FlowNode extends FlowElement { if (subtype === 'start') { const connectors = []; - connectors.push( - new FlowElementConnector('connector', element.connector, {}) - ); + if(element.connector){ + connectors.push( + new FlowElementConnector('connector', element.connector, {}) + ); + } if (Array.isArray(element.scheduledPaths)) { for (const asyncElement of element?.scheduledPaths) { if (asyncElement.connector) { connectors.push( new FlowElementConnector('connector', asyncElement.connector, { childName: asyncElement?.name ?? 'AsyncAfterCommit', - childOf: 'rules' + childOf: 'scheduledPaths' }) ) } } + } else { + if (element.scheduledPaths) { + connectors.push( + new FlowElementConnector('connector', element.scheduledPaths, { + childName: element.scheduledPaths.name, + childOf: 'scheduledPaths' + }) + ); + } } return connectors; } else if (subtype === 'decisions') { const connectors = []; - connectors.push( - new FlowElementConnector('defaultConnector', element.defaultConnector, {}) - ); - for (const rule of element.rules) { - if (rule.connector) { - connectors.push( - new FlowElementConnector('connector', rule.connector, { - childName: rule.name, - childOf: 'rules' - }) - ); + if(element.defaultConnector){ + connectors.push( + new FlowElementConnector('defaultConnector', element.defaultConnector, {}) + ); + } + if(element.rules){ + if (Array.isArray(element.rules)) { + for (const rule of element.rules) { + if (rule.connector) { + connectors.push( + new FlowElementConnector('connector', rule.connector, { + childName: rule.name, + childOf: 'rules' + }) + ); + } + } + } else { + if (element.rules.connector) { + connectors.push( + new FlowElementConnector('connector', element.rules.connector, { + childName: element.rules.name, + childOf: 'rules' + }) + ); + } } } return connectors; @@ -94,16 +120,19 @@ export class FlowNode extends FlowElement { new FlowElementConnector('faultConnector', element.faultConnector, {}) ); } - for (const waitEvent of element.waitEvents) { - if (waitEvent.connector) { - connectors.push( - new FlowElementConnector('connector', waitEvent.connector, { - childName: waitEvent.name, - childOf: 'rules' - }) - ); + if (Array.isArray(element.waitEvents)) { + for (const waitEvent of element.waitEvents) { + if (waitEvent.connector) { + connectors.push( + new FlowElementConnector('connector', waitEvent.connector, { + childName: waitEvent.name, + childOf: 'waitEvents' + }) + ); + } } } + return connectors; } else if (subtype === 'recordCreates') { const connectors = []; diff --git a/tests/FlowName.test.ts b/tests/FlowName.test.ts index 56a9f35..bcf87a4 100644 --- a/tests/FlowName.test.ts +++ b/tests/FlowName.test.ts @@ -7,7 +7,7 @@ describe('FlowName', () => { let example_uri = path.join(__dirname, './xmlfiles/FlowNamingConvention.flow-meta.xml'); let fixed_uri = path.join(__dirname, './xmlfiles/Flow_Naming_Convention_Fixed.flow-meta.xml'); - it('should have no result', async () => { + it('should have a result when not in line with conventions', async () => { let flows = await core.parse([example_uri]); const ruleConfig = { @@ -24,7 +24,7 @@ describe('FlowName', () => { const results: core.ScanResult[] = core.scan(flows, ruleConfig); expect(results[0].ruleResults.length).to.equal(1); expect(results[0].ruleResults[0].ruleName).to.equal('FlowName'); - expect(results[0].ruleResults[0].occurs).to.equal(false); + expect(results[0].ruleResults[0].occurs).to.equal(true); }); it('should have no result when defined as exception', async () => { @@ -40,7 +40,7 @@ describe('FlowName', () => { }, exceptions: { - AAAA: + FlowNamingConvention: {"FlowName":["FlowNamingConvention"]} } }; @@ -51,13 +51,22 @@ describe('FlowName', () => { expect(results[0].ruleResults[0].occurs).to.equal(false); }); - it('should have a result when provided', async () => { + it('should not have a result when in line with conventions', async () => { let flows = await core.parse([fixed_uri]); + const ruleConfig = { + rules: + { + FlowName: + { + severity: 'error', + expression: '[A-Za-z0-9]+_[A-Za-z0-9]+' + }, + } + }; - const results: core.ScanResult[] = core.scan(flows); + const results: core.ScanResult[] = core.scan(flows, ruleConfig); const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); - expect(occurringResults.length).to.equal(1); - expect(occurringResults[0].ruleName).to.equal("FlowName"); + expect(occurringResults.length).to.equal(0); }); }); From 1d9ed2680f09b1b18bb6a9a3aaaa4da95224641d Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 15:52:42 +0200 Subject: [PATCH 05/11] add inactiveFlow --- .DS_Store | Bin 8196 -> 8196 bytes src/main/models/Flow.ts | 6 +- tests/InactiveFlow.test.ts | 46 + tests/testfiles/.DS_Store | Bin 6148 -> 0 bytes tests/testfiles/ActiveFlow_Demo.json | 66 - tests/testfiles/AssignTaskOwner.json | 266 ---- tests/testfiles/AsyncAfterCommitOnly.json | 58 - tests/testfiles/CopyOfAPIName_Demo.json | 1 - tests/testfiles/CreateANewAccount.json | 1 - .../testfiles/CreateANewAccountImproved.json | 281 ---- .../testfiles/CreateANewAccountWithChild.json | 447 ------ .../testfiles/CreateANewAccountWithCopy.json | 447 ------ tests/testfiles/CreateNewCase.json | 1 - tests/testfiles/CreateNewTask.json | 1 - tests/testfiles/DMLStatementInALoop_Demo.json | 267 ---- .../DMLStatementInALoop_Demo_Fixed.json | 357 ----- .../testfiles/DuplicateDMLOperation_Demo.json | 1 - .../testfiles/FlowNamingConvention_Demo.json | 154 --- tests/testfiles/GetAccounts.json | 1 - tests/testfiles/HardcodedID_Demo.json | 205 --- .../MissingFlowDescription_Demo.json | 139 -- tests/testfiles/MissingNullHandler.json | 1 - tests/testfiles/MissingNullHandler_Fixed.json | 218 --- tests/testfiles/ObsoleteFlow_Demo.json | 66 - tests/testfiles/SOQLQueryInALoop_Demo.json | 299 ----- .../SOQLQueryInALoop_Demo_Fixed.json | 282 ---- tests/testfiles/SendEmailFlow.json | 184 --- tests/testfiles/UnconnectedElement.json | 66 - .../UnconnectedScreensWithDuplicateDML.json | 1 - tests/testfiles/WaitForOnly.json | 63 - tests/testfiles/api58test.json | 368 ----- tests/testfiles/cv.json | 1194 ----------------- tests/testfiles/flawedflow.json | 7 - tests/testfiles/hidenav.json | 261 ---- tests/testfiles/missingerrorhandler.json | 114 -- .../testfiles/missingerrorhandler_fixed.json | 164 --- tests/testfiles/taskbs.json | 1002 -------------- tests/testfiles/unusedvariable.json | 57 - tests/testfiles/unusedvariablefixed.json | 47 - .../Utility_Copy_Files_Subflow.flow-meta.xml | 294 ++++ 40 files changed, 343 insertions(+), 7090 deletions(-) create mode 100644 tests/InactiveFlow.test.ts delete mode 100644 tests/testfiles/.DS_Store delete mode 100644 tests/testfiles/ActiveFlow_Demo.json delete mode 100644 tests/testfiles/AssignTaskOwner.json delete mode 100644 tests/testfiles/AsyncAfterCommitOnly.json delete mode 100644 tests/testfiles/CopyOfAPIName_Demo.json delete mode 100644 tests/testfiles/CreateANewAccount.json delete mode 100644 tests/testfiles/CreateANewAccountImproved.json delete mode 100644 tests/testfiles/CreateANewAccountWithChild.json delete mode 100644 tests/testfiles/CreateANewAccountWithCopy.json delete mode 100644 tests/testfiles/CreateNewCase.json delete mode 100644 tests/testfiles/CreateNewTask.json delete mode 100644 tests/testfiles/DMLStatementInALoop_Demo.json delete mode 100644 tests/testfiles/DMLStatementInALoop_Demo_Fixed.json delete mode 100644 tests/testfiles/DuplicateDMLOperation_Demo.json delete mode 100644 tests/testfiles/FlowNamingConvention_Demo.json delete mode 100644 tests/testfiles/GetAccounts.json delete mode 100644 tests/testfiles/HardcodedID_Demo.json delete mode 100644 tests/testfiles/MissingFlowDescription_Demo.json delete mode 100644 tests/testfiles/MissingNullHandler.json delete mode 100644 tests/testfiles/MissingNullHandler_Fixed.json delete mode 100644 tests/testfiles/ObsoleteFlow_Demo.json delete mode 100644 tests/testfiles/SOQLQueryInALoop_Demo.json delete mode 100644 tests/testfiles/SOQLQueryInALoop_Demo_Fixed.json delete mode 100644 tests/testfiles/SendEmailFlow.json delete mode 100644 tests/testfiles/UnconnectedElement.json delete mode 100644 tests/testfiles/UnconnectedScreensWithDuplicateDML.json delete mode 100644 tests/testfiles/WaitForOnly.json delete mode 100644 tests/testfiles/api58test.json delete mode 100644 tests/testfiles/cv.json delete mode 100644 tests/testfiles/flawedflow.json delete mode 100644 tests/testfiles/hidenav.json delete mode 100644 tests/testfiles/missingerrorhandler.json delete mode 100644 tests/testfiles/missingerrorhandler_fixed.json delete mode 100644 tests/testfiles/taskbs.json delete mode 100644 tests/testfiles/unusedvariable.json delete mode 100644 tests/testfiles/unusedvariablefixed.json create mode 100644 tests/xmlfiles/Utility_Copy_Files_Subflow.flow-meta.xml diff --git a/.DS_Store b/.DS_Store index c62731e02efece879ae1b047e8d851dc5b158620..ac8ed64c88bd6d08b9e9ec73a8f136ce21095ad4 100644 GIT binary patch delta 72 zcmZp1XmQw}D!{mXvYJ4lns{}!iHWg}g1JepjzYDik%5kaiLqI2EhmSlvc7dte0EN5 cUVi7~{Q~lgU7PO3dl3|Y`!a?!M>SY;ycUc IKO$_*0IE_DSpWb4 diff --git a/src/main/models/Flow.ts b/src/main/models/Flow.ts index cb3f365..8842d32 100644 --- a/src/main/models/Flow.ts +++ b/src/main/models/Flow.ts @@ -102,7 +102,7 @@ export class Flow { if (this.flowMetadata.includes(nodeType)) { if (Array.isArray(data)) { for (const node of data) { - allNodes.push(new FlowMetadata(nodeType, data[node])); + allNodes.push(new FlowMetadata(nodeType, node)); } for (const node of data) { } @@ -113,7 +113,7 @@ export class Flow { if (Array.isArray(data)) { for (const node of data) { allNodes.push( - new FlowVariable(data[node].name, nodeType, data[node]) + new FlowVariable(node.name, nodeType, node) ); } } else { @@ -131,7 +131,7 @@ export class Flow { if (Array.isArray(data)) { for (const node of data) { allNodes.push( - new FlowResource(data[node].name, nodeType, data[node]) + new FlowResource(node.name, nodeType, node) ); } } else { diff --git a/tests/InactiveFlow.test.ts b/tests/InactiveFlow.test.ts new file mode 100644 index 0000000..9da69ef --- /dev/null +++ b/tests/InactiveFlow.test.ts @@ -0,0 +1,46 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src' +import * as path from 'path-browserify'; + +describe('InactiveFlow', () => { + let example_uri = path.join(__dirname, './xmlfiles/Utility_Copy_Files_Subflow.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Missing_Flow_Description_Fixed.flow-meta.xml'); + + it('should return a result when flow is inactive', async () => { + + let flows = await core.parse([example_uri]); + const ruleConfig = { + rules: + { + InactiveFlow: { + severity: 'error', + }, + }, + }; + + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(1); + expect(occurringResults[0].ruleName).to.equal("InactiveFlow"); + }); + + it('should have no result when flow is active', async () => { + + let flows = await core.parse([fixed_uri]); + const ruleConfig = { + rules: + { + FlowDescription: { + severity: 'error', + }, + }, + }; + + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + + expect(results[0].ruleResults.length).to.equal(1); + expect(results[0].ruleResults[0].ruleName).to.equal('FlowDescription'); + expect(results[0].ruleResults[0].occurs).to.equal(false); + }); +}); diff --git a/tests/testfiles/.DS_Store b/tests/testfiles/.DS_Store deleted file mode 100644 index 38b9e163e51927a27920e89089f74d90ec057122..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%Sr<=6g|-{iZ6thC6t!?SFx*gp51^$35!SC>o zbfxDeQKr+5bR|-9OLFqMC&@`BX#l8FKiC8c0P+lixfwovu- zHU?J}x14jA+;{9L$l_M3Dem<#xKF7@4|TSzGu8Zs{V~P9IKXZ+C~Hl_%n^Q!!STH= z846Bar8o-Mqbj|W{!!K#^lH8&R&!3zJRnDlqrc1Y)9OAa{N{iBWNpG{!createAccount.Name}

"],"fieldType":["DisplayText"]}],"showFooter":["true"],"showHeader":["true"]}],"start":[{"locationX":["50"],"locationY":["50"],"connector":[{"targetReference":["NameNewAccount"]}]}],"status":["Active"],"variables":[{"name":["createAccount"],"dataType":["SObject"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"objectType":["Account"]}]}} \ No newline at end of file diff --git a/tests/testfiles/CreateANewAccountImproved.json b/tests/testfiles/CreateANewAccountImproved.json deleted file mode 100644 index a04fdca..0000000 --- a/tests/testfiles/CreateANewAccountImproved.json +++ /dev/null @@ -1,281 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "assignments": [ - { - "name": [ - "NewAccountName" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "428" - ], - "locationY": [ - "193" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord" - ] - } - ] - } - ], - "interviewLabel": [ - "CreateANewAccountImproved {!$Flow.CurrentDateTime}" - ], - "label": [ - "CreateANewAccountImproved" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "FREE_FORM_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordCreates": [ - { - "name": [ - "createAccountRecord" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "449" - ], - "locationY": [ - "463" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId" - ] - } - ], - "inputReference": [ - "createAccount" - ] - } - ], - "screens": [ - { - "name": [ - "NameNewAccount" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "178" - ], - "locationY": [ - "214" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "172" - ], - "locationY": [ - "454" - ], - "allowBack": [ - "false" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "fields": [ - { - "name": [ - "AccountNameDisplay" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "50" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "createAccount" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "createAccount2" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/CreateANewAccountWithChild.json b/tests/testfiles/CreateANewAccountWithChild.json deleted file mode 100644 index 87db9d6..0000000 --- a/tests/testfiles/CreateANewAccountWithChild.json +++ /dev/null @@ -1,447 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "assignments": [ - { - "name": [ - "NewAccountName" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "428" - ], - "locationY": [ - "192" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord" - ] - } - ] - }, - { - "name": [ - "NewAccountName_0" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "420" - ], - "locationY": [ - "677" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord_0" - ] - } - ] - } - ], - "interviewLabel": [ - "CreateANewAccountWithChild {!$Flow.CurrentDateTime}" - ], - "label": [ - "CreateANewAccountWithChild" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "FREE_FORM_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordCreates": [ - { - "name": [ - "createAccountRecord" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "449" - ], - "locationY": [ - "462" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId" - ] - } - ], - "inputReference": [ - "createAccount" - ] - }, - { - "name": [ - "createAccountRecord_0" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "441" - ], - "locationY": [ - "947" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId_0" - ] - } - ], - "inputReference": [ - "createAccount" - ] - } - ], - "screens": [ - { - "name": [ - "NameNewAccount" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "177" - ], - "locationY": [ - "213" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "NameNewAccount_0" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "169" - ], - "locationY": [ - "698" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName_0" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name_0" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "172" - ], - "locationY": [ - "453" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount_0" - ] - } - ], - "fields": [ - { - "name": [ - "AccountNameDisplay" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId_0" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "164" - ], - "locationY": [ - "938" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "fields": [ - { - "name": [ - "AccountNameDisplay_0" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "50" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "createAccount" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "createAccount2" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/CreateANewAccountWithCopy.json b/tests/testfiles/CreateANewAccountWithCopy.json deleted file mode 100644 index 0b6b60f..0000000 --- a/tests/testfiles/CreateANewAccountWithCopy.json +++ /dev/null @@ -1,447 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "assignments": [ - { - "name": [ - "NewAccountName" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "428" - ], - "locationY": [ - "192" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord" - ] - } - ] - }, - { - "name": [ - "NewAccountName_0" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "420" - ], - "locationY": [ - "677" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord_0" - ] - } - ] - } - ], - "interviewLabel": [ - "CreateANewAccountWithChild {!$Flow.CurrentDateTime}" - ], - "label": [ - "CreateANewAccountWithChild" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "FREE_FORM_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordCreates": [ - { - "name": [ - "createAccountRecord" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "449" - ], - "locationY": [ - "462" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId" - ] - } - ], - "inputReference": [ - "createAccount" - ] - }, - { - "name": [ - "createAccountRecord_0" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "441" - ], - "locationY": [ - "947" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId_0" - ] - } - ], - "inputReference": [ - "createAccount" - ] - } - ], - "screens": [ - { - "name": [ - "NameNewAccount" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "177" - ], - "locationY": [ - "213" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "Copy_2_of_NameNewAccount" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "169" - ], - "locationY": [ - "698" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName_0" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name_0" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "172" - ], - "locationY": [ - "453" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount_0" - ] - } - ], - "fields": [ - { - "name": [ - "AccountNameDisplay" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId_0" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "164" - ], - "locationY": [ - "938" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "fields": [ - { - "name": [ - "AccountNameDisplay_0" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "50" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "createAccount" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "createAccount2" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/CreateNewCase.json b/tests/testfiles/CreateNewCase.json deleted file mode 100644 index 7761f33..0000000 --- a/tests/testfiles/CreateNewCase.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"actionCalls":[{"name":["LogCall"],"label":["LogCall"],"locationX":["546"],"locationY":["188"],"actionName":["Case.LogACall"],"actionType":["quickAction"],"inputParameters":[{"name":["contextId"],"value":[{"elementReference":["UserID"]}]}]}],"assignments":[{"name":["AssignCaseDescription"],"label":["AssignCaseDescription"],"locationX":["341"],"locationY":["295"],"assignmentItems":[{"assignToReference":["Case.Description"],"operator":["Assign"],"value":[{"elementReference":["UserID"]}]}]}],"description":["An example flow that creates a new case, demonstrating the rule Unconnected elements"],"interviewLabel":["CreateNewCase {!$Flow.CurrentDateTime}"],"label":["CreateNewCase"],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["FREE_FORM_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["AutoLaunchedFlow"],"start":[{"locationX":["50"],"locationY":["50"],"connector":[{"targetReference":["LogCall"]}]}],"status":["Active"],"variables":[{"name":["Case"],"dataType":["SObject"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"objectType":["Case"]},{"name":["UserID"],"dataType":["String"],"isCollection":["false"],"isInput":["true"],"isOutput":["false"]}]}} \ No newline at end of file diff --git a/tests/testfiles/CreateNewTask.json b/tests/testfiles/CreateNewTask.json deleted file mode 100644 index 07e8e3a..0000000 --- a/tests/testfiles/CreateNewTask.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"actionCalls":[{"name":["NewTask"],"label":["NewTask"],"locationX":["190"],"locationY":["204"],"actionName":["NewTask"],"actionType":["quickAction"],"inputParameters":[{"name":["OwnerId"],"value":[{"elementReference":["UserID"]}]}]}],"constants":[{"name":["User_ID"],"dataType":["String"]}],"description":["Example flow creating a new task demonstrating the rule Unused Variables"],"interviewLabel":["CreateNewTask {!$Flow.CurrentDateTime}"],"label":["CreateNewTask"],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["FREE_FORM_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["AutoLaunchedFlow"],"start":[{"locationX":["50"],"locationY":["50"],"connector":[{"targetReference":["NewTask"]}]}],"status":["Active"],"variables":[{"name":["UserID"],"dataType":["String"],"isCollection":["false"],"isInput":["true"],"isOutput":["false"]}]}} \ No newline at end of file diff --git a/tests/testfiles/DMLStatementInALoop_Demo.json b/tests/testfiles/DMLStatementInALoop_Demo.json deleted file mode 100644 index 3f00b8d..0000000 --- a/tests/testfiles/DMLStatementInALoop_Demo.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "description": [ - "a Case failed to create automatically. Please examine its details manually." - ], - "name": [ - "create_case_manually" - ], - "label": [ - "create case manually" - ], - "locationX": [ - "528" - ], - "locationY": [ - "350" - ], - "actionName": [ - "FeedItem.NewTaskFromFeedItem" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "inputParameters": [ - { - "name": [ - "contextId" - ], - "value": [ - { - "elementReference": [ - "createCase.OwnerId" - ] - } - ] - } - ], - "nameSegment": [ - "FeedItem.NewTaskFromFeedItem" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "description": [ - "This flow demonstrates a violation of the rule \"DML statements in a loop\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "DML statements in a loop {!$Flow.CurrentDateTime}" - ], - "label": [ - "DML statements in a loop" - ], - "loops": [ - { - "description": [ - "an example loop" - ], - "name": [ - "aLoop" - ], - "label": [ - "aLoop" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "collectionReference": [ - "Accounts" - ], - "iterationOrder": [ - "Asc" - ], - "nextValueConnector": [ - { - "targetReference": [ - "createNewCase" - ] - } - ] - } - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordCreates": [ - { - "description": [ - "creates a new case" - ], - "name": [ - "createNewCase" - ], - "label": [ - "createNewCase" - ], - "locationX": [ - "264" - ], - "locationY": [ - "242" - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ], - "faultConnector": [ - { - "targetReference": [ - "create_case_manually" - ] - } - ], - "inputReference": [ - "createCase" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "description": [ - "A collection of Accounts" - ], - "name": [ - "Accounts" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "true" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "createCase" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Case" - ] - }, - { - "description": [ - "a task" - ], - "name": [ - "task" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Task" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/DMLStatementInALoop_Demo_Fixed.json b/tests/testfiles/DMLStatementInALoop_Demo_Fixed.json deleted file mode 100644 index 30aa649..0000000 --- a/tests/testfiles/DMLStatementInALoop_Demo_Fixed.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "create_case_manually" - ], - "label": [ - "create case manually" - ], - "locationX": [ - "440" - ], - "locationY": [ - "542" - ], - "actionName": [ - "FeedItem.NewTaskFromFeedItem" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "inputParameters": [ - { - "name": [ - "contextId" - ], - "value": [ - { - "elementReference": [ - "aLoop.Id" - ] - } - ] - } - ], - "nameSegment": [ - "FeedItem.NewTaskFromFeedItem" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "assignments": [ - { - "description": [ - "Assigns values to newCase variable." - ], - "name": [ - "createNewCaseAssignment" - ], - "label": [ - "createNewCaseAssignment" - ], - "locationX": [ - "264" - ], - "locationY": [ - "242" - ], - "assignmentItems": [ - { - "assignToReference": [ - "newCase.AccountId" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "aLoop.Id" - ] - } - ] - }, - { - "assignToReference": [ - "newCase.OwnerId" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "aLoop.OwnerId" - ] - } - ] - }, - { - "assignToReference": [ - "newCases" - ], - "operator": [ - "Add" - ], - "value": [ - { - "elementReference": [ - "newCase" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ] - } - ], - "description": [ - "This flow demonstrates how to resolve a violation of the rule \"DML Statement In A Loop\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "DML Statement In A Loop Fixed {!$Flow.CurrentDateTime}" - ], - "label": [ - "Fix: DML Statement In A Loop" - ], - "loops": [ - { - "description": [ - "an example loop" - ], - "name": [ - "aLoop" - ], - "label": [ - "aLoop" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "collectionReference": [ - "Accounts" - ], - "iterationOrder": [ - "Asc" - ], - "nextValueConnector": [ - { - "targetReference": [ - "createNewCaseAssignment" - ] - } - ], - "noMoreValuesConnector": [ - { - "targetReference": [ - "insert_cases" - ] - } - ] - } - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordCreates": [ - { - "name": [ - "insert_cases" - ], - "label": [ - "insert cases" - ], - "locationX": [ - "176" - ], - "locationY": [ - "434" - ], - "faultConnector": [ - { - "targetReference": [ - "create_case_manually" - ] - } - ], - "inputReference": [ - "newCases" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "description": [ - "A collection of Accounts" - ], - "name": [ - "Accounts" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "true" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "newCase" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Case" - ] - }, - { - "description": [ - "Collection of New Cases" - ], - "name": [ - "newCases" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Case" - ] - }, - { - "description": [ - "a task" - ], - "name": [ - "task" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Task" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/DuplicateDMLOperation_Demo.json b/tests/testfiles/DuplicateDMLOperation_Demo.json deleted file mode 100644 index ea6fae0..0000000 --- a/tests/testfiles/DuplicateDMLOperation_Demo.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"actionCalls":[{"name":["create_account_manually"],"label":["create account manually"],"locationX":["440"],"locationY":["350"],"actionName":["FeedItem.NewTaskFromFeedItem"],"actionType":["quickAction"],"flowTransactionModel":["CurrentTransaction"],"inputParameters":[{"name":["contextId"],"value":[{"elementReference":["$User.Id"]}]}],"nameSegment":["FeedItem.NewTaskFromFeedItem"],"versionSegment":["1"]}],"apiVersion":["58.0"],"description":["This flow demonstrates a violation of the rule \"Duplicate DML operations\"."],"environments":["Default"],"interviewLabel":["Duplicate DML operations {!$Flow.CurrentDateTime}"],"label":["Duplicate DML operations"],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["AUTO_LAYOUT_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["Flow"],"recordCreates":[{"name":["createAccount"],"label":["createAccount"],"locationX":["176"],"locationY":["242"],"connector":[{"targetReference":["mock_screen_2"]}],"faultConnector":[{"targetReference":["create_account_manually"]}],"inputAssignments":[{"field":["Name"],"value":[{"elementReference":["account_name"]}]}],"object":["Account"],"storeOutputAutomatically":["true"]}],"screens":[{"name":["mock_screen_1"],"label":["mock screen 1"],"locationX":["176"],"locationY":["134"],"allowBack":["true"],"allowFinish":["true"],"allowPause":["true"],"connector":[{"targetReference":["createAccount"]}],"fields":[{"name":["account_name"],"dataType":["String"],"fieldText":["account name"],"fieldType":["InputField"],"isRequired":["false"]}],"showFooter":["true"],"showHeader":["true"]},{"name":["mock_screen_2"],"label":["mock screen 2"],"locationX":["176"],"locationY":["350"],"allowBack":["true"],"allowFinish":["true"],"allowPause":["true"],"showFooter":["true"],"showHeader":["true"]}],"start":[{"locationX":["50"],"locationY":["0"],"connector":[{"targetReference":["mock_screen_1"]}]}],"status":["Active"],"variables":[{"name":["Account"],"dataType":["SObject"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"objectType":["Account"]}]}} \ No newline at end of file diff --git a/tests/testfiles/FlowNamingConvention_Demo.json b/tests/testfiles/FlowNamingConvention_Demo.json deleted file mode 100644 index 01c823c..0000000 --- a/tests/testfiles/FlowNamingConvention_Demo.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "58.0" - ], - "decisions": [ - { - "name": [ - "isAccountsProvided" - ], - "label": [ - "isAccountsProvided" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "NotNull" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "Accounts" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "label": [ - "NotNull" - ] - } - ] - } - ], - "description": [ - "This flow demonstrates a violation of the rule \"Flow naming conventions\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Flow naming conventions {!$Flow.CurrentDateTime}" - ], - "label": [ - "Flow naming conventions" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "isAccountsProvided" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "Accounts" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/GetAccounts.json b/tests/testfiles/GetAccounts.json deleted file mode 100644 index 5ce4735..0000000 --- a/tests/testfiles/GetAccounts.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"description":["An example flow that creates a new account based in a loop, demonstrating the rules: DML statements in a loop,\nMissing error handlers and Missing null handlers."],"interviewLabel":["GetAccounts {!$Flow.CurrentDateTime}"],"label":["GetAccounts"],"loops":[{"name":["loopoverints"],"label":["loopoverints"],"locationX":["176"],"locationY":["158"],"collectionReference":["intlist"],"iterationOrder":["Asc"],"nextValueConnector":[{"targetReference":["GetAccounts"]}]}],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["AUTO_LAYOUT_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["AutoLaunchedFlow"],"recordLookups":[{"name":["GetAccounts"],"label":["GetAccounts"],"locationX":["264"],"locationY":["278"],"assignNullValuesIfNoRecordsFound":["false"],"connector":[{"targetReference":["loopoverints"]}],"getFirstRecordOnly":["false"],"object":["Account"],"storeOutputAutomatically":["true"]}],"start":[{"locationX":["50"],"locationY":["0"],"connector":[{"targetReference":["loopoverints"]}]}],"status":["Active"],"variables":[{"name":["incvar"],"dataType":["Number"],"isCollection":["false"],"isInput":["true"],"isOutput":["false"],"scale":["2"],"value":[{"numberValue":["10.0"]}]},{"name":["int"],"dataType":["Number"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"scale":["2"]},{"name":["intlist"],"dataType":["Number"],"isCollection":["true"],"isInput":["false"],"isOutput":["false"],"scale":["2"]},{"name":["somecount"],"dataType":["Number"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"scale":["2"],"value":[{"numberValue":["0.0"]}]}]}} \ No newline at end of file diff --git a/tests/testfiles/HardcodedID_Demo.json b/tests/testfiles/HardcodedID_Demo.json deleted file mode 100644 index c29dc35..0000000 --- a/tests/testfiles/HardcodedID_Demo.json +++ /dev/null @@ -1,205 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "create_account_manually" - ], - "label": [ - "create account manually" - ], - "locationX": [ - "440" - ], - "locationY": [ - "242" - ], - "actionName": [ - "FeedItem.NewTaskFromFeedItem" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "inputParameters": [ - { - "name": [ - "contextId" - ], - "value": [ - { - "elementReference": [ - "$User.Id" - ] - } - ] - } - ], - "nameSegment": [ - "FeedItem.NewTaskFromFeedItem" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "description": [ - "This flow demonstrates a violation of the rule \"Hardcoded Ids\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Hardcoded Ids {!$Flow.CurrentDateTime}" - ], - "label": [ - "Hardcoded Ids" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordCreates": [ - { - "name": [ - "create_Test_Account" - ], - "label": [ - "create Test Account" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "faultConnector": [ - { - "targetReference": [ - "create_account_manually" - ] - } - ], - "inputAssignments": [ - { - "field": [ - "Name" - ], - "value": [ - { - "stringValue": [ - "Test Account" - ] - } - ] - }, - { - "field": [ - "OwnerId" - ], - "value": [ - { - "stringValue": [ - "005Dn000006GuG4IAK" - ] - } - ] - } - ], - "object": [ - "Account" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "create_Test_Account" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "Account" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/MissingFlowDescription_Demo.json b/tests/testfiles/MissingFlowDescription_Demo.json deleted file mode 100644 index 3edda97..0000000 --- a/tests/testfiles/MissingFlowDescription_Demo.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "58.0" - ], - "assignments": [ - { - "name": [ - "do_Anything" - ], - "label": [ - "do Anything" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "assignmentItems": [ - { - "assignToReference": [ - "text" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "stringValue": [ - "new text" - ] - } - ] - } - ] - } - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Missing flow description {!$Flow.CurrentDateTime}" - ], - "label": [ - "Missing flow description" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "do_Anything" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "text" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "value": [ - { - "stringValue": [ - "any text" - ] - } - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/MissingNullHandler.json b/tests/testfiles/MissingNullHandler.json deleted file mode 100644 index ee1a788..0000000 --- a/tests/testfiles/MissingNullHandler.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"assignments":[{"name":["Assign_New_Account_Name"],"label":["Assign New Account Name"],"locationX":["176"],"locationY":["242"],"assignmentItems":[{"assignToReference":["GetAnAccount.Name"],"operator":["Assign"],"value":[{"stringValue":["Test"]}]}]}],"description":["A flow demonstrating a violation of the rule 'MissingNullHandler'."],"interviewLabel":["MissingNullHandler {!$Flow.CurrentDateTime}"],"label":["MissingNullHandler"],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["AUTO_LAYOUT_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["AutoLaunchedFlow"],"recordLookups":[{"name":["GetAnAccount"],"label":["GetAnAccount"],"locationX":["176"],"locationY":["134"],"assignNullValuesIfNoRecordsFound":["false"],"connector":[{"targetReference":["Assign_New_Account_Name"]}],"filters":[{"field":["Name"],"operator":["EqualTo"],"value":[{"stringValue":["Acme"]}]}],"getFirstRecordOnly":["true"],"object":["Account"],"storeOutputAutomatically":["true"]}],"start":[{"locationX":["50"],"locationY":["0"],"connector":[{"targetReference":["GetAnAccount"]}]}],"status":["Active"]}} \ No newline at end of file diff --git a/tests/testfiles/MissingNullHandler_Fixed.json b/tests/testfiles/MissingNullHandler_Fixed.json deleted file mode 100644 index 52e232c..0000000 --- a/tests/testfiles/MissingNullHandler_Fixed.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "assignments": [ - { - "name": [ - "Assign_New_Account_Name" - ], - "label": [ - "Assign New Account Name" - ], - "locationX": [ - "50" - ], - "locationY": [ - "350" - ], - "assignmentItems": [ - { - "assignToReference": [ - "GetAnAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "stringValue": [ - "Test" - ] - } - ] - } - ] - } - ], - "decisions": [ - { - "name": [ - "ifAccountNotNull" - ], - "label": [ - "ifAccountNotNull" - ], - "locationX": [ - "182" - ], - "locationY": [ - "242" - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "notnull" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "GetAnAccount" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_New_Account_Name" - ] - } - ], - "label": [ - "notnull" - ] - } - ] - } - ], - "description": [ - "A flow demonstrating how to fix the violation of the rule 'MissingNullHandler'." - ], - "interviewLabel": [ - "MissingNullHandler_Fixed {!$Flow.CurrentDateTime}" - ], - "label": [ - "MissingNullHandler_Fixed" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordLookups": [ - { - "name": [ - "GetAnAccount" - ], - "label": [ - "GetAnAccount" - ], - "locationX": [ - "182" - ], - "locationY": [ - "134" - ], - "assignNullValuesIfNoRecordsFound": [ - "false" - ], - "connector": [ - { - "targetReference": [ - "ifAccountNotNull" - ] - } - ], - "filters": [ - { - "field": [ - "Name" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "stringValue": [ - "Acme" - ] - } - ] - } - ], - "getFirstRecordOnly": [ - "true" - ], - "object": [ - "Account" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "56" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "GetAnAccount" - ] - } - ] - } - ], - "status": [ - "Active" - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/ObsoleteFlow_Demo.json b/tests/testfiles/ObsoleteFlow_Demo.json deleted file mode 100644 index e386c75..0000000 --- a/tests/testfiles/ObsoleteFlow_Demo.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "58.0" - ], - "description": [ - "This flow demonstrates a violation of the rule \"Inactive Flow\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Obsolete Flow {!$Flow.CurrentDateTime}" - ], - "label": [ - "Obsolete Flow" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "status": [ - "Obsolete" - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/SOQLQueryInALoop_Demo.json b/tests/testfiles/SOQLQueryInALoop_Demo.json deleted file mode 100644 index d38f0aa..0000000 --- a/tests/testfiles/SOQLQueryInALoop_Demo.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "dosomethingelse" - ], - "label": [ - "dosomethingelse" - ], - "locationX": [ - "704" - ], - "locationY": [ - "350" - ], - "actionName": [ - "NewCase" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "nameSegment": [ - "NewCase" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "decisions": [ - { - "name": [ - "notnull" - ], - "label": [ - "notnull" - ], - "locationX": [ - "352" - ], - "locationY": [ - "350" - ], - "defaultConnector": [ - { - "isGoTo": [ - "true" - ], - "targetReference": [ - "dosomethingelse" - ] - } - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "notnulln" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "SOQL_Query_Example" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ], - "label": [ - "notnull" - ] - } - ] - } - ], - "description": [ - "This flow demonstrates a violation of the rule \"SOQL Query In A Loop\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "SOQL Query In A Loop {!$Flow.CurrentDateTime}" - ], - "label": [ - "SOQL Query In A Loop" - ], - "loops": [ - { - "description": [ - "an example loop" - ], - "name": [ - "aLoop" - ], - "label": [ - "aLoop" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "collectionReference": [ - "Accounts" - ], - "iterationOrder": [ - "Asc" - ], - "nextValueConnector": [ - { - "targetReference": [ - "SOQL_Query_Example" - ] - } - ] - } - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordLookups": [ - { - "name": [ - "SOQL_Query_Example" - ], - "label": [ - "SOQL Query Example" - ], - "locationX": [ - "352" - ], - "locationY": [ - "242" - ], - "assignNullValuesIfNoRecordsFound": [ - "false" - ], - "connector": [ - { - "targetReference": [ - "notnull" - ] - } - ], - "faultConnector": [ - { - "targetReference": [ - "dosomethingelse" - ] - } - ], - "filterLogic": [ - "and" - ], - "filters": [ - { - "field": [ - "Active__c" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "stringValue": [ - "Yes" - ] - } - ] - } - ], - "getFirstRecordOnly": [ - "true" - ], - "object": [ - "Account" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "description": [ - "A collection of Accounts" - ], - "name": [ - "Accounts" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "true" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/SOQLQueryInALoop_Demo_Fixed.json b/tests/testfiles/SOQLQueryInALoop_Demo_Fixed.json deleted file mode 100644 index 8f3e57f..0000000 --- a/tests/testfiles/SOQLQueryInALoop_Demo_Fixed.json +++ /dev/null @@ -1,282 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "dosomethingelse" - ], - "label": [ - "dosomethingelse" - ], - "locationX": [ - "440" - ], - "locationY": [ - "434" - ], - "actionName": [ - "NewCase" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "nameSegment": [ - "NewCase" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "decisions": [ - { - "name": [ - "notnull" - ], - "label": [ - "notnull" - ], - "locationX": [ - "176" - ], - "locationY": [ - "434" - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "notnulln" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "SOQL_Query_Example" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "label": [ - "notnull" - ] - } - ] - } - ], - "description": [ - "This flow demonstrates how to resolve a violation of the rule \"SOQL Query In A Loop\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Fix: SOQL Query In A Loop {!$Flow.CurrentDateTime}" - ], - "label": [ - "Fix: SOQL Query In A Loop" - ], - "loops": [ - { - "description": [ - "an example loop" - ], - "name": [ - "aLoop" - ], - "label": [ - "aLoop" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "collectionReference": [ - "Accounts" - ], - "iterationOrder": [ - "Asc" - ], - "noMoreValuesConnector": [ - { - "targetReference": [ - "SOQL_Query_Example" - ] - } - ] - } - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordLookups": [ - { - "name": [ - "SOQL_Query_Example" - ], - "label": [ - "SOQL Query Example" - ], - "locationX": [ - "176" - ], - "locationY": [ - "326" - ], - "assignNullValuesIfNoRecordsFound": [ - "false" - ], - "connector": [ - { - "targetReference": [ - "notnull" - ] - } - ], - "faultConnector": [ - { - "targetReference": [ - "dosomethingelse" - ] - } - ], - "filterLogic": [ - "and" - ], - "filters": [ - { - "field": [ - "Active__c" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "stringValue": [ - "Yes" - ] - } - ] - } - ], - "getFirstRecordOnly": [ - "true" - ], - "object": [ - "Account" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "aLoop" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "description": [ - "A collection of Accounts" - ], - "name": [ - "Accounts" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "true" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/SendEmailFlow.json b/tests/testfiles/SendEmailFlow.json deleted file mode 100644 index ba030c3..0000000 --- a/tests/testfiles/SendEmailFlow.json +++ /dev/null @@ -1,184 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "Send_Email" - ], - "label": [ - "Send Email" - ], - "locationX": [ - "176" - ], - "locationY": [ - "323" - ], - "actionName": [ - "emailSimple" - ], - "actionType": [ - "emailSimple" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "inputParameters": [ - { - "name": [ - "emailSubject" - ], - "value": [ - { - "stringValue": [ - "My Subject" - ] - } - ] - }, - { - "name": [ - "emailBody" - ], - "value": [ - { - "elementReference": [ - "myTextTemplate" - ] - } - ] - }, - { - "name": [ - "recipientId" - ], - "value": [ - { - "elementReference": [ - "$User.Id" - ] - } - ] - } - ], - "nameSegment": [ - "emailSimple" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "60.0" - ], - "environments": [ - "Default" - ], - "formulas": [ - { - "name": [ - "myFormula" - ], - "dataType": [ - "DateTime" - ], - "expression": [ - "NOW()" - ] - } - ], - "interviewLabel": [ - "SendEmailFlow {!$Flow.CurrentDateTime}" - ], - "label": [ - "SendEmailFlow" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "Send_Email" - ] - } - ], - "object": [ - "Account" - ], - "recordTriggerType": [ - "Create" - ], - "triggerType": [ - "RecordAfterSave" - ] - } - ], - "status": [ - "Draft" - ], - "textTemplates": [ - { - "name": [ - "myTextTemplate" - ], - "isViewedAsPlainText": [ - "false" - ], - "text": [ - "

{!myFormula}

" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/UnconnectedElement.json b/tests/testfiles/UnconnectedElement.json deleted file mode 100644 index 78c479e..0000000 --- a/tests/testfiles/UnconnectedElement.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "Flow": { - "$": { "xmlns": "http://soap.sforce.com/2006/04/metadata" }, - "apiVersion": ["60.0"], - "assignments": [ - { - "name": ["NotAssigned"], - "label": ["Not Assigned"], - "locationX": ["50"], - "locationY": ["276"], - "assignmentItems": [ - { - "assignToReference": ["$Record.Name"], - "operator": ["Assign"], - "value": [{ "stringValue": ["Unassigned"] }] - } - ] - }, - { - "description": ["Default Action for Asynchronous Transaction"], - "name": ["VariableAssignment"], - "label": ["VariableAssignment"], - "locationX": ["314"], - "locationY": ["276"], - "assignmentItems": [ - { - "assignToReference": ["$Record.Name"], - "operator": ["Assign"], - "value": [{ "stringValue": ["Test"] }] - } - ] - } - ], - "description": ["AsyncOnlyAutomation"], - "environments": ["Default"], - "interviewLabel": ["AsyncOnlyTransaction {!$Flow.CurrentDateTime}"], - "label": ["Async_OnlyTransaction"], - "processMetadataValues": [ - { - "name": ["BuilderType"], - "value": [{ "stringValue": ["LightningFlowBuilder"] }] - }, - { - "name": ["CanvasMode"], - "value": [{ "stringValue": ["AUTO_LAYOUT_CANVAS"] }] - }, - { - "name": ["OriginBuilderType"], - "value": [{ "stringValue": ["LightningFlowBuilder"] }] - } - ], - "processType": ["AutoLaunchedFlow"], - "start": [ - { - "locationX": ["56"], - "locationY": ["0"], - "object": ["Account"], - "connector": [{ "targetReference": ["VariableAssignment"] }], - "recordTriggerType": ["Create"], - "triggerType": ["RecordAfterSave"] - } - ], - "status": ["Active"] - } - } - \ No newline at end of file diff --git a/tests/testfiles/UnconnectedScreensWithDuplicateDML.json b/tests/testfiles/UnconnectedScreensWithDuplicateDML.json deleted file mode 100644 index 5b1164e..0000000 --- a/tests/testfiles/UnconnectedScreensWithDuplicateDML.json +++ /dev/null @@ -1 +0,0 @@ -{"Flow":{"$":{"xmlns":"http://soap.sforce.com/2006/04/metadata"},"assignments":[{"name":["fillerAssignment"],"label":["fillerAssignment"],"locationX":["461"],"locationY":["53"],"assignmentItems":[{"assignToReference":["createAccount.Name"],"operator":["Assign"],"value":[{"stringValue":["test"]}]}]},{"name":["NewAccountName"],"label":["NewAccountName"],"locationX":["428"],"locationY":["192"],"assignmentItems":[{"assignToReference":["createAccount.Name"],"operator":["Assign"],"value":[{"elementReference":["New_Account_Name"]}]}],"connector":[{"targetReference":["createAccountRecord"]}]}],"interviewLabel":["UnconnectedScreens {!$Flow.CurrentDateTime}"],"label":["UnconnectedScreensWithDuplicateDML"],"processMetadataValues":[{"name":["BuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]},{"name":["CanvasMode"],"value":[{"stringValue":["FREE_FORM_CANVAS"]}]},{"name":["OriginBuilderType"],"value":[{"stringValue":["LightningFlowBuilder"]}]}],"processType":["Flow"],"recordCreates":[{"name":["createAccountRecord"],"label":["createAccountRecord"],"locationX":["449"],"locationY":["462"],"connector":[{"targetReference":["ViewAccountId"]}],"inputReference":["createAccount"]}],"screens":[{"name":["NameNewAccount"],"label":["NameNewAccount"],"locationX":["177"],"locationY":["213"],"allowBack":["true"],"allowFinish":["true"],"allowPause":["true"],"connector":[{"targetReference":["NewAccountName"]}],"fields":[{"name":["New_Account_Name"],"dataType":["String"],"fieldText":["New Account Name"],"fieldType":["InputField"],"isRequired":["false"]}],"showFooter":["true"],"showHeader":["true"]},{"name":["ViewAccountId"],"label":["View AccountId"],"locationX":["172"],"locationY":["453"],"allowBack":["true"],"allowFinish":["true"],"allowPause":["true"],"fields":[{"name":["AccountNameDisplay"],"fieldText":["

{!createAccount.Name}

"],"fieldType":["DisplayText"]}],"showFooter":["true"],"showHeader":["true"]}],"start":[{"locationX":["50"],"locationY":["50"],"connector":[{"targetReference":["fillerAssignment"]}]}],"status":["Active"],"variables":[{"name":["createAccount"],"dataType":["SObject"],"isCollection":["false"],"isInput":["false"],"isOutput":["false"],"objectType":["Account"]}]}} \ No newline at end of file diff --git a/tests/testfiles/WaitForOnly.json b/tests/testfiles/WaitForOnly.json deleted file mode 100644 index 612a693..0000000 --- a/tests/testfiles/WaitForOnly.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "Flow": { - "$": { "xmlns": "http://soap.sforce.com/2006/04/metadata" }, - "apiVersion": ["60.0"], - "assignments": [ - { - "description": ["Default Action for Asynchronous Transaction"], - "name": ["VariableAssignment"], - "label": ["VariableAssignment"], - "locationX": ["706"], - "locationY": ["382"], - "assignmentItems": [ - { - "assignToReference": ["$Record.Name"], - "operator": ["Assign"], - "value": [{ "stringValue": ["Test"] }] - } - ] - } - ], - "description": ["AsyncOnlyAutomation"], - "environments": ["Default"], - "interviewLabel": ["AsyncOnlyTransaction {!$Flow.CurrentDateTime}"], - "label": ["Async_OnlyTransaction"], - "processMetadataValues": [ - { - "name": ["BuilderType"], - "value": [{ "stringValue": ["LightningFlowBuilder"] }] - }, - { - "name": ["CanvasMode"], - "value": [{ "stringValue": ["FREE_FORM_CANVAS"] }] - }, - { - "name": ["OriginBuilderType"], - "value": [{ "stringValue": ["LightningFlowBuilder"] }] - } - ], - "processType": ["AutoLaunchedFlow"], - "start": [ - { - "locationX": ["185"], - "locationY": ["0"], - "object": ["Account"], - "recordTriggerType": ["Create"], - "scheduledPaths": [ - { "pathType": ["AsyncAfterCommit"] }, - { - "name": ["Wait_For"], - "connector": [{ "targetReference": ["VariableAssignment"] }], - "label": ["Wait For"], - "offsetNumber": ["2"], - "offsetUnit": ["Hours"], - "timeSource": ["RecordTriggerEvent"] - } - ], - "triggerType": ["RecordAfterSave"] - } - ], - "status": ["Active"] - } - } - \ No newline at end of file diff --git a/tests/testfiles/api58test.json b/tests/testfiles/api58test.json deleted file mode 100644 index 52c6b26..0000000 --- a/tests/testfiles/api58test.json +++ /dev/null @@ -1,368 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "53.0" - ], - "collectionProcessors": [ - { - "name": [ - "filter_test_accounts" - ], - "elementSubtype": [ - "FilterCollectionProcessor" - ], - "label": [ - "filter test accounts" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "assignNextValueToReference": [ - "currentItem_af_0" - ], - "collectionProcessorType": [ - "FilterCollectionProcessor" - ], - "collectionReference": [ - "c" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "currentItem_af_0.Name" - ], - "operator": [ - "Contains" - ], - "rightValue": [ - { - "stringValue": [ - "test" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "sort_acc" - ] - } - ] - }, - { - "name": [ - "sort_acc" - ], - "elementSubtype": [ - "SortCollectionProcessor" - ], - "label": [ - "sort acc" - ], - "locationX": [ - "176" - ], - "locationY": [ - "242" - ], - "collectionProcessorType": [ - "SortCollectionProcessor" - ], - "collectionReference": [ - "filter_test_accounts" - ], - "connector": [ - { - "targetReference": [ - "rb" - ] - } - ], - "sortOptions": [ - { - "doesPutEmptyStringAndNullFirst": [ - "false" - ], - "sortField": [ - "AccountNumber" - ], - "sortOrder": [ - "Asc" - ] - } - ] - } - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "api58test {!$Flow.CurrentDateTime}" - ], - "label": [ - "api58test" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordRollbacks": [ - { - "name": [ - "rb" - ], - "label": [ - "rb" - ], - "locationX": [ - "176" - ], - "locationY": [ - "350" - ], - "connector": [ - { - "targetReference": [ - "aa" - ] - } - ] - } - ], - "screens": [ - { - "name": [ - "aa" - ], - "label": [ - "aa" - ], - "locationX": [ - "176" - ], - "locationY": [ - "458" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "fields": [ - { - "name": [ - "bb" - ], - "dataTypeMappings": [ - { - "typeName": [ - "T" - ], - "typeValue": [ - "Account" - ] - } - ], - "extensionName": [ - "flowruntime:datatable" - ], - "fieldType": [ - "ComponentInstance" - ], - "inputParameters": [ - { - "name": [ - "label" - ], - "value": [ - { - "stringValue": [ - "Data Table" - ] - } - ] - }, - { - "name": [ - "selectionMode" - ], - "value": [ - { - "stringValue": [ - "MULTI_SELECT" - ] - } - ] - }, - { - "name": [ - "minRowSelection" - ], - "value": [ - { - "numberValue": [ - "0.0" - ] - } - ] - }, - { - "name": [ - "tableData" - ], - "value": [ - { - "elementReference": [ - "filter_test_accounts" - ] - } - ] - }, - { - "name": [ - "columns" - ], - "value": [ - { - "stringValue": [ - "[{\"apiName\":\"AccountNumber\",\"guid\":\"column-8e94\",\"editable\":false,\"hasCustomHeaderLabel\":false,\"customHeaderLabel\":\"\",\"wrapText\":true,\"order\":0,\"label\":\"Account Number\",\"type\":\"text\"}]" - ] - } - ] - } - ], - "inputsOnNextNavToAssocScrn": [ - "UseStoredValues" - ], - "isRequired": [ - "true" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "filter_test_accounts" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "c" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "true" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "currentItem_af_0" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/cv.json b/tests/testfiles/cv.json deleted file mode 100644 index bf4cb69..0000000 --- a/tests/testfiles/cv.json +++ /dev/null @@ -1,1194 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "56.0" - ], - "decisions": [ - { - "name": [ - "contact_doublon_selectionne" - ], - "label": [ - "Contact en doublon doublon sélectionné ?" - ], - "locationX": [ - "248" - ], - "locationY": [ - "1190" - ], - "defaultConnector": [ - { - "isGoTo": [ - "true" - ], - "targetReference": [ - "Interlocuteur" - ] - } - ], - "defaultConnectorLabel": [ - "Non" - ], - "rules": [ - { - "name": [ - "Oui_doublon_s_lectionn" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "selectedDuplicateContact.Id" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Renseigner_targetContactid_avec_doublon_potentiel_selectionne" - ] - } - ], - "label": [ - "Oui doublon sélectionné" - ] - } - ] - }, - { - "name": [ - "Conversion_reussie" - ], - "label": [ - "Conversion réussie ?" - ], - "locationX": [ - "578" - ], - "locationY": [ - "2462" - ], - "defaultConnector": [ - { - "targetReference": [ - "Conversion_KO_message" - ] - } - ], - "defaultConnectorLabel": [ - "Non" - ], - "rules": [ - { - "name": [ - "Oui_conversion_reussie" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "finalConvertedContactId" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Conversion_OK_message" - ] - } - ], - "label": [ - "Oui, conversion réussie" - ] - } - ] - }, - { - "name": [ - "conversion_vers_une_opport" - ], - "label": [ - "conversion vers une opport ?" - ], - "locationX": [ - "314" - ], - "locationY": [ - "2678" - ], - "defaultConnector": [ - { - "targetReference": [ - "Set_redirect_to_Interlo" - ] - } - ], - "defaultConnectorLabel": [ - "Non, pas d'opport ciblée" - ], - "rules": [ - { - "name": [ - "Oui_opport_cibl_e" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "currentLead.Offre_convertie__c" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "create_contact_role_on_opport" - ] - } - ], - "label": [ - "Oui, opport ciblée" - ] - } - ] - }, - { - "name": [ - "Doublons_potentiels_trouves" - ], - "label": [ - "Doublons potentiels trouvés ?" - ], - "locationX": [ - "578" - ], - "locationY": [ - "674" - ], - "defaultConnector": [ - { - "targetReference": [ - "Interlocuteur" - ] - } - ], - "defaultConnectorLabel": [ - "Non" - ], - "rules": [ - { - "name": [ - "Oui_doublons_trouves" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "Interlo_doublon_potentiel.duplicateContacts" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Renseigner_booleen_doublon_trouves" - ] - } - ], - "label": [ - "Oui, doublons trouvés" - ] - } - ] - }, - { - "name": [ - "Initial_Lead_data_OK" - ], - "label": [ - "Initial Lead data OK ?" - ], - "locationX": [ - "2360" - ], - "locationY": [ - "242" - ], - "defaultConnector": [ - { - "targetReference": [ - "Donnees_manquantes" - ] - } - ], - "defaultConnectorLabel": [ - "KO" - ], - "rules": [ - { - "name": [ - "Lead_data_OK" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "currentLead.hbiz__apifc_SIRET__c" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "leftValueReference": [ - "currentLead.OwnerId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "005" - ] - } - ] - }, - { - "leftValueReference": [ - "currentLead.Salutation" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "leftValueReference": [ - "currentLead.Produit__c" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "leftValueReference": [ - "currentLead.Phone" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "leftValueReference": [ - "currentLead" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Get_etab_from_Rubis" - ] - } - ], - "label": [ - "Lead data OK" - ] - } - ] - }, - { - "name": [ - "Interlocuteur_options" - ], - "label": [ - "Interlocuteur options" - ], - "locationX": [ - "578" - ], - "locationY": [ - "1082" - ], - "defaultConnector": [ - { - "targetReference": [ - "Get_all_opport" - ] - } - ], - "defaultConnectorLabel": [ - "Sélection existant" - ], - "rules": [ - { - "name": [ - "doublon_selectionne" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "radioInterlo" - ], - "operator": [ - "EqualTo" - ], - "rightValue": [ - { - "elementReference": [ - "interlo_select_duplicate" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "contact_doublon_selectionne" - ] - } - ], - "label": [ - "Sélection doublon" - ] - }, - { - "name": [ - "creation" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "radioInterlo" - ], - "operator": [ - "EqualTo" - ], - "rightValue": [ - { - "elementReference": [ - "interlo_create" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Vider_targetContactId" - ] - } - ], - "label": [ - "Création" - ] - } - ] - }, - { - "name": [ - "Opport_Options" - ], - "label": [ - "Opport Options" - ], - "locationX": [ - "578" - ], - "locationY": [ - "1898" - ], - "defaultConnector": [ - { - "targetReference": [ - "add_existing_Opport_to_Lead" - ] - } - ], - "defaultConnectorLabel": [ - "Existing opport" - ], - "rules": [ - { - "name": [ - "No_opport" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "radioOpport" - ], - "operator": [ - "EqualTo" - ], - "rightValue": [ - { - "elementReference": [ - "opp_none" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Pas_d_offre_convertie" - ] - } - ], - "label": [ - "No opport" - ] - }, - { - "name": [ - "Create_opport" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "radioOpport" - ], - "operator": [ - "EqualTo" - ], - "rightValue": [ - { - "elementReference": [ - "opp_create" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Creer_affaire" - ] - } - ], - "label": [ - "Create opport" - ] - } - ] - }, - { - "name": [ - "Siret_trouv_dans_Rubis" - ], - "label": [ - "Siret trouvé dans Rubis ?" - ], - "locationX": [ - "1502" - ], - "locationY": [ - "458" - ], - "defaultConnector": [ - { - "targetReference": [ - "Lancement_import_Calypso" - ] - } - ], - "defaultConnectorLabel": [ - "SIRET non trouvé" - ], - "rules": [ - { - "name": [ - "SIRET_trouve" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "targetEtablissement" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Interlo_doublon_potentiel" - ] - } - ], - "label": [ - "SIRET trouvé" - ] - } - ] - } - ], - "description": [ - "abc" - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "abc {!$Flow.CurrentDateTime}" - ], - "label": [ - "abc" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordCreates": [ - { - "name": [ - "create_contact_role_on_opport" - ], - "label": [ - "Create contact role on opport" - ], - "locationX": [ - "50" - ], - "locationY": [ - "2786" - ], - "connector": [ - { - "targetReference": [ - "Set_redirect_to_Opport" - ] - } - ], - "faultConnector": [ - { - "isGoTo": [ - "true" - ], - "targetReference": [ - "Rollback" - ] - } - ], - "inputAssignments": [ - { - "field": [ - "ContactId" - ], - "value": [ - { - "elementReference": [ - "finalConvertedContactId" - ] - } - ] - }, - { - "field": [ - "OpportunityId" - ], - "value": [ - { - "elementReference": [ - "currentLead.Offre_convertie__c" - ] - } - ] - }, - { - "field": [ - "Role" - ], - "value": [ - { - "stringValue": [ - "Interlocuteur affaire" - ] - } - ] - } - ], - "object": [ - "OpportunityContactRole" - ], - "storeOutputAutomatically": [ - "true" - ] - }, - { - "description": [ - "Crée une affaire et stocke son Id entant que cible de la conversion à venir. Mise à jour : puisqu'il n'est pas possible de convertir vers une opport (diff de record type d'account sur Interlo & Offre), l'affaire créée est renseignée sur un champ custo" - ], - "name": [ - "Creer_affaire" - ], - "label": [ - "Créer affaire" - ], - "locationX": [ - "314" - ], - "locationY": [ - "2006" - ], - "assignRecordIdToReference": [ - "currentLead.Offre_convertie__c" - ], - "connector": [ - { - "targetReference": [ - "add_new_Affaire_to_Lead" - ] - } - ], - "faultConnector": [ - { - "isGoTo": [ - "true" - ], - "targetReference": [ - "Rollback" - ] - } - ], - "inputAssignments": [ - { - "field": [ - "AccountId" - ], - "value": [ - { - "elementReference": [ - "targetEtablissement.Id" - ] - } - ] - }, - { - "field": [ - "CloseDate" - ], - "value": [ - { - "elementReference": [ - "defaultCloseDate" - ] - } - ] - }, - { - "field": [ - "Name" - ], - "value": [ - { - "stringValue": [ - "Ne pas modifier" - ] - } - ] - }, - { - "field": [ - "Produit__c" - ], - "value": [ - { - "elementReference": [ - "currentLead.Produit__c" - ] - } - ] - }, - { - "field": [ - "RecordTypeId" - ], - "value": [ - { - "stringValue": [ - "012w0000000MQHvAAO" - ] - } - ] - }, - { - "field": [ - "StageName" - ], - "value": [ - { - "stringValue": [ - "Détectée" - ] - } - ] - } - ], - "object": [ - "Opportunity" - ] - } - ], - "runInMode": [ - "SystemModeWithoutSharing" - ], - "start": [ - { - "locationX": [ - "2234" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "Initial_lead_data" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "conversionResultMessage" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "description": [ - "pas possible d'assigner une opport lors la conversion. A la place, une champ custo du Lead est utilisé (Offre_convertie)" - ], - "name": [ - "createOpport" - ], - "dataType": [ - "Boolean" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "value": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "description": [ - "Lead en cours de conversion" - ], - "name": [ - "currentLead" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Lead" - ] - }, - { - "description": [ - "vrai si des doublons potentiels ont été identifiés" - ], - "name": [ - "doublonsPotentielsTrouves" - ], - "dataType": [ - "Boolean" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "value": [ - { - "booleanValue": [ - "false" - ] - } - ] - }, - { - "description": [ - "Reçoit l'id de l'établissemnt créé suite à un appel Calypso" - ], - "name": [ - "etabFromCalypsoId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "description": [ - "Id du contact vers lequel a été converti le Lead" - ], - "name": [ - "finalConvertedContactId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "description": [ - "Destination de la redirection finale : Opport, si une opport a été ciblée. Sinon interlocuteur." - ], - "name": [ - "finalRedirectRecordId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "name": [ - "nbExistingOpportFound" - ], - "dataType": [ - "Number" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "scale": [ - "0" - ] - }, - { - "description": [ - "Id du Lead en cours de convertion" - ], - "name": [ - "recordId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "true" - ], - "isOutput": [ - "false" - ] - }, - { - "description": [ - "Contact en doublon potentiel sélectionne comme cible de convertion" - ], - "name": [ - "selectedDuplicateContact" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Contact" - ] - }, - { - "name": [ - "targetContactId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "description": [ - "Etablissement ciblé par la convertion" - ], - "name": [ - "targetEtablissement" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - }, - { - "name": [ - "targetOpport" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Opportunity" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/flawedflow.json b/tests/testfiles/flawedflow.json deleted file mode 100644 index f497d38..0000000 --- a/tests/testfiles/flawedflow.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - } - } -} \ No newline at end of file diff --git a/tests/testfiles/hidenav.json b/tests/testfiles/hidenav.json deleted file mode 100644 index c3e7eed..0000000 --- a/tests/testfiles/hidenav.json +++ /dev/null @@ -1,261 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "assignments": [ - { - "name": [ - "NewAccountName" - ], - "label": [ - "NewAccountName" - ], - "locationX": [ - "428" - ], - "locationY": [ - "193" - ], - "assignmentItems": [ - { - "assignToReference": [ - "createAccount.Name" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "New_Account_Name" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "createAccountRecord" - ] - } - ] - } - ], - "interviewLabel": [ - "CreateANewAccountImprovedHideNav {!$Flow.CurrentDateTime}" - ], - "label": [ - "CreateANewAccountImprovedHideNav" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "FREE_FORM_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "Flow" - ], - "recordCreates": [ - { - "name": [ - "createAccountRecord" - ], - "label": [ - "createAccountRecord" - ], - "locationX": [ - "449" - ], - "locationY": [ - "463" - ], - "connector": [ - { - "targetReference": [ - "ViewAccountId" - ] - } - ], - "inputReference": [ - "createAccount" - ] - } - ], - "screens": [ - { - "name": [ - "NameNewAccount" - ], - "label": [ - "NameNewAccount" - ], - "locationX": [ - "176" - ], - "locationY": [ - "214" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "NewAccountName" - ] - } - ], - "fields": [ - { - "name": [ - "New_Account_Name" - ], - "dataType": [ - "String" - ], - "fieldText": [ - "New Account Name" - ], - "fieldType": [ - "InputField" - ], - "isRequired": [ - "false" - ] - } - ], - "showFooter": [ - "true" - ], - "showHeader": [ - "true" - ] - }, - { - "name": [ - "ViewAccountId" - ], - "label": [ - "View AccountId" - ], - "locationX": [ - "172" - ], - "locationY": [ - "454" - ], - "allowBack": [ - "true" - ], - "allowFinish": [ - "true" - ], - "allowPause": [ - "true" - ], - "fields": [ - { - "name": [ - "AccountNameDisplay" - ], - "fieldText": [ - "

{!createAccount.Name}

" - ], - "fieldType": [ - "DisplayText" - ] - } - ], - "showFooter": [ - "false" - ], - "showHeader": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "50" - ], - "connector": [ - { - "targetReference": [ - "NameNewAccount" - ] - } - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "createAccount" - ], - "dataType": [ - "SObject" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ], - "objectType": [ - "Account" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/missingerrorhandler.json b/tests/testfiles/missingerrorhandler.json deleted file mode 100644 index d6a5972..0000000 --- a/tests/testfiles/missingerrorhandler.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "log_call" - ], - "label": [ - "log call" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "actionName": [ - "LogACall" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "nameSegment": [ - "LogACall" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "description": [ - "This flow demonstrates a violation of the rule \"DML statements in a loop\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Missing error handlers {!$Flow.CurrentDateTime}" - ], - "label": [ - "Missing error handlers" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "log_call" - ] - } - ] - } - ], - "status": [ - "Active" - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/missingerrorhandler_fixed.json b/tests/testfiles/missingerrorhandler_fixed.json deleted file mode 100644 index bb79dc6..0000000 --- a/tests/testfiles/missingerrorhandler_fixed.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "actionCalls": [ - { - "name": [ - "dosomethingelse" - ], - "label": [ - "dosomethingelse" - ], - "locationX": [ - "440" - ], - "locationY": [ - "242" - ], - "actionName": [ - "NewTask" - ], - "actionType": [ - "quickAction" - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "inputParameters": [ - { - "name": [ - "OwnerId" - ], - "value": [ - { - "elementReference": [ - "$User.Id" - ] - } - ] - } - ], - "nameSegment": [ - "NewTask" - ], - "versionSegment": [ - "1" - ] - }, - { - "name": [ - "log_call" - ], - "label": [ - "log call" - ], - "locationX": [ - "176" - ], - "locationY": [ - "134" - ], - "actionName": [ - "LogACall" - ], - "actionType": [ - "quickAction" - ], - "faultConnector": [ - { - "targetReference": [ - "dosomethingelse" - ] - } - ], - "flowTransactionModel": [ - "CurrentTransaction" - ], - "nameSegment": [ - "LogACall" - ], - "versionSegment": [ - "1" - ] - } - ], - "apiVersion": [ - "58.0" - ], - "description": [ - "This flow demonstrates how to resolve a violation of the rule \"Missing Error Handler\"." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Fix: Missing Error Handler {!$Flow.CurrentDateTime}" - ], - "label": [ - "Fix: Missing Error Handler" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "start": [ - { - "locationX": [ - "50" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "log_call" - ] - } - ] - } - ], - "status": [ - "Active" - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/taskbs.json b/tests/testfiles/taskbs.json deleted file mode 100644 index 1b0c743..0000000 --- a/tests/testfiles/taskbs.json +++ /dev/null @@ -1,1002 +0,0 @@ -{ - "Flow": { - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": [ - "57.0" - ], - "assignments": [ - { - "name": [ - "Assign_Contact" - ], - "label": [ - "Assign Contact" - ], - "locationX": [ - "314" - ], - "locationY": [ - "503" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "$Record.WhoId" - ] - } - ] - }, - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ] - } - ] - }, - { - "description": [ - "When there is no ContactId on the Opp, and there is no Primary OCR, We assign the first Contact the Flow \"Gets\" from the Account related to the Opp." - ], - "name": [ - "Assign_Contact_from_Account_Opp" - ], - "label": [ - "Assign Contact from Account.Opp" - ], - "locationX": [ - "1106" - ], - "locationY": [ - "1259" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Var_ContactId_Account" - ] - } - ] - }, - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ] - }, - { - "assignToReference": [ - "$Record.WhoId" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Var_ContactId_Account" - ] - } - ] - } - ] - }, - { - "name": [ - "Assign_Contact_from_OCR" - ], - "label": [ - "Assign Contact from OCR" - ], - "locationX": [ - "842" - ], - "locationY": [ - "1043" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Var_OCRId" - ] - } - ] - }, - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ] - }, - { - "assignToReference": [ - "$Record.WhoId" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Var_OCRId" - ] - } - ] - } - ] - }, - { - "name": [ - "Assign_Contact_from_Opportunity" - ], - "label": [ - "Assign Contact from Opportunity" - ], - "locationX": [ - "578" - ], - "locationY": [ - "827" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Get_Opportunity.ContactId" - ] - } - ] - }, - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ] - }, - { - "assignToReference": [ - "$Record.WhoId" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "Get_Opportunity.ContactId" - ] - } - ] - } - ] - }, - { - "name": [ - "Assign_Lead" - ], - "label": [ - "Assign Lead" - ], - "locationX": [ - "50" - ], - "locationY": [ - "503" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ], - "value": [ - { - "elementReference": [ - "$Record.WhoId" - ] - } - ] - }, - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ] - } - ] - }, - { - "name": [ - "No_Contact_Lead" - ], - "label": [ - "No Contact/Lead" - ], - "locationX": [ - "1546" - ], - "locationY": [ - "611" - ], - "assignmentItems": [ - { - "assignToReference": [ - "$Record.Lead__c" - ], - "operator": [ - "Assign" - ] - }, - { - "assignToReference": [ - "$Record.Contact__c" - ], - "operator": [ - "Assign" - ] - } - ] - } - ], - "decisions": [ - { - "name": [ - "Contact_on_Opportunity" - ], - "label": [ - "Contact on Opportunity?" - ], - "locationX": [ - "809" - ], - "locationY": [ - "719" - ], - "defaultConnector": [ - { - "targetReference": [ - "Get_OCR_from_related_Opp" - ] - } - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "True_Contact_on_Opp" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "Get_Opportunity.ContactId" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_Contact_from_Opportunity" - ] - } - ], - "label": [ - "True - Contact on Opp" - ] - } - ] - }, - { - "name": [ - "Found_Contact_from_Account" - ], - "label": [ - "Found Contact from Account?" - ], - "locationX": [ - "1238" - ], - "locationY": [ - "1151" - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "True_Found_Contact_from_Account" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "Var_ContactId_Account" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_Contact_from_Account_Opp" - ] - } - ], - "label": [ - "True - Found Contact from Account" - ] - } - ] - }, - { - "name": [ - "Found_Primary_OCR" - ], - "label": [ - "Found Primary OCR?" - ], - "locationX": [ - "1040" - ], - "locationY": [ - "935" - ], - "defaultConnector": [ - { - "targetReference": [ - "Get_Contact_from_Account_Opp" - ] - } - ], - "defaultConnectorLabel": [ - "No Primary OCR" - ], - "rules": [ - { - "name": [ - "True_Found_Primary_OCR" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "Get_OCR_from_related_Opp" - ], - "operator": [ - "IsNull" - ], - "rightValue": [ - { - "booleanValue": [ - "false" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_Contact_from_OCR" - ] - } - ], - "label": [ - "True - Found Primary OCR" - ] - } - ] - }, - { - "description": [ - "Check if the \"WhoId\" is a Lead or a Contact." - ], - "name": [ - "Lead_Or_Contact_related_to_the_Task" - ], - "label": [ - "Lead Or Contact related to the Task" - ], - "locationX": [ - "613" - ], - "locationY": [ - "395" - ], - "defaultConnector": [ - { - "targetReference": [ - "Task_created_from_Opportunity" - ] - } - ], - "defaultConnectorLabel": [ - "Null" - ], - "rules": [ - { - "name": [ - "Lead" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "$Record.WhoId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "00Q" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_Lead" - ] - } - ], - "label": [ - "Lead" - ] - }, - { - "name": [ - "Contact" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "$Record.WhoId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "003" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Assign_Contact" - ] - } - ], - "label": [ - "Contact" - ] - } - ] - }, - { - "name": [ - "Task_created_from_Opportunity" - ], - "label": [ - "Task created from Opportunity?" - ], - "locationX": [ - "1177" - ], - "locationY": [ - "503" - ], - "defaultConnector": [ - { - "targetReference": [ - "No_Contact_Lead" - ] - } - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "True_Opp" - ], - "conditionLogic": [ - "and" - ], - "conditions": [ - { - "leftValueReference": [ - "$Record.WhatId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "006" - ] - } - ] - } - ], - "connector": [ - { - "targetReference": [ - "Get_Opportunity" - ] - } - ], - "label": [ - "True - Opp" - ] - } - ] - }, - { - "name": [ - "Task_Related_to_Case_WI" - ], - "label": [ - "Task Related to Case/WI?" - ], - "locationX": [ - "199" - ], - "locationY": [ - "287" - ], - "defaultConnector": [ - { - "targetReference": [ - "Lead_Or_Contact_related_to_the_Task" - ] - } - ], - "defaultConnectorLabel": [ - "Default Outcome" - ], - "rules": [ - { - "name": [ - "True_Relates_to_Case_WI" - ], - "conditionLogic": [ - "or" - ], - "conditions": [ - { - "leftValueReference": [ - "$Record.WhatId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "500" - ] - } - ] - }, - { - "leftValueReference": [ - "$Record.WhatId" - ], - "operator": [ - "StartsWith" - ], - "rightValue": [ - { - "stringValue": [ - "a2G" - ] - } - ] - } - ], - "label": [ - "True - Relates to Case/WI" - ] - } - ] - } - ], - "description": [ - "WI-02771\r\nWI-02814 - Added logic to populate the WhoId and the Contact when Task created from an Opportunity. Migrate the logic from Appex." - ], - "environments": [ - "Default" - ], - "interviewLabel": [ - "Task - Before - SDR/Sales Trigger {!$Flow.CurrentDateTime}" - ], - "label": [ - "Task - Before - SDR/Sales Trigger" - ], - "processMetadataValues": [ - { - "name": [ - "BuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - }, - { - "name": [ - "CanvasMode" - ], - "value": [ - { - "stringValue": [ - "AUTO_LAYOUT_CANVAS" - ] - } - ] - }, - { - "name": [ - "OriginBuilderType" - ], - "value": [ - { - "stringValue": [ - "LightningFlowBuilder" - ] - } - ] - } - ], - "processType": [ - "AutoLaunchedFlow" - ], - "recordLookups": [ - { - "name": [ - "Get_Contact_from_Account_Opp" - ], - "label": [ - "Get Contact from Account.Opp" - ], - "locationX": [ - "1238" - ], - "locationY": [ - "1043" - ], - "assignNullValuesIfNoRecordsFound": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "Found_Contact_from_Account" - ] - } - ], - "filterLogic": [ - "and" - ], - "filters": [ - { - "field": [ - "AccountId" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "elementReference": [ - "Get_Opportunity.AccountId" - ] - } - ] - } - ], - "object": [ - "Contact" - ], - "outputAssignments": [ - { - "assignToReference": [ - "Var_ContactId_Account" - ], - "field": [ - "Id" - ] - } - ] - }, - { - "description": [ - "Get the Primary Opportunity Contact Role from the related Opportunity" - ], - "name": [ - "Get_OCR_from_related_Opp" - ], - "label": [ - "Get OCR from related Opp" - ], - "locationX": [ - "1040" - ], - "locationY": [ - "827" - ], - "assignNullValuesIfNoRecordsFound": [ - "true" - ], - "connector": [ - { - "targetReference": [ - "Found_Primary_OCR" - ] - } - ], - "filterLogic": [ - "and" - ], - "filters": [ - { - "field": [ - "OpportunityId" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "elementReference": [ - "$Record.WhatId" - ] - } - ] - }, - { - "field": [ - "IsPrimary" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "booleanValue": [ - "true" - ] - } - ] - } - ], - "object": [ - "OpportunityContactRole" - ], - "outputAssignments": [ - { - "assignToReference": [ - "Var_OCRId" - ], - "field": [ - "ContactId" - ] - } - ] - }, - { - "name": [ - "Get_Opportunity" - ], - "label": [ - "Get Opportunity" - ], - "locationX": [ - "809" - ], - "locationY": [ - "611" - ], - "assignNullValuesIfNoRecordsFound": [ - "false" - ], - "connector": [ - { - "targetReference": [ - "Contact_on_Opportunity" - ] - } - ], - "filterLogic": [ - "and" - ], - "filters": [ - { - "field": [ - "Id" - ], - "operator": [ - "EqualTo" - ], - "value": [ - { - "elementReference": [ - "$Record.WhatId" - ] - } - ] - } - ], - "getFirstRecordOnly": [ - "true" - ], - "object": [ - "Opportunity" - ], - "storeOutputAutomatically": [ - "true" - ] - } - ], - "start": [ - { - "locationX": [ - "73" - ], - "locationY": [ - "0" - ], - "connector": [ - { - "targetReference": [ - "Task_Related_to_Case_WI" - ] - } - ], - "filterFormula": [ - "(ISNEW() || ISCHANGED({!$Record.WhoId})) && \r\nCONTAINS({!$Label.SDR_Sales_Profiles},{!$Profile.Name})" - ], - "object": [ - "Task" - ], - "recordTriggerType": [ - "CreateAndUpdate" - ], - "triggerType": [ - "RecordBeforeSave" - ] - } - ], - "status": [ - "Active" - ], - "variables": [ - { - "name": [ - "Var_ContactId_Account" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - }, - { - "name": [ - "Var_OCRId" - ], - "dataType": [ - "String" - ], - "isCollection": [ - "false" - ], - "isInput": [ - "false" - ], - "isOutput": [ - "false" - ] - } - ] - } -} \ No newline at end of file diff --git a/tests/testfiles/unusedvariable.json b/tests/testfiles/unusedvariable.json deleted file mode 100644 index 4360b4d..0000000 --- a/tests/testfiles/unusedvariable.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": ["58.0"], - "description": ["This flow demonstrates a violation of the rule \"Unused Variable\"."], - "environments": ["Default"], - "interviewLabel": ["Unused Variable {!$Flow.CurrentDateTime}"], - "label": ["Unused Variable"], - "processMetadataValues": [ - { - "name": ["BuilderType"], - "value": [{"stringValue": ["LightningFlowBuilder"]}] - }, - { - "name": ["CanvasMode"], - "value": [{"stringValue": ["AUTO_LAYOUT_CANVAS"]}] - }, - { - "name": ["OriginBuilderType"], - "value": [{"stringValue": ["LightningFlowBuilder"]}] - } - ], - "processType": ["Flow"], - "screens": [ - { - "name": ["mock_screen"], - "label": ["mock screen"], - "locationX": ["176"], - "locationY": ["134"], - "allowBack": ["true"], - "allowFinish": ["true"], - "allowPause": ["true"], - "showFooter": ["true"], - "showHeader": ["true"] - } - ], - "start": [ - { - "locationX": ["50"], - "locationY": ["0"], - "connector": [{"targetReference": ["mock_screen"]}] - } - ], - "status": ["Active"], - "variables": [ - { - "name": ["anUnusedVariable"], - "dataType": ["String"], - "isCollection": ["false"], - "isInput": ["false"], - "isOutput": ["false"], - "value": [{"stringValue": ["hello world"]}] - } - ] - } - \ No newline at end of file diff --git a/tests/testfiles/unusedvariablefixed.json b/tests/testfiles/unusedvariablefixed.json deleted file mode 100644 index 4559aae..0000000 --- a/tests/testfiles/unusedvariablefixed.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "$": { - "xmlns": "http://soap.sforce.com/2006/04/metadata" - }, - "apiVersion": ["58.0"], - "description": ["This flow demonstrates how to resolve a violation of the rule \"Unused Variable\"."], - "environments": ["Default"], - "interviewLabel": ["Fix: Unused Variables {!$Flow.CurrentDateTime}"], - "label": ["Fix: Unused Variable"], - "processMetadataValues": [ - { - "name": ["BuilderType"], - "value": [{"stringValue": ["LightningFlowBuilder"]}] - }, - { - "name": ["CanvasMode"], - "value": [{"stringValue": ["AUTO_LAYOUT_CANVAS"]}] - }, - { - "name": ["OriginBuilderType"], - "value": [{"stringValue": ["LightningFlowBuilder"]}] - } - ], - "processType": ["Flow"], - "screens": [ - { - "name": ["mock_screen"], - "label": ["mock screen"], - "locationX": ["176"], - "locationY": ["134"], - "allowBack": ["true"], - "allowFinish": ["true"], - "allowPause": ["true"], - "showFooter": ["true"], - "showHeader": ["true"] - } - ], - "start": [ - { - "locationX": ["50"], - "locationY": ["0"], - "connector": [{"targetReference": ["mock_screen"]}] - } - ], - "status": ["Active"] - } - \ No newline at end of file diff --git a/tests/xmlfiles/Utility_Copy_Files_Subflow.flow-meta.xml b/tests/xmlfiles/Utility_Copy_Files_Subflow.flow-meta.xml new file mode 100644 index 0000000..73bc671 --- /dev/null +++ b/tests/xmlfiles/Utility_Copy_Files_Subflow.flow-meta.xml @@ -0,0 +1,294 @@ + + + 57.0 + + Add_to_Collection + + 138 + 674 + + colContentDocumentLinksNew + Add + + Content_Document_Links + + + + Content_Document_Links + + + + Set_Create_Target_Error + + 314 + 974 + + vIsError + Assign + + true + + + + vErrorMessage + Assign + + There was an error creating the Target Document Links + + + + + Set_Missing_Id_Error + + 842 + 242 + + vIsError + Assign + + true + + + + vErrorMessage + Assign + + Either or both of the Source or Target record ids are blank. + + + + + Set_No_Source_Error + + 578 + 458 + + vIsError + Assign + + true + + + + vErrorMessage + Assign + + There are no files attached to the Source record + + + + + Set_Target_Link_Clear_Record_Id + + 138 + 566 + + Content_Document_Links.LinkedEntityId + Assign + + vTargetObjectId + + + + Content_Document_Links.Id + Assign + + + Add_to_Collection + + + + Found_Source_Files + + 314 + 350 + + Set_No_Source_Error + + NO SOURCE FILES (Default) + + HAVE_FILES + and + + Get_Source_Files + IsNull + + false + + + + Content_Document_Links + + + + + + Have_Record_Ids + + 578 + 134 + + Set_Missing_Id_Error + + MISSING (Default) + + HAVE_BOTH + and + + vSourceObjectId + IsNull + + false + + + + vTargetObjectId + IsNull + + false + + + + vSourceObjectId + NotEqualTo + + + + + + vTargetObjectId + NotEqualTo + + + + + + Get_Source_Files + + + + + Copy all files/attachments from one record to another record. + Default + Utility - Copy Files - Subflow {!$Flow.CurrentDateTime} + + + Content_Document_Links + + 50 + 458 + Get_Source_Files + Asc + + Set_Target_Link_Clear_Record_Id + + + Create_Target_Content_Document_Links + + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + AutoLaunchedFlow + + Create_Target_Content_Document_Links + + 50 + 866 + + Set_Create_Target_Error + + colContentDocumentLinksNew + + + Get_Source_Files + + 314 + 242 + false + + Found_Source_Files + + and + + LinkedEntityId + EqualTo + + vSourceObjectId + + + + IsDeleted + EqualTo + + false + + + false + ContentDocumentLink + true + + SystemModeWithoutSharing + + 452 + 0 + + Have_Record_Ids + + + Draft + + colContentDocumentLinksNew + SObject + true + false + false + ContentDocumentLink + + + vErrorMessage + String + false + false + true + + + vIsError + Boolean + false + false + true + + false + + + + vSourceObjectId + String + false + true + false + + + vTargetObjectId + String + false + true + false + + From ff7ced74d5cfb94f9e87fba86c6599378fde5d47 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 16:07:53 +0200 Subject: [PATCH 06/11] add autolayout --- .DS_Store | Bin 8196 -> 8196 bytes src/main/rules/AutoLayout.ts | 4 +-- tests/APIVersion.test.ts | 2 +- tests/AutoLayout.test.ts | 46 +++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 tests/AutoLayout.test.ts diff --git a/.DS_Store b/.DS_Store index ac8ed64c88bd6d08b9e9ec73a8f136ce21095ad4..3c06f8bc766bfa261013842f5f96dc15ef9a614b 100644 GIT binary patch delta 50 zcmZp1XmQw}D!{mHvYJ34r&x8hrH+D;k?G`x0@92fllKb9Gj?viE1<=`nN8w5%jSO~ G?92d=z7OvJ delta 51 zcmZp1XmQw}D!{mXvYJ34mw0uxiHWg}g1O1$1p?BHos;(n$TN0rz9XQ;zL{O(8_VWD HBJ9inoqP}@ diff --git a/src/main/rules/AutoLayout.ts b/src/main/rules/AutoLayout.ts index 7dc0a94..92dcfac 100644 --- a/src/main/rules/AutoLayout.ts +++ b/src/main/rules/AutoLayout.ts @@ -17,10 +17,10 @@ export class AutoLayout extends RuleCommon implements core.IRuleDefinition { public execute(flow: core.Flow, options?: { expression: string }): core.RuleResult { - if (flow.xmldata.processMetadataValues) { + if (flow.processMetadataValues) { const CanvasMode = flow.xmldata.processMetadataValues.find(mdv => mdv.name === 'CanvasMode'); - const AutoLayout = CanvasMode.value && typeof CanvasMode.value === 'object' && 'stringValue' in CanvasMode.value && Array.isArray(CanvasMode.value.stringValue) && CanvasMode.value.stringValue === "AUTO_LAYOUT_CANVAS"; + const AutoLayout = CanvasMode.value && typeof CanvasMode.value === 'object' && CanvasMode.value.stringValue && CanvasMode.value.stringValue === "AUTO_LAYOUT_CANVAS"; return (!AutoLayout ? new core.RuleResult(this, [new core.ResultDetails(new core.FlowAttribute(CanvasMode.value?.stringValue, "CanvasMode", '!== AUTO_LAYOUT_CANVAS'))]) : new core.RuleResult(this, [])); diff --git a/tests/APIVersion.test.ts b/tests/APIVersion.test.ts index a223831..40511a5 100644 --- a/tests/APIVersion.test.ts +++ b/tests/APIVersion.test.ts @@ -1,6 +1,6 @@ import { assert, expect } from 'chai'; import 'mocha'; -import * as core from '../src' +import * as core from '../src'; import * as path from 'path-browserify'; describe('APIVersion', () => { diff --git a/tests/AutoLayout.test.ts b/tests/AutoLayout.test.ts new file mode 100644 index 0000000..3b8a75d --- /dev/null +++ b/tests/AutoLayout.test.ts @@ -0,0 +1,46 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('Autolayout', () => { + let example_uri = path.join(__dirname, './xmlfiles/Unconnected_Element.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Outdated_API_Version_Fixed.flow-meta.xml'); + + it('should have a result when CanvasMode is set to FREE_FORM_CANVAS', async () => { + let flows = await core.parse([example_uri]) + const ruleConfig = { + rules: + { + AutoLayout: + { + severity: 'error' + }, + } + }; + + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(1); + expect(occurringResults.find((res) => res.ruleName === 'AutoLayout')); + + }); + + it('should not have result when autolayout is configured', async () => { + + let flows = await core.parse([fixed_uri]) + const ruleConfig = { + rules: + { + AutoLayout: + { + severity: 'error' + }, + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(0); + + }); +}); From bc2f48923158d83e05890df21adcdfd7b60523b2 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 16:13:18 +0200 Subject: [PATCH 07/11] add unusedVariabble test --- tests/UnusedVariable.test.ts | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/UnusedVariable.test.ts diff --git a/tests/UnusedVariable.test.ts b/tests/UnusedVariable.test.ts new file mode 100644 index 0000000..6935136 --- /dev/null +++ b/tests/UnusedVariable.test.ts @@ -0,0 +1,45 @@ +import { expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('UnusedVariable Rule', () => { + let example_uri = path.join(__dirname, './xmlfiles/Unused_Variable.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Unused_Variable_Fixed.flow-meta.xml'); + + it('there should be a result for unused variables', async () => { + + let flows = await core.parse([example_uri]); + const ruleConfig = { + rules: + { + UnusedVariable: + { + severity: 'error', + }, + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(1); + }); + + it('there should be no result for variables used in text elements', async () => { + let flows = await core.parse([fixed_uri]); + const ruleConfig = { + rules: + { + UnusedVariable: + { + severity: 'error', + }, + } + }; + + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(0); + }); + +}); + From 7abec05d42ae2eca0517da4a23e9581acbde1799 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 16:28:05 +0200 Subject: [PATCH 08/11] add 3 more tests --- .DS_Store | Bin 8196 -> 8196 bytes tests/DMLStatementInLoop.test.ts | 24 ++++++++++++++++++++++++ tests/HardcodedId.test.ts | 16 ++++++++++++++++ tests/UnconnectedElement.test.ts | 17 +++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 tests/DMLStatementInLoop.test.ts create mode 100644 tests/HardcodedId.test.ts create mode 100644 tests/UnconnectedElement.test.ts diff --git a/.DS_Store b/.DS_Store index 3c06f8bc766bfa261013842f5f96dc15ef9a614b..c49f0c037e97a35a7003096029c181c8197d09ff 100644 GIT binary patch delta 50 zcmZp1XmQw}D!{mXvYJ34r+9U>nVF7)sp;hT0y2!9llKV7Gj?shBcR2;nO))=%jQ2K G?92d>dJpmd delta 49 zcmZp1XmQw}D!{mHvYJ34hgfyBrH+D;(c}dJGK?LQ_X@}}c5c2apvAtKP2xMt=6@pW F%m9RM54ivU diff --git a/tests/DMLStatementInLoop.test.ts b/tests/DMLStatementInLoop.test.ts new file mode 100644 index 0000000..b26a888 --- /dev/null +++ b/tests/DMLStatementInLoop.test.ts @@ -0,0 +1,24 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('DMLStatementInLoop ', () => { + let example_uri = path.join(__dirname, './xmlfiles/DML_Statement_In_A_Loop.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml'); + + it('there should be one result for the rule DMLStatementInLoop', async () => { + let flows = await core.parse([example_uri]) + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(1); + expect(occurringResults[0].ruleName).to.equal("DMLStatementInLoop"); + }); + + it('there should be no result for the rule DMLStatementInLoop', async () => { + let flows = await core.parse([fixed_uri]) + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(0); + }); +}); \ No newline at end of file diff --git a/tests/HardcodedId.test.ts b/tests/HardcodedId.test.ts new file mode 100644 index 0000000..9677e93 --- /dev/null +++ b/tests/HardcodedId.test.ts @@ -0,0 +1,16 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('In the Hardcoded_Ids flow', () => { + let example_uri = path.join(__dirname, './xmlfiles/Hardcoded_Id.flow-meta.xml'); + + it('there should be one result for the rule HardcodedIds', async () => { + let flows = await core.parse([example_uri]); + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.length).to.equal(1); + expect(occurringResults[0].ruleName).to.equal("HardcodedId"); + }); +}); \ No newline at end of file diff --git a/tests/UnconnectedElement.test.ts b/tests/UnconnectedElement.test.ts new file mode 100644 index 0000000..ab16ee2 --- /dev/null +++ b/tests/UnconnectedElement.test.ts @@ -0,0 +1,17 @@ +import { expect } from 'chai'; +import 'mocha'; +import * as core from '../src' +import * as path from 'path-browserify'; + +describe('In the unconnected element flow', () => { + let example_uri = path.join(__dirname, './xmlfiles/Unconnected_Element.flow-meta.xml'); + + + it('there should be checks for unconnected element', async () => { + let flows = await core.parse([example_uri]); + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults.find((res) => res.ruleName === 'UnconnectedElement')); + }); +}); + From ffbc94114c431f6d26c169f019d8d172852f4ee4 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 16:28:58 +0200 Subject: [PATCH 09/11] 3.12.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2cf17e6..9f9c6c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lightning-flow-scanner-core", - "version": "3.11.0", + "version": "3.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lightning-flow-scanner-core", - "version": "3.11.0", + "version": "3.12.0", "license": "AGPL-3.0", "dependencies": { "@types/path-browserify": "^1.0.2", diff --git a/package.json b/package.json index 156db5a..c8e7926 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lightning-flow-scanner-core", - "version": "3.11.0", + "version": "3.12.0", "main": "out/**", "types": "index.d.ts", "scripts": { From 335a889d9cf05c1dcaacfbb3fe9db3fbfb1c5baf Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 17:34:56 +0200 Subject: [PATCH 10/11] add final tests and updat dml --- src/main/rules/DuplicateDMLOperation.ts | 80 +- src/main/rules/SOQLQueryInLoop.ts | 4 +- tests/Config.test.ts | 123 +++ tests/DuplicateDMLOperation.test.ts | 50 ++ tests/HardcodedId.test.ts | 2 +- tests/MissingFaultPath.test.ts | 34 + tests/MissingNullHandler.test.ts | 42 + tests/SOQLQueryInLoop.test.ts | 23 + tests/UnconnectedElement.test.ts | 2 +- yarn.lock | 1035 ----------------------- 10 files changed, 330 insertions(+), 1065 deletions(-) create mode 100644 tests/Config.test.ts create mode 100644 tests/DuplicateDMLOperation.test.ts create mode 100644 tests/MissingFaultPath.test.ts create mode 100644 tests/MissingNullHandler.test.ts create mode 100644 tests/SOQLQueryInLoop.test.ts delete mode 100644 yarn.lock diff --git a/src/main/rules/DuplicateDMLOperation.ts b/src/main/rules/DuplicateDMLOperation.ts index 7325378..f9b5d4e 100644 --- a/src/main/rules/DuplicateDMLOperation.ts +++ b/src/main/rules/DuplicateDMLOperation.ts @@ -1,34 +1,40 @@ -import { RuleCommon } from '../models/RuleCommon'; -import * as core from '../internals/internals'; - -export class DuplicateDMLOperation extends RuleCommon implements core.IRuleDefinition { +import { RuleCommon } from "../models/RuleCommon"; +import * as core from "../internals/internals"; +export class DuplicateDMLOperation + extends RuleCommon + implements core.IRuleDefinition +{ constructor() { super({ - name: 'DuplicateDMLOperation', - label: 'Duplicate DML Operation', - description: "When the flow executes database changes or actions between two screens, it's important to prevent users from navigating back between screens. Failure to do so may result in duplicate database operations being performed within the flow.", + name: "DuplicateDMLOperation", + label: "Duplicate DML Operation", + description: + "When the flow executes database changes or actions between two screens, it's important to prevent users from navigating back between screens. Failure to do so may result in duplicate database operations being performed within the flow.", supportedTypes: core.FlowType.visualTypes, docRefs: [], - isConfigurable: false, - autoFixable: false + isConfigurable: false, + autoFixable: false, }); } public execute(flow: core.Flow): core.RuleResult { - - const flowElements: core.FlowNode[] = flow.elements.filter(node => node instanceof core.FlowNode) as core.FlowNode[]; + const flowElements: core.FlowNode[] = flow.elements.filter( + (node) => node instanceof core.FlowNode + ) as core.FlowNode[]; const processedElementIndexes: number[] = []; const unconnectedElementIndexes: number[] = []; const DuplicateDMLOperations: core.FlowNode[] = []; const startingNode = this.findStart(flow); if (!startingNode || startingNode === -1) { - throw 'Can not find starting element'; + throw "Can not find starting element"; } let dmlFlag = false; let indexesToProcess = [startingNode]; do { - indexesToProcess = indexesToProcess.filter(index => !processedElementIndexes.includes(index)); + indexesToProcess = indexesToProcess.filter( + (index) => !processedElementIndexes.includes(index) + ); if (indexesToProcess.length > 0) { for (const [index, element] of flowElements.entries()) { if (indexesToProcess.includes(index)) { @@ -42,11 +48,20 @@ export class DuplicateDMLOperation extends RuleCommon implements core.IRuleDefin } dmlFlag = this.flagDML(element, dmlFlag); if (references.length > 0) { - const elementsByReferences = flowElements.filter(element => references.includes(element.name)); + const elementsByReferences = flowElements.filter((element) => + references.includes(element.name) + ); for (const nextElement of elementsByReferences) { - const nextIndex = flowElements.findIndex(element => nextElement.name === element.name); - if ('screens' === nextElement.subtype) { - if (dmlFlag && nextElement.element['allowBack'] && nextElement.element['allowBack'][0] == 'true' && nextElement.element['showFooter'][0] == 'true') { + const nextIndex = flowElements.findIndex( + (element) => nextElement.name === element.name + ); + if ("screens" === nextElement.subtype) { + if ( + dmlFlag && + nextElement.element["allowBack"] && + nextElement.element["allowBack"] == "true" && + nextElement.element["showFooter"] == "true" + ) { DuplicateDMLOperations.push(nextElement); } } @@ -66,7 +81,10 @@ export class DuplicateDMLOperation extends RuleCommon implements core.IRuleDefin } } } - } while ((processedElementIndexes.length + unconnectedElementIndexes.length) < flowElements.length); + } while ( + processedElementIndexes.length + unconnectedElementIndexes.length < + flowElements.length + ); let results = []; for (const det of DuplicateDMLOperations) { @@ -76,10 +94,19 @@ export class DuplicateDMLOperation extends RuleCommon implements core.IRuleDefin } private flagDML(element, dmlFlag) { - const dmlStatementTypes = ['recordDeletes', 'recordUpdates', 'recordCreates']; + const dmlStatementTypes = [ + "recordDeletes", + "recordUpdates", + "recordCreates", + ]; if (dmlStatementTypes.includes(element.subtype)) { return true; - } else if (dmlFlag === true && element.subtype === 'screens' && element.element['allowBack'] && element.element['allowBack'][0] == 'true') { + } else if ( + dmlFlag === true && + element.subtype === "screens" && + element.element["allowBack"] && + element.element["allowBack"] == "true" + ) { return false; } else { return dmlFlag; @@ -87,18 +114,19 @@ export class DuplicateDMLOperation extends RuleCommon implements core.IRuleDefin } private findStart(flow: core.Flow) { - const flowElements: core.FlowNode[] = flow.elements.filter(node => node instanceof core.FlowNode) as core.FlowNode[]; + const flowElements: core.FlowNode[] = flow.elements.filter( + (node) => node instanceof core.FlowNode + ) as core.FlowNode[]; let start; if (flow.startElementReference) { - start = flowElements.findIndex(n => { - return n.name == flow.startElementReference[0]; + start = flowElements.findIndex((n) => { + return n.name == flow.startElementReference; }); } else { - start = flowElements.findIndex(n => { - return n.subtype === 'start'; + start = flowElements.findIndex((n) => { + return n.subtype === "start"; }); } return start; } - } diff --git a/src/main/rules/SOQLQueryInLoop.ts b/src/main/rules/SOQLQueryInLoop.ts index d761e55..258186d 100644 --- a/src/main/rules/SOQLQueryInLoop.ts +++ b/src/main/rules/SOQLQueryInLoop.ts @@ -30,8 +30,8 @@ export class SOQLQueryInLoop extends RuleCommon implements core.IRuleDefinition for (const element of loopElements) { let loopEnd: string | undefined; // Check if 'noMoreValuesConnector' attribute exists - if (element.element['noMoreValuesConnector'] && element.element['noMoreValuesConnector'][0]) { - loopEnd = element.element['noMoreValuesConnector'][0].targetReference[0]; + if (element.element['noMoreValuesConnector'] && element.element['noMoreValuesConnector']) { + loopEnd = element.element['noMoreValuesConnector'].targetReference; } else { loopEnd = element.name; } diff --git a/tests/Config.test.ts b/tests/Config.test.ts new file mode 100644 index 0000000..c5a8bda --- /dev/null +++ b/tests/Config.test.ts @@ -0,0 +1,123 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('Rule Configurations ', () => { + let example_uri1 = path.join(__dirname, './xmlfiles/Unconnected_Element.flow-meta.xml'); + let example_uri2 = path.join(__dirname, './xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml'); + + it(' should use default when no configuration is provided', async () => { + let flows = await core.parse([example_uri1]) + const results: core.ScanResult[] = core.scan(flows, undefined); + const rules = core.getRules(); + expect(results[0].ruleResults.length).to.equal(rules.length); + }); + + it(' should use default when no rules are specified', async () => { + let flows = await core.parse([example_uri1]) + const ruleConfig = { + rules: + { + + }, + exceptions: + { + CreateANewAccountWithChild: + {"DuplicateDMLOperation":["ViewAccountId"]} + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const rules = core.getRules(); + expect(results[0].ruleResults.length).to.equal(rules.length); + }); + + it('incorrect rule severity configurations are defaulted', async () => { + let flows = await core.parse([example_uri1]) + const ruleConfig = { + rules: + { + MissingNullHandler: + { + severity: 'errorr', + } + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + expect(results[0].ruleResults.length).to.equal(1); + }); + + + it('incorrect rule configurations are skipped', async () => { + let flows = await core.parse([example_uri1]) + const ruleConfig = { + rules: + { + MissingNullHandler: + { + severity: 'error', + }, + MissingNullHandler2: + { + severity: 'error', + } + }, + exceptions: + { + CreateANewAccountWithChild: + {"DuplicateDMLOperation":["ViewAccountId"]} + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + expect(results[0].ruleResults.length).to.equal(1); + }); + + it('Multiple Expressions are individually checked', async () => { + let flows = await core.parse([example_uri1]) + const ruleConfig = { + rules: { + APIVersion: { + severity: "error", + expression: ">50", + }, + CopyAPIName: { + severity: "error", + }, + DMLStatementInLoop: { + severity: "error", + }, + DuplicateDMLOperation: { + severity: "error", + }, + FlowDescription: { + severity: "error", + }, + FlowName: { + severity: "error", + expression: "[A-Za-z0-9]+_[A-Za-z0-9]+", + }, + HardcodedId: { + severity: "error", + }, + MissingFaultPath: { + severity: "error", + }, + MissingNullHandler: { + severity: "error", + }, + SOQLQueryInLoop: { + severity: "error", + }, + UnconnectedElement: { + severity: "error", + }, + UnusedVariable: { + severity: "error", + }, + }, + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + expect(results[0].ruleResults.find((r) => r.ruleName === 'FlowName')?.occurs).to.equal(false); + }); + +}); \ No newline at end of file diff --git a/tests/DuplicateDMLOperation.test.ts b/tests/DuplicateDMLOperation.test.ts new file mode 100644 index 0000000..1c1ec46 --- /dev/null +++ b/tests/DuplicateDMLOperation.test.ts @@ -0,0 +1,50 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('DuplicateDMLOperation ', () => { + let example_uri = path.join(__dirname, './xmlfiles/Duplicate_DML_Operation.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Duplicate_DML_Operation_Fixed.flow-meta.xml'); + + it('should have 1 result in a flow with a DML statement inbetween screens ', async () => { + let flows = await core.parse([example_uri]) + + const ruleConfig = { + rules: + { + DuplicateDMLOperation: { + severity: 'error', + }, + }, + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter( + (rule) => rule.occurs + ); + expect(occurringResults.length).to.equal(1); + expect(occurringResults[0].ruleName).to.equal("DuplicateDMLOperation"); + }); + + it('should have no results in the fixed example', async () => { + let flows = await core.parse([fixed_uri]) + + const ruleConfig = { + rules: + { + DuplicateDMLOperation: { + severity: 'error', + }, + }, + }; + + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + const occurringResults = results[0].ruleResults.filter( + (rule) => rule.occurs + ); + expect(occurringResults.length).to.equal(0); + }); + + +}); + diff --git a/tests/HardcodedId.test.ts b/tests/HardcodedId.test.ts index 9677e93..c5dcd97 100644 --- a/tests/HardcodedId.test.ts +++ b/tests/HardcodedId.test.ts @@ -3,7 +3,7 @@ import 'mocha'; import * as core from '../src'; import * as path from 'path-browserify'; -describe('In the Hardcoded_Ids flow', () => { +describe('HardcodedId', () => { let example_uri = path.join(__dirname, './xmlfiles/Hardcoded_Id.flow-meta.xml'); it('there should be one result for the rule HardcodedIds', async () => { diff --git a/tests/MissingFaultPath.test.ts b/tests/MissingFaultPath.test.ts new file mode 100644 index 0000000..6e92bf7 --- /dev/null +++ b/tests/MissingFaultPath.test.ts @@ -0,0 +1,34 @@ +import { assert, expect } from "chai"; +import "mocha"; +import * as core from "../src"; +import * as path from "path-browserify"; + +describe("MissingFaultPath", () => { + let example_uri = path.join( + __dirname, + "./xmlfiles/Missing_Error_Handler.flow-meta.xml" + ); + let fixed_uri = path.join( + __dirname, + "./xmlfiles/Missing_Error_Handler_Fixed.flow-meta.xml" + ); + + it("there should be one result for the rule MissingFaultPath", async () => { + let flows = await core.parse([example_uri]); + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter( + (rule) => rule.occurs + ); + expect(occurringResults.length).to.equal(1); + expect(occurringResults[0].ruleName).to.equal("MissingFaultPath"); + }); + + it("Should have no result", async () => { + let flows = await core.parse([fixed_uri]); + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter( + (rule) => rule.occurs + ); + expect(occurringResults.length).to.equal(0); + }); +}); diff --git a/tests/MissingNullHandler.test.ts b/tests/MissingNullHandler.test.ts new file mode 100644 index 0000000..1c368ca --- /dev/null +++ b/tests/MissingNullHandler.test.ts @@ -0,0 +1,42 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('MissingNullHandler ', () => { + let example_uri = path.join(__dirname, './xmlfiles/Missing_Null_Handler.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/Missing_Null_Handler_Fixed.flow-meta.xml'); + + it('should return a result when no fault path is implemented', async () => { + let flows = await core.parse([example_uri]); + const ruleConfig = { + rules: + { + MissingNullHandler: + { + severity: 'error', + }, + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler') + expect(results[0].ruleResults[0].occurs).to.equal(true); + }); + + it(' should return no result when null handlers are implemented', async () => { + + let flows = await core.parse([fixed_uri]); + const ruleConfig = { + rules: + { + MissingNullHandler: + { + severity: 'error', + }, + } + }; + const results: core.ScanResult[] = core.scan(flows, ruleConfig); + expect(results[0].ruleResults[0].ruleName).to.equal('MissingNullHandler') + expect(results[0].ruleResults[0].occurs).to.equal(false); + }); +}); diff --git a/tests/SOQLQueryInLoop.test.ts b/tests/SOQLQueryInLoop.test.ts new file mode 100644 index 0000000..3c4b509 --- /dev/null +++ b/tests/SOQLQueryInLoop.test.ts @@ -0,0 +1,23 @@ +import { assert, expect } from 'chai'; +import 'mocha'; +import * as core from '../src'; +import * as path from 'path-browserify'; + +describe('SOQLQueryInLoop ', () => { + let example_uri = path.join(__dirname, './xmlfiles/SOQL_Query_In_A_Loop.flow-meta.xml'); + let fixed_uri = path.join(__dirname, './xmlfiles/SOQL_Query_In_A_Loop_Fixed.flow-meta.xml'); + + it('there should be one result for the rule SOQLQueryInLoop', async () => { + let flows = await core.parse([example_uri]); + const results: core.ScanResult[] = core.scan(flows); + const SOQLQueryInLoop = results[0].ruleResults.find((rule) => rule.occurs && rule.ruleName === 'SOQLQueryInLoop'); + expect(SOQLQueryInLoop?.occurs).to.equal(true); + }); + + it('there should be no result for the rule SOQLQueryInLoop', async () => { + let flows = await core.parse([example_uri]); + const results: core.ScanResult[] = core.scan(flows); + const occurringResults = results[0].ruleResults.filter((rule) => rule.occurs); + expect(occurringResults).not.include("SOQLQueryInLoop"); + }); +}); \ No newline at end of file diff --git a/tests/UnconnectedElement.test.ts b/tests/UnconnectedElement.test.ts index ab16ee2..73df446 100644 --- a/tests/UnconnectedElement.test.ts +++ b/tests/UnconnectedElement.test.ts @@ -3,7 +3,7 @@ import 'mocha'; import * as core from '../src' import * as path from 'path-browserify'; -describe('In the unconnected element flow', () => { +describe('UnconnectedElement', () => { let example_uri = path.join(__dirname, './xmlfiles/Unconnected_Element.flow-meta.xml'); diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 964ddae..0000000 --- a/yarn.lock +++ /dev/null @@ -1,1035 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0": - version "7.24.2" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== - dependencies: - "@babel/highlight" "^7.24.2" - picocolors "^1.0.0" - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/highlight@^7.24.2": - version "7.24.2" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@oozcitak/dom@1.15.10": - version "1.15.10" - resolved "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz" - integrity sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ== - dependencies: - "@oozcitak/infra" "1.0.8" - "@oozcitak/url" "1.0.4" - "@oozcitak/util" "8.3.8" - -"@oozcitak/infra@1.0.8": - version "1.0.8" - resolved "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz" - integrity sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg== - dependencies: - "@oozcitak/util" "8.3.8" - -"@oozcitak/url@1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz" - integrity sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw== - dependencies: - "@oozcitak/infra" "1.0.8" - "@oozcitak/util" "8.3.8" - -"@oozcitak/util@8.3.8": - version "8.3.8" - resolved "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz" - integrity sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ== - -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/chai@^4.2.21": - version "4.3.14" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz" - integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== - -"@types/mocha@^9.0.0": - version "9.1.1" - resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz" - integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== - -"@types/node@*", "@types/node@^20.4.5": - version "20.11.30" - resolved "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz" - integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== - dependencies: - undici-types "~5.26.4" - -"@types/path-browserify@^1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@types/path-browserify/-/path-browserify-1.0.2.tgz" - integrity sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA== - -"@ungap/promise-all-settled@1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" - integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== - -acorn-walk@^8.1.1: - version "8.3.2" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.4.1: - version "8.11.3" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" - integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ== - -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -chai@^4.3.4: - version "4.4.1" - resolved "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz" - integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.3" - deep-eql "^4.1.3" - get-func-name "^2.0.2" - loupe "^2.3.6" - pathval "^1.1.1" - type-detect "^4.0.8" - -chalk@^2.3.0: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz" - integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== - dependencies: - get-func-name "^2.0.2" - -chokidar@3.5.3: - version "3.5.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -commander@^2.12.1: - version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -debug@^4.3.1: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@4.3.3: - version "4.3.3" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -deep-eql@^4.1.3: - version "4.1.3" - resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.1, get-func-name@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz" - integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^7.1.1: - version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hasown@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@3.14.1: - version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -logging@^3.3.0: - version "3.3.0" - resolved "https://registry.npmjs.org/logging/-/logging-3.3.0.tgz" - integrity sha512-Hnmu3KlGTbXMVS7ONjBpnjjiF9cBlK5qsmj77sOcqRkNpvO9ouUGPKe2PmBCWWYpKAbxb96b08cYEv4hiBk3lQ== - dependencies: - chalk "^4.1.0" - debug "^4.3.1" - nicely-format "^1.1.0" - -loupe@^2.3.6: - version "2.3.7" - resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz" - integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== - dependencies: - get-func-name "^2.0.1" - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@4.2.1: - version "4.2.1" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz" - integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp@^0.5.3: - version "0.5.6" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mocha@^9.1.1: - version "9.2.2" - resolved "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz" - integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== - dependencies: - "@ungap/promise-all-settled" "1.1.2" - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.3" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - growl "1.10.5" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "4.2.1" - ms "2.1.3" - nanoid "3.3.1" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - which "2.0.2" - workerpool "6.2.0" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@3.3.1: - version "3.3.1" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -nicely-format@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/nicely-format/-/nicely-format-1.1.0.tgz" - integrity sha512-nZk4ea8ZeH6KKpfzhopC7sC0KeN2+QZQIxp2jvElndkyXuM3pJqB8I4fTypkWCyeKBJRLdQ1h/O2L48lS6S6gg== - dependencies: - ansi-styles "^2.2.1" - esutils "^2.0.2" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve@^1.3.2: - version "1.22.8" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -semver@^5.3.0: - version "5.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-node@^10.2.1: - version "10.9.2" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tslib@^1.13.0, tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslint@^6.1.3: - version "6.1.3" - resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz" - integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.3" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.13.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - -type-detect@^4.0.0, type-detect@^4.0.8: - version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -typescript@^4.3.4, "typescript@>=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev", "typescript@>=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev", typescript@>=2.7: - version "4.9.5" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -which@2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -workerpool@6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz" - integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -xmlbuilder2@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz" - integrity sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw== - dependencies: - "@oozcitak/dom" "1.15.10" - "@oozcitak/infra" "1.0.8" - "@oozcitak/util" "8.3.8" - js-yaml "3.14.1" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yargs-parser@^20.2.2, yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0: - version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 760cbf8e4fe28b7b71a2f9688eff83b161bd9197 Mon Sep 17 00:00:00 2001 From: Ruben Date: Mon, 13 May 2024 17:43:38 +0200 Subject: [PATCH 11/11] update readme --- .DS_Store | Bin 8196 -> 8196 bytes readme.md | 25 +++++++++++++++++++++++-- src/media/bannerslim.png | Bin 0 -> 49818 bytes 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 src/media/bannerslim.png diff --git a/.DS_Store b/.DS_Store index c49f0c037e97a35a7003096029c181c8197d09ff..e35bdae86879b80346224bab2efd1908dcc60c54 100644 GIT binary patch delta 52 zcmZp1XmQw}D!{m7vYJ34w?uWdxq+#Uf{CH|` + +The `parse` function parses the metadata of Salesforce Lightning Flows, Process Builders, and Workflows from the provided URIs. It returns a Promise that resolves to an array of `ParsedFlow` objects containing the parsed metadata. + +### `scan(parsedFlows: ParsedFlow[], ruleOptions?: IRulesConfig): ScanResult[]` + +The `scan` function conducts static analysis on the parsed metadata of Lightning Flows, Process Builders, and Workflows using the specified rules. It takes an array of `ParsedFlow` objects and an optional `IRulesConfig` object as arguments and returns an array of `ScanResult` objects representing the results of the analysis. + +### `fix(results: ScanResult[]): ScanResult[]` + +The `fix` function attempts to automatically fix certain issues identified during the static analysis. It takes an array of `ScanResult` objects as input and returns a modified array with any applicable fixes applied. + ## Configurations ### Rule Configuration diff --git a/src/media/bannerslim.png b/src/media/bannerslim.png new file mode 100644 index 0000000000000000000000000000000000000000..24a851a26893509f806705b30591f6ec3f8f3222 GIT binary patch literal 49818 zcmeFZWmKHYvM`J#KyW9)-QAtw?(XjHF2OyxI|PT|4#5Tw?(XjH-(>G|?!D)%&9Cq8 z%X${m(^g&8rCt3@n4F9#+@~*}KtMp?#KnXZKtMitf`EYHL45?)AbvyZ1Aai5ewF?T z0#Y3V^Q`{?_#NL+OhFn1#Df$B#4iv8j%#q@PC&<@&0sNVTzLh0Rh`FS5k9Qla}H%w6&(yH?lP_rggKn`_lo0+l>=g zv^I9q$9J=~vT@{e<01U32Pd%nr<#rs|F14imOO-N(sKBMwhqSlthDsB^n|>h@bU4v z9gIvk6@*0oH5~YjhtSN)$&Qnb&eheG)|H9Y*1?pHfrEpCj-HW@k&y=2gT~R_#!26e z#>SE8?@9hWkC3sWp@X@dlew)8{-1gE4Q!pAcnAsq0Q#T5zt`zxZt}m7Y#jfE77#(Y zKP_|&wDffUG|bq|{GDNcTK*pP7hZpZa2(UEbgQ z6^tEit(^a0p=@LB#LM`vA^%nV-=kz5%#DF$`7`W)p#0yu|L!kmX6s}N+#&~aLvb4? zV+Y_8|26vG0N?NNf9CpwH>aGro3WLekh!(7&EHru(=&0?{bSRA4;8evvUO0j(>FB! zv+BQw{GY1-?)?`a_5TIL$j8HUcV1dX2)m?tA_VLShbfvD1S8q{9hU%Q=d#ASr@z?1wV~gqT zyQ!&XrzgL8pN^RbrHJ{#{@?TeDDeNE0tb@(g|>6^wYw7QDNB3xRSS0`#g%H$=LM5# z?#ra0$oTI(=gA;Z?XQ?!u>V{*mg774&? zMCg4{u?q!aQE@DX$$pdC4I4YPk?Hv**e3)1b5KBzHd7BsdR@8T8Xt1SY5?ec1^9=F zyKrBQ!t&IpfEAK==z*W_y>O1xVQ$4QYY-07=cC z_H!^{VK+~?vzImS18p-rypJ(~0+p&HN%8Ma=12mZ%yGq$<&ozSu;(d^b0^Wu+61vs zw1rYGKQd|omc211sc~SMx4;oG`)cC#q3fSl1q8q^N%&`BE9n76qbI0#JzGe58y;?F zKA=5zX$Nv?c}q`q3UrjJqtM4yT6I>x6NY~5Lo5-$OE^B@4j++?q8?E`?;dBcLVk;{ zreBaYJCyP=TbIsyu<3os%+Eh1DtmR?c^WLs|M)I%ntcIdzGa2GYtq1BzFE+ZPQprv zD=D65s2oCVAj>i0@Ij0@_~dT1W0-taQza(;{yZLk=6T@_T?jymH#HSmGWL=;_vYeu zmkpyY@(_~C>9 zayXX$_6vNA%KZF_BNeMHGg(ZIpvS*ISkLcE(v<+w8+%^pfT&m z>^H>ZHUivc&c5tqN4A!}OuX6zB<$=eMDMVI88i@I>&=jdA4(JOt;ZI%aREF zbrBLTy;h++TYrDoh(P`A8FS0|`V|U#kiCZF$Zx0g&zn;XArLi73o0^7m1popSbUc7YOvdv>!mHGfd+U>yH}9Ddr;Zq2iqZwWc{*3{Rzp-Dnp^UNz*! zLXvEpY_OOvUd4{3FgDg^ybEzAAQ4s1%6 zn?)%3G(Ui!trk2k7*J6Kv3ITzmrdah9&-yR{a6duz3C7c*-?(sxloBP9`JvUH40cj zzj$Kl-@&%-q+ZpjbP6aEJzL1ACW-f%4i_3MIe44{pp_{^zu`Pes5HjLg~=hDk3=a7 zwr@i1QOQP>ooQX{qhTE-8i2mLCk1|fwknmV*A)w8*dD{R0SuvQp-C`apCe~OyEI`D zR?!ryEi1$lat-2l4vlujRpxS)gLP5P=CTVUbM`{~y(hBi(wPc(ASG@gztq2{!HC6y zTR{v8DD`pKpIM(B_3SLIdjfBY+U<)ABa;>FQK_tL0Te3U=-kIr}$nETn}+Y6?(Whkk( zEkdNwU~Hb4t13!GLn%j$1I6BqLtOQi8aL4)%eYeF*X{-g&%%3=5+DE^iUkuN#l53B zm5_jX(;r-ae%f@bzf_adO0Wo`R8<)$-DD)$9RxNH9YV@Kbx=?S_Qz!}KSrXFwc>AN znaRU2GBH*@-QS_y5tj#|y++3;K5LCvnB{N9^l3BnV1>k>EU2Z@(GPzkQ)I1=Y;p9zI1Mu$M@YTxYd>|z=c zzN6If{hOf2Yv;fg*3D%RoVE5iLgDKXtBC$s5%|i7@O<<${3-9%=sV#p_ zLS^To$amxIvPe#Oy^RfxED5~5ZeE=cKTKIQ# z0{;;aP>@EvD`&<_#(w{Lbe@vO#v_8zshF=(l31S@o^NB=XegCJ8D{ex_y9DcSp!Xt zo9F3um$Ad>WD2Ry|GZj12n`JXd)U+pztI$P1mlFJOuR0+PSi8ImGFS`U2k#1r-ok5 z#7mkKKZR(cI}Tw7kEky4t=B;ur^K|HM}%Y=tFBOX=JyN>9#pTj`(^HEoic;L@opHILh0mwLW{KZtLO1@LnCV5;p03 z)BpqSAPPj~Yf0V|Ex3*|zmG9ttQ8?uKUGBNxr!#2Yh zgN+7F6&{C&?9B=>_ji`;Kl>GboHKagoLm$bq*QUs@nR_Ku~EA_l|%;@8qM$(cwIq~ z`%y%PL2yIui#01*>C(!mbU<8jd5YmFAFmIN^x^btwY$#66|HiV2I{^?bf83Pv{&CX z(eceyGS*%i|70i1BI>T7jt$7>CIfm87fSim(Cf{9N#~W$2C$u!@)K||1+K?+xJb*Z8NR#UTRxEyFR8Zr0vmFpJ$?HZ z8C@uRa-Sj%?*c#KoxUnT~ZS^N_i7vUa*tGi^mbD00UOQ z>iMd{;PJe!57%52V z*9hL$%DtY90?-#WlqqE_#femEjruY zfv7GkZY@h@HR>Gh4x0z@1!sQpP&`LC;W=&PLcCtKvE}NoHu*OUr@@y?;ji7wd9$== z>Z@*+xg4qPle;OBB;S`9vS>quxm3%&t`%y3;iJ4KBUGg0hX%JM2yNS-$7fiZ3wy@G z5rtMgniopqI_ME@B{#!DF+tLcZVxuwrtSP)E% z8!uc^pB7!>M$=UcDr%S+4bmB~J(Kn&ZBf*38;WCAuVa%MDRJN=cPi`S!i1MHMzqd8 z%^-uyKi0??R=PXy#gR2@JDrM|vqB zoS|8NOB6e?7n)&LSv=$rdxCY+nk_Kc#(HABT-Yc{+op#ie!}Gv57v9V(sUXxRQjab z?{?K4uMrJ-)K?Yiu}AW@^m8KA8+Wx@Aaztuy@j}N{i9^cnVpBC|=~$^&<*t6};V2xu^}l&f64LPeRrHT>yoQ;`IP-LVoetKm2pb=* zC0&k6TJhP^e|$2_5Z?O0N2NnLE-o*I{ll5!n%=nhbRVz${P|#Q`cVWLA&K9 z(YY*Htf>YX-FkQksd?XHB9w#rEB2Sru`=`*mK&J!1;k1E`_sU#MsM3dr-51^^*G7< zISOA6*tk2MRyqwYSV`Yir9wGuWQ6&gBXF$}LxRqBNfKx6Y}W^g+I^NY=h zOZ^euo7M_7V=9sg4(*Ro-(R6T*G-3Pr@pFqJ%5C)@Uf^6#X#4eBGV;id=-h!5X7w| zwK-qr3w4+>t8VI9aYgEJ-P0J{H?ut#o-yRY^PQ2w^jhO85B7a;r!{y%i%1X{$nsBY z^}h<`XtpW=Ba9UG_Ja)6&81RPA0h>Lm6cH!ZK29$lzeWCiO`B3Br@*aEbm}qt;UY< z1^O13$3WUhk~L zN-UcPUJj^$Dwm!H?Gd}aOrGr@7>L`cVgDRnh~=;#n#BTE^%b)@KF}S#4Y@#yNV-Z6 zUOxQ1`mtg8d;@3jMCx|`DpOGN>#|BO`v5S>_Q8b_*R6ORFcjpxMWttZo%+Dw49FU;&%}myuDfdf>0nZ>jABGjo-Tl#au<;UauYi-vES#I<^wLO>UK z&2o7*_1#6&`|C+!Y5qvR;F52tnrT`t##UohT@D9V*`&ZYT*V7suFShy>ViSbs&uCp z+U>%cu}XKVRTdGC(D?;Y-mgPjI)^_2^F~;@%sX3_d|MOuqA))D_8q2h{K)c-qG1de*~SDWA?osq%+U|7=P?pqVAXN^~d6kg8!@A5xF%6=D`x)oXTj6{@XM zE8Gru5E~nYP-fgt9}{oSkm}cC2-Ep)gtx-zlJIv#t=lM2B?Ro;Qw>S@6F8bszN} zlNKWS8J8Ou5Gd*%7vbFaHsqJg-->&D_K@zsJ4L;@9}}8=(DP%(Eyhv}*Qgchb=#!$ zJ$~%NT3`CpD8bScgdpj&3`E z3O!U)-JoN!pt~3Xw*jdD_FV}kUXS_kv!tKb-9-=Rm3K}=OSix6 zW?U^X)ggThbZl=mMK@cjm!AGTn&)cMwMIiYFQeQ93Q0gn`?8rCXDT3lpTO&NmVJ4# z>HAPnk@Usw*CD*NkaHlU)gEqM+3T&)v0?8KO9qw%eM%VyF6u%}B|!-(4Gg+d@;7-^ zHBW{uNZ+1tQCi<}ajsFodumWYAV(PUk1aW7tB-rKhB~lIJ$_mrybhaMk}ImlOyfQK zf`nqos-kg~JMb(jEQ~d0wqkp3#<2yX+IJ|w?7m}6a{0W)2lVy`Pg}&5_a`N<6LnDr z2V*Ks`c34=-gJz7A4PcvPB}Cjp0YoCVmmwDHFph!&LGHip@6#$Cn`k*xS7k zi!i#BNTy7vNy>DS2K*~n^Q7sn)T@i7%Y;5gMz*tS_S+D)2ZsU`T|v!7WZ{#GZE`ey z5^1|!`s^ioH_`FJ%)k>kz`}d5f^ea^`tIV8WF}arR!x&h49Tq&a?zbs^ft z<3#H+;bD~iJqf782OC|TUoszIk=6HwZCoG&hO@Dkn|-W#2Skn_Fy$3O&kI@L!i&97 znR4Tx`F!frrlGQ}wyOCzo=lsdcc)xhH4c}^Hdj4&x=AdzfJS68%q`Wvbywi!xj_Bq6F}F&~EQIzZROwb8x)iC7&>2GB zlZa+yv)RAY_6zba-~NvsnhjMJU#TWWheK6aSlv!a(au!*Q%@q@YU>q6&|y2s!YJv` z78-J0%q2QRtL+vZ>+vMW-0pX=0vxf$TQzvS?noYt2FvWHB^0IuEt`&SDPgs}R zO6wxPbGC`Mz@yRXVE3S9KYWKXXl0{WN%aY!Owon;81w6!R(&^3`q_&}sKuJF(F-Fr z@7@ouK)`yd{)s|ZAXTB@o&Yr9GO1!F0%wVB=;+N$i`DBn|d7a1l~TQ$;W5(|L0#ZXp+RNfvT*%o!;GF&dU$fU!d5MhZswnev^8i#_h zUxqvLD8G}BF>`Sm&?}ORCD*=J^jUtXkX44e!K3i#mJZ#|z-iU);tb3k%twBdg_stn!fP&1?PIO}{Kfd6?M%)Ml3m)?_mH*AI(zG&4`W=y8z*Wi zfhmnZ2UUyU(3TIq#8$r+_eEIut&>puiFvV@3h|@s*}ZsL zMDGLZ8!Qh#H|c4|PD_Sh9dMmiBnov)99-~D-xo`-v=hPX6i6(lf7U8FiO6P203B7X z&feEg9;ZyyP0B!90cAc8yLIgWXLBYaAM++<1T?F?5)UUrx-T@bUH$!()(h^RQ}f7V z`V6d+H&gi|1>0)0rn!6fyp3J*16$3k<~Mk-3NM+C>gQze7;hG+zO=?z#k?Z~zkIh!(kxBPT9}1132Ob+yH~=^YbRp$XGo6>yN`_11POv^M+X{FY+wcoYUbDd1;^`OjhN z_$Mf4Dj;`P(F}YWyewjU>Z>4+t$};1MzYRgT;RxqS&VSnr?hw?jeXP0tWb-n!GSlW zKR}O-EZ^l&S<=CPNA+I0J4DdcZ_9nVDG&oWLT)$;EPT1#z{@f(YgZpU5Nl4T^zA7f zyO+M9w5RISCy^p}FIK1{S;zTA5Y>W9O_%;d81CnR!a*>buqc(aP!jsEHoZ zVg<*7FCo@C)km3K#i_sehh9iYGk>(-%OaffRfWL)NkjU1Y)6qSwBy`k0$|7%8#oSs z*)2#jG_D!-Rq~+4*YJgANOnS0ZNt)3Y|6?g4q3O42zDOdH-I<$# z*9uWajm_B>oKeGMTZT5gBS>O>%#78D|;Qtj=c{oPAwM1StnfvIkiWJV^p^Hk31g0axN zBlfcU^8qA5^W1^$T(6@!{fem zY%&ru_=Sh22QU~?06L$82i`Sza`n%hU5%r!Gl!5xR=4OsAl{=JCz6<_;Tcfm93_{} z*{pMvfjJtW-^`jvBOr3JNO}qM@N{p{Vk_HA`=@i$_p6gtLp{3wH=(*`t5N>ohOX)9Iv8~1LK^XD_+3b(V+fv~*@TxUS+S%o!K3TVvUlF%ZK zhYVsRs`~~($)~mPMK$a%wht!HB8Zb+Oy(2=PT-0>JLK=(Tl%g7F}XO;RlYwT@zt^z zquQdXk3`3SrbR3Dz7FP%`f`;oCh}^zOz7^57ZAe*#%g!EHkks?w?m|4T-4Mn$r6q4 z74`I?3^FI(t#gY{+TMnL(w_#!`snX%avHLjr6HXT?^^?0<7EY2SY_`wtqPu0wT3D_ zvctrM8JHM-Bv$7O=GcZ+d3p`h7L?y8JlDO41Sd-rpI{bBDzG%C5m9iYI5stoe$Lny z{v=+6?uvdl7)yikuVcA|Z$3CcsY4!PhtOzMsNTun?QXSyeCV>w+vTN1hK~6C8;$3{ z1Syck46S5roaiFFu@d9vURLTz#;5Yas=ki}#@N!@DSA^-Z%Y)Skb9%6EGo@F)kf;rM3O&i3ry*2F^--pl263ga{H+lNItHM?fjC*ot;+rVD6g#o}s!GH~wVPbOWtUNrOO#Qa9 ze8elI!>lpkCx1o_0gE~HX}>L@my>=%E~JKUgK7MI4aP1t8cYcRI2029969jEBa3kv zRw?{WwhmS5mMg5cB$7x?g9x7sZR3$G@a#-$9(CkGL|v(Hb@o~fpWNjLCOvj`yYpZ` zkfxqIAhPk%&k4d7{%42J4sC~EJa$F zPk+>3wQ2g)&o5W%$Z{;QjPQ}n!jXmIH}GA2b+iN8`95RBb!D%7)e+dlSRUgINv;xOEGK`0P4 zJ@)9bjKd+5i1nlK?;gC{D~@|1(kgt^Zl#Y5@S_fe+hl(Zz4~I@N0bb#8H(lX<2qVFS)mB4uObxAzddIUF^|Y z>QHnwU&~ELtve%puwIn(@$s|=TfIZdmtmJ3*|RGxCyxhzavkn^X*C)#s_;gbem{%05E5Wk$XM2f75yBt zVPUxa!d)U5jVIEZfXU|PU@BW+*F8cquNByq+^`MrE4nKc=A#pa^|yCyE{X3Q*?!LZ z-QeVN_t#b==rgVC27XP6{>XltudTF`g_?K=I_z>ScVDPeQx`hm=$NQPIbBZGZw{E& zLlR(#O zUxeU0Fps7$+@Ike+Kzh~M7W`SB;2|o;y<Jb^AXgH`+MUQXHydr?$iwhB#NT+VDJ- zQBybV8c0vgQ~9FcnKtY29YHWk^>EyVVA; z;P&WgW%CHDUjD{UpF$82oJ}1dnnC!%noE7!%p2D?;dgYvs=s1318opdn+NV{y*~kV8@_vjsgcp3UoP3e zz=UC6pp+TV_eMAEmQEQnU1A-oLC}fcl%}dq1HmIDYvH4E^`>+OAL{~lzyHYm9h*k& z*dMU^5wSWHBJBfcZ761vZtD7idPOoi9aQ@^h3Nm>!SGK&*=L}b<~kJ75fKbfSXJ|a z%ZTioUF#xj>~u`@!Vp=Tyf0Nu`-}9yWWmh!k4ODLp=BYk8W{DbH+Zf$rJVLmjrWGm zSsdM}KQk$SuhJ>l>t@t-L~j zbz_@uZ3Jad}MF1Glm~!xpxDhbyjN`d|pSfu>ZP!#mwsegY8x( z3+GqP*v%I=U|eQTCE3=irW3#)BEz#?z(g1OTYJh^MlOFz+}h=2LY7pjLr}&0Qdj-) zln^@Pz|R7Pxy>|x`+ziiY(obUoQKXiT%#*Ps(-+PiH5h zk2cYuBN%$Tx=zx4DG0&HSi8+mZNO@DUy_GCwvR~@ogQ|;b(}I);M%!y`Ksw?JoRWy zV-s0|DYyNLbs{n4%y^f%7&pF$2@6$EzXg%Ldh*uO`6C;Aq7EZ987T5kGQ?PZX8g)g z+cUp*6^S_hL#SVh=hB7K%hUCGRSOeeBIy5|aZVHer6JXtc9&SLHs@EN7RaCyZb&!1g$oUio%aHiuT3v) zH3hQScR!-XmppeSpT!(R7@%yYMf$m{cp|0J5&ed5tEhWj%lp8z%8$uc2m#)@b;J`nF(WGmbm*gT7Tu}lMMR*yC@ z!N413=@E&2{!fqAzZVKs2m1?@;8_B@1zxYFrY>a`-^+F02LkF{6Wjf$82~_dZB3(2 z@6lVk(G?5C@Qir?Q+9(BdUhL4Uevct29)V<_arTle+tV}*d2iT32zyGPZz>dFI@ar zpf&qZ8{H6vA)RO_@lm6d!J$P-s`Zj{(giRt9*n!?-c+vyp|TZzykH5=8bzj{R6Vy`e`YV`McTz9M1(RK z2rH5;Wejfwr~z0Z1?o_bn1#yG>+`GUK9c|Eu_pdku=AAqo5QH}*WEmtE5SGMpA=;l zA(0)O@a)me4}p91r@QrDuEX62cxn_mh=0YF{P~Dx3WinT5Hj_jjg9yW+xj=BfqF;F zZO}SScbq_l;p&h;uUi|ahmw0SeN!z^#*rI5n;axg(w=4h(-U4t@VD9Wng5(7qG7K1 zxF_sb)M-j`6fh2GzALBWmCw!>(yn#yy4HQjiKF~`W4wsR3jjKz!_}*X3;;5~QN?J9 z<_15<+omQl6qv| z&N16LJBRCYR9tNAj0GSg+~4JJ5-V$>Q9_3oL%M2^&Fk0De1yC9^wpiFB3urHxXGXrD%n1{ z{^0(ZvCY@>^KxrN-RM}t^D-<2P0YY+K;q@W?#t!iB2SHHr}DGP8UaUi+$+!00MvDr zXOWh9Ku4O>PiE>Rm&CyuXV2}a%@^b-!Z>B*66>c*ht~p46p-)L|LamLJ}YRstzm54V@MF{zak|KB!5z-TlhAYul~iCygKDXg{^Hu8q)6i z*|`qk2*Emr?CtB@0vzT>rqI8NHJF^OU~D%k-5Cw|JyV@j@YGv8lBvDQ)Lc%eswk3b ztf$fqAzc$9WT+BkPHK+ors@TwVach#PsN;2dg_JhT)R|L>oiYM!+y83m}&^fU^_5* z=!ZcN7Zz6U_Rx?JuH{eHR40`AAsUKU7-LRhxXb<@;T(P@lv&{tA!(&+a)RbDjS%$T z4%Dnr&R}G_jLrkOeS4M8L|kTtx$iXBtcPB@+7t1-OAUs=xN-C#rw!s<%7uUfAdZ!JieZyQSU37flav(EExO zI)}gmiJUigJ{!$cb&hFgr({1B_j7r2dhb4GJ31dzlIYo`;VUDOG3A36$n+n&64=;e ztGG1LE)8tb2vb!v9i|~QJrBPTcUo5J6|B!m4X_Yl!M47Rz}&XnkLsV+TTeZYw_G2! zi&aGk@(>@w+6lWljx-C1n<(>1za?r`Vi%Dk+Ra(H@z$~7JmJ}9dq{n{0dUF?33HkB zJ&f(y4mpQ2YP(81cDi85w7GtF$rq$2Gp|Y*>UxnS@tN|}615&5(yleODQ4C&ktWe) zzu;{%NBm4&c^JCIh2UM3i{i-xnd!nqKPbQ@`ZuRjjF2!Z1DueOFT?l?R#U=4-?v0e^#4Lhm`Bnq_de!&K<$0hWIKeT-wgeTCJgY`g@m? zRoUO1ZyFDGd7a^9_QUhx@eH>nb!SubpfrNUm&bl1sc}t-?HlN7X%PP1z$o)0(cyDF_`vU8jMZ|QoBrg^;Q`Q@5C}H*zWJ4p6G=f+e8pAVGY{HyP|naFXX-I$>lG*gP-q|_`DuM{ zP+9Kbs4^)*^AxqOQQ~Wg924-4bF^(ebN3wMd~hFsURkihgA1+^JzFMCud3|bq|rON zoGcTq-IV7& z`f|3(`q>pxy^u0|ttW)tX4i1pcdZS-u7x+#XIpixiM{h?vaqfd{kY?R1fy&jFIeLy zi}~u>Olc($`WRvv#FZmF*FSXOnIJfpGFW0ag58%c%XKVG?Zu+5tyZwBTgw?57el+Y zN(r!4A`cJSmW?;bKB45=_uLhOct*N`nQ|lR^&%;MI?hpDsmb1$5eDizY6)AZP-T_H z_VSgEBdO5_%$xT4>zx@sC+J+;1-`vPp^{R2bc`Z$^z`9X0zqI;EoB#ZkYnP07K({Y zV6U&ebVd;qqt4><@|{;J(jm*~Dk#0nOL0qI@LSAB@U_*;?iFD;$v)LZOND(fOz0ng z@ z?pL$|9p47eG57Q90H|e;66X(RqtCM=EO5T1dpb;adXCV%XMzqs6Je*C-#+Y}w<9Uu zIL|xpcxAxZ!NtWpDV~*cuP+2UDB?|X1@Q9IF&O1Gqcb--{V20DNI+)Hb=zvB%%+zYCj@79VtGr6 zEb?%iG+JH@R|#`VGjfHS4sphJ?Oeeu;4NQ5E1yBhusm5`HL_>TP*`+B&L33iEnrh{ ztLv3<3Awj@IWX1o;)Evh;4EEc^35W0O{x4TV?JM{v+G-&Z7<~!?`sDy`?8J5T4$)^ z00>iFX`sKJDnaTR?r)sRRN3Fpi0V}va1VUeXi?N+1vRw!aX^n68q=U z{gVJS(ER}sHCg*B9ajmBQeMc~boc5yB0sOWQhs@3VZ5>KKH8?P-<1B)C-j7&T^`fV zd+n@`l8|$zbkaU89D{E14VKEs@`Q|rK~rLP!1!SY2sQQGJcX4}HJEfYZmu5_?)PYCVEFE0AbxA;oqLykl&ObSq0qdK`?lZMJW>v1mlvM1aCP zc*``C+G6&lvP`C|1@huGD(ztt`kp4+ujJI}>M0Q8e5Iu0BK$*<-Ln+67XDqXl^OOP zIyU$tA?#INRw31oqcEnkMMhh|a@wQ(EaVzbj3js7g)6dBEy}XZErf^cr_5Y!XHg}> zT~6cQJQu`Qj>i#>%DUJ~s%1kzHQDWF!L%gLsC4LGGTl)7;%F!%Y^X;Rb@|o%)pl5} z!1P@~JKma2bZVA@VVtBwOGL#{MOqbf_EXxljQX)rfb^*Yk_ur_} zupUJTAFYnoH4fY}dpqb?OPwRz-Ng95Abj`ruW`)jC;ede90O1jh3tL7{T*^8e`dpN zr){Cgq4T+LSu6cQUj}DtUyI#*R_!LM125)FbfXm)_!id(>nvpG;?$Hi-oiZp17Vo6 zhv}M*Hv@VVj1ID713VvuS?Q6?Eg5izEPr~7HMyJgw22)ro`3%q0R7e8>*`eRp={(+ zhMEB(;MbMNDB;y^2~{G~28tcmrL|T5ZVT_n{%y>;nYBX>{aG#1);n|>sCHdN+ZLJC=z)aJ2N6eoKEn@E?h=-Bm;4?xNE&j(P3`Irg{mCxvgapa9=P`J(56N$6fEBt zZrFcJzos>o8xn%hfi)i0 z&-WVz;iy<6WC5}=JMMcf8z5T52{Y9wWt}F`_cn{!QV2Hn$8dLg4i8!IX;AJQX76wD zpG0mya>=@hZh4Ng)s=0NNs9;0EJ&T8b`ub~w~kpd-mKx;>svvA>FYd~aD7y__HdZJq!C3d8m6X)Q+w-Y-D_Lg`vosrGW+T9iHT#`Mm9-`siipJw`U!$$-5 zjAb)iVae--)L|=UK9hQP}feAD!;@ ze12H_n9OXNiMt$J9RmEg;UlUa5@|W><-YlEBOECLbZCKr{cV}%s7%a>?bvRvbS)M) zR|Y+(loPEGY-yhyJ)=H}sOm_U(5veC_LDNF4!@-fT6{{?I_aD8_Je}}Q@n7$vhCK7 zT^N=n^NJ;JI=K2CqYE@_1lMo=cx*1IdR}-on0qPW9+vACku=%POShD`#JQ(#@zb~gX4k1gV9NEbIVWtoWNK?>=D z{LMJp4yz=8z-8R&{49x?>*-${SQrv=-a#Gk=*w>fsAMN!ekX=f&0Q3U;s}t`& zM8YYK^l%Sfuu3vGRe>KvJv**I)EoX7$@?G>Ny9`Wi6b(SyLh^v& zrD!$jmVDsm9tZTyt2aJO-EG&Ugp>vqQlW1|mAB?nJfu4z)%u=NP-{N4L7OLPoyAqH z0I!`nMeUX}+S#FW0s*-96&$bfY)Z3^ z?zMji_w6i7D@9rQxTdL};rqG%#jO~nm-h+jl)@)Y%~nBmI0jG4pk1*vTUA&yAU-*3 zSIuU#Kbmtjn`29y=(#q`y-2-w`&N0w$zI^*VLWy2DRYfnS=W|X^mZY#Lz0Y`$ zJ9h=;I5rl$H(&5Lsa62XDK8AU421eO$cx-lcP{l>NWTTi<3-Zso>qM&gG}tn-RRl^ z*Ua*8CvF-bGUJhah>c;RVmXP5U&G*Gs~S>)-(#i0x7`4!zsKr`!I=1f+JD(DZAPzf@X5a8_bo&Y{h?-|)VjUgMC zjd}-7#rD~0M0m_xx~{-3t>t(={eByANJHP%vGmjV(E@W?(q=Ue4|oq(hf)tSov!Y{ zN70hWwQUdm?*frVR}!n@6vx9P=WQKyXpi+u+@ZR2#Y+3U1&-`0HNKy8hJ0im73Z}} zWe~tL(2^?dQDED3t-rl4Cl+_P_GgTL)vDB~J*eHfM;Xecd=89bvRa&$Hw}-q_9IPOGy7l@V|Z-(#GJutVb|!PlUmy<9vQNWjRG5} zD^#Sg0qtp4e%O+AR@Qn5yIcgjkq>f&PT(kgVl+*M!J^AX*QC1eL2l#jNsH`nXeN+#qSmKgk8C4%OY9Wxdq*MZKh~viaYl0o`G3YzGMDP ztmNI=A2{v~?aCZQg`Py49ew(6rmW~X;<|~p!L=z6XMMHx`WCP&6+65K&+ z;*yd2B)N^MRNXwN*7hf5BXbi)+CkxaPs#idyj^)npg287lEMov#~BL7L%_GYwf(&Pj+Ibv>8<$sHT|(efHQskP@`w z8nGc@hU2FU_PfLg3~Ld0iR9%3^3GWoz;liuH$O>JFuT971pfaq z^%iV#bX~A$f&_Q>06~JgTW}}1d$8axgFC^4dw}4e!`!zz&I&1GNT}9wZ%^4=ubw;Dpfhs4pLsSLh zh4xS+%l-=tZSg-{+=9eR&RkC=;f-o`jT0`X1xlqqbnYNl0KyD$qkTMGsU9;Q?o#+$wBs-4}NwTU3djuA3 z*UT$XIFv(L-&2Ml}G7SLnasC>p#_MRGo!8D?# zn_qjr6{wI`R>}@YlXCes=G4Z=k$DvLBGGUt(=kw5P{wR>*0|3+GJbNcxy~u~F#2K@ zOS`ByEM#f6<6?QEr#BPQdsp7umZG5)=6V(q3$lc%TJ|iQ&-s1meKMpcGDJVQR-Ti? zvX<4mfTHgsL-K*xSwdf(<5M5b`1Re#^!^+*TLu64=0EmyL?Y!jP|}}6etY5e;;j$9 z-F8DC>rX-vKd&g#=l?1VT{}cxNfwG5hrNHq*?uMs|9bVq&9Fd#q$QVKgjX+E^#$yv z=huw&DL0IV_(U#?ox^v|{i!jQt*YOyTj<4(E8N;va(sn>75o=MIHn1dkQ;}?I}rmB zIE6fYe%)N5676yuXm@!dZz{ZJOB6GM!^DTrcOT)dusO|-J9SSbaWa96WW@s!E(Nc3 zKjAk%_SDw_!wf)F5oYIcW!j&mKZ+mekVKekR1bAOo7wqUa9>fTLHmu|@TC(WKW`U* zl3eW9-uJr@j^%}@?$s$1y#0;U1aV=PBg^IY5vVvChld@>G}jGz*;YDSJrlVa$WTOh zl~(I$V+VbN%hzgnCcgT8;Du=~-ly2NCU~)YuNgdF+r;q4pHPP4Hy-yDdH|@J_*C`H zI@eXbhYFmUshwR5AZE^q(E)<_=QP5?r!Ti8ed1krJ$zrIS_2?{%Wpy5#u$F0m?hx2 zF0rC0&$aZyUHf>iM|Et?u~`x$6kQ^vP1WNxyFzFw`6-vtV0~R_mQ;bBx`5?1zZq(@ zfAI^AspzaI?#E=2u?yM?fwE)OW(d5<{ zMNS|n#AyE09nJ}d7uhn&%lPdpchYPmx=6cw*DA?T$edp{s3%y!2f?AdM7&t8O7rGs zl)3{BC(jE0Vl}y$;*-JR!Kb=gsq9}o*v9lgF~2UxR*XD-$@?X~Uh7UXV+?u7XKQp*6LLMBj_G##bMtRzz7PQT7) zsM6^yVr?DLF7cz3{B>@o6rh1Buj8>^xxJ2G%-M!t=B@v=kI8qG)-*9E3ukHHOpfVk zR*v(uJI7^5eIs@R74BT1s9sbD$35&sZ?=jq`PQ{ZODU}sx@!e+vf~!EUJmc?y?rjx zXCm576!U}gNvTQ?UmL5vN#RZCz~wB0PiF%$d~Bro10%?-l^erw5UQ);SUF4Jq^R8M zZ7T~aaEMO{C$|wgvD0@YF+RuqPZYr(6zJ^bqbR^KRzej}VVoorRk6u47lhD_xqn6{ z0OYFWx=R@eu zy}<4HB2-Vb?yWO$Vm&%jm?tJPp+>mUIle)1Xz-_GqUif%%6uAH|QaIX6#`?)`AG1M>F0siC)KgN17f z6Y<{XvH_gf6H>Yi<|;PcI)X$&ad9qyKLJ*SsO;uj7$-rtp&9xh!irU|D;VYNh-N<^ zx*W_4Ub^QS`Q9!aPhKEG82hevf4#txG|QAKH%`Zrs+OO)keyJ1&xgGY&wtzM)C~x( z8znV5a~&zv6ct0A4rFdawcq^^c>lDmmz|b5<&wr1kN5AB0Xf^pEen=lpXAjF)Tu2I@G`hgVn;5Ytx(oXG)o@ z@QZnKi>%cP3N>H(7eOW?is0fml}&!Sc%$Mb>95*Ok9$-$L4Hkv^UAQbZ~oud799$Y zGhH4=5Q9*m*)4hW39)}C$}Mt7H3_R%>%_(rp@`QpgTiOA+_j8AFPfyNnqWMuwkCJ* z8QraGMYcVBoatW^fHnqr(XSy`d>5)~{!Y?>2?g}b^r)+RL0%izX-tG;T-6m@;rAsU zoLxxS;*R)5+*Wqs^D(wcU6ZZHojE6Se?e-T#Ts(!yt`0iP>^I~{cNV6&ob9GSuaSQ z)&EXCsHd?16*1jS5>tZFVN>hSzF{l0teU^&SiywCV{|;+AUa6A(%mz4#*XKJXjcGu zG4P_Dcds`C^Mm1#Ja(8~i(@JM<~SXu^3w9nTUxv0Fqs$JHrr9vp2KO^O;CwlE}bJq zitWRWnD?w%axLml8QY1==Sd=)N3?v>nb3?k42bH@19PoICcxiSNeBl+UP>M#)b#lU z5wax6=F*N6*?Q*4kTiR#NB=wBC&1SJtksW$tKSukZF-W1&3}wRkB#h8ZMri3?uv0t z{Ke0=dUoZotDLWF*DJASA?HyUf9_Zfn>^YqE;jX(&i|;jdIbqhY!v_q_&?sUTJN88 zyA$|#Of&ZI2k_g;Lb2-!WUQ(JE}oVXuS7v~qmL-Nv;7~eUBLrR1)3=GQ1^x=>4zpP z!1j?8ohf@SVYv9U37rV7$j#CHN<;!q$@*wlp2@P1U7ZrF^Q%yyHMreWze}bi9_!}@ zNppvH5qVA?WdOX$TlZeBQIa^px~Fx&C#i^s+@LOqF7(kclS0o*o3aUalb0g;K~2a} zg-NaIYPKNk&R4I<*~ktQ(XOADRxfdd?209#C`aG)qjKf&2AiciWtq^J+UuUXo+b~!fV}!UjZoKa61U?`gBZbkk^kdB zb0OiErKZP96oKsL^|#Yf)V8`}>kibT`7vJdWzV$1G0+ZpU%$yAKHJ@w*Vv6r>vFJU z7kChGIP2N$_RcdkIU1gITyo8no^o=z`hg+H!q@d!~YMUN1H=)ztPT8CEt zdR9^63Yxd;3IlzlZWdsexja?bB#aG5nSXHi7CcO^1xCy-_!S*`mO9mI(jayvEw21% z5;A8MO5zxP-3WPujhbWi0aiO~c5hlJSm51;f<^zNuvIs39= zQ)Tzv4%I%Pbp=9yY|CUIm>6PNW=K|KTIz+3L1pwyqkPY~UTCg37oT4k8lfR|C6U*; z0Q~fL#Ow^GJJ7J`+XP zbmWTZUl7_5AL@NVhICHweG1R3ZodD9zf0-c8Jcm{^XKC115}w|c-oP7(LjQTRp}`- z;-rItAyKd*c9!!W138DX@TaYrt+19cPZJPQzS*2=O3EwynED#yFMA;o`I+6})U;FG zu-mcyl#HfT8~G7+d&Q=u~mbblMFWg@ABDaz=fp>kRc*iz@e6`(r;%D@#Qd z|5HHQ2sLw7gSY8^$GV$?DVW2Q5&TmfG7wmn0pO~u)fOg0-}8N_sf89-OSwwCbv|4u zJ&(P{TmcX2mDH+SM*PyeKjb-eFNXm$JWH7HgeKkffh3zg6F~^leN>zPrEK>P!+6)r*orn1d=1nrI0Bo%QxaJJKGf*u|)$6u%K(h1O5(&PkkXvi%nPwHF4~k58+yzdIbt7beW` z51e4+-Fi-_$-k@FL_-l@J`cT#zK<84Xdd&Bk?+Y7D8j$=_p3&ZVD(Laf4KS4Z>H8nSMUD#E)wxi1 z!lWM~^YAkWhZ5^W?<#dr(8YAj43s-gBhlaWKO(CqU{H{>pm&_iZ_Zb8L8l&+zhpXF zCJ7@(*H0^%9ZR`=I@7kLYPthC$MK={$;7?Fj7^p;<55&EGLrzwuPwIw(;w%iPQd#d z@&+Tf1g{9=0lxC@UIhktP2F_v?laf>+&Tgta@J$|GTN@+QbJj#~%zmzS zk$W_2w?5I-Le#apPblSHU$c)!3+3U(aX%s-V#mm5!^_aD{(vIei7AGN;C1EOh21|U z_QgrPyPuBBtR0xsUlrmv#Dy~;XsZr(C7?-zuv@wR5IOmjbB)PecUZx@clzg0@= zHe06OVqc$oid7;PecwSZ3J$MxfH@V$p>0!T4gtcW`LZJjDDFd_%usKmX>Aw0k}FdkmZOVeK?F><{w9RlUOgz23hTB zGM3*4rRDk3UhIe4iCmLx9G1J!9`+v66=j$XX?<&S_N$B~y{pIeTjj{~Z-6&<(y6dLal1ub{YpNc-OZaIFgPz(nQaFuKlL>r^}CEG=y zNwh!QDJTec{W(IdPZpME;?yxa%+QVzPI9?{%@xOoNt8WZ`)v784hj?h)xZY>!WT4W zD;?8iS$-K+X(^bN?EV1*7?j~OlHPP3l zrMg0mT%GH$_+>oBYxhZI+;=xhbw9Vj_l$rUw$?n!wO>tXUb1t>?Pw^V7r%`q29=G+ zqUWy%tDd0^M^0|p8>bmv0#8fFZ^r9=KsK9-S-$$!6Xt!5y-@%>QCM)Q{gCavKU zt3o84aI2)7A)ysz@6QmgyW;6SQ}2s*fE@@89fNvzO(JPg#vFfcsCV>jLQj|Zma+fw zpK(Y9;twLQ1UZhoCH%EUWVpYn!XLs?sPoa3} zNEdWU1G$`2_%L6W#4HnlX>=aYlzf9b&2TS>7$yu)`3Gi*P~ap<_gKV-+vUI-7@pGLSsIJ_l+ynjazQsACuG zq=4>4vS+)Wu|w=BJ7l-O#W#vBXOp-HfRh0ezxiK-fb9?L5Cv7-ZT(t?rOn;g6l!8T zoR5+zI!GKffc|P{vXO_je%64+$FBJ8lDZo#V~R<{w@72<3ouJx)9)p?{#{5k>rUrI zVJ^_MSRuUjNC3=k(8$(~@N6_dBO!^QpQA5HnP-z4Pv}7!;a|DMktX{&HxQustfqbD z9P;xUZA)$2rRV2XdEwRBTlAyVYbnxU#QDh{79@<539Vo7N%9|qNY&NS)0OTo&c3Ez z|1K8Z5`K1Dh$;QrYFQ}CM0Mq~ z*}uo{nq$oY6IcZQy>7wGiA|L#_N-I^%!`;J6l2*}{ml;goh`tb&?+dAzhTAt2A^uWt)D?;5$d-+Mk) zn2e(YgTgx)E<{U(!RNZ$zdi%=#L5#yISzVlvPx!Unfbwf`SQA5HNR720afu{yrXI< z!ty=KzAJv-+0d->1Kx2DSAi-ofil{|{}56=^Ckc_M>1yOpk6=E`P~`Sap~Z!M=!iIp+$o>EX?wTU|MC(g#wu`X+QyVOjGG7kpS z_an6UnUq@X@tgL_ns*c9SOmx(T`wJJHQ7HcP1ua+7e|;xopVM5ET&(zICOjiQv(b~ zIS|RPN_Ij5bC-2U8y=8kuZN)B*H24g_1hiI@>p)}?pl*4QFqnlMdx%#K-BZo<(r-n zK-SZs^~ULs%YVif+Vv8LpR%Nc{GR)~{wFjcjAj}v)c+tiy*F2S!?^+(bs{ucZ$_f;#D z)JK59=0rb>fk1|`%5HZ!wln*fNV&zDA2-UnjsEeH<~*&DdBQ^Lj2c=jH`H-SjTPt! zFsp6$@xFlG4`tVUd`GncXPu5D%(uyV9RY8EP#NHFD z=2vlW!v2vGA}3$vwZi?jcf7hB2&gK9lGOdze{+OxVkk6DA3Ie;zxP-e$u^0lpd=TD zx!e3yH=tEW^{pU1tN81}p`1+KTL_eAa>|{1?4TKGo94$iocXIHkM>CIrkxku79xq} z7Ur8iFldkJ@Q#X9=nT@z?gj56EQI(quM(h|MfTV-vRoIf*XwybodHzs=1zge`JHli z{$z!vXp+%l&W^L4sllj1Z>hmPblT#XwvCrS(`{dLFik3s!lD9IS2@89+xf;3+iVy$ z6dEhnZ{_Y{9uiPSQZ3Kmk^I42Dx-4U)c~tJwIl z4Ff*!{@CGEgKG<>@=-ao(26N>}SyAxVYZ7yHg#QOa8~w%$B`tjVo}HWhDv zwdRPwh}c7Qv@E_3m^WF!A>Z<|Otr_Oz3KfeF{28kF6>tq?+Sz|u%kMfA{OW-=8+)1 zVcIv2Em3uW#W~1SI}Y=AbGR%gn>YKN!yuIBVgqT+N%crQ0%IuLM^|MM=E73059ctU zSC?9sS#!Uh3bivl2=0g{+(PA8cQq7cp^XlP%WQiUv~`{vU1>3GR0d7JLH>`f%2oq3=YEn%o~FnpX$mME`So6R4^ii1*=1U0kq*RqHw?Y~?rpzF~&rruQ zDc&g#)f8^VBAaS{ay5@G=j=k0B*9wkic|kXN@nF2wx$-30jV~qs7R~nRGlIMey8c< z@MMTEHQ(0D_!^Y3gPt0)4w&1tTgk^JK>pR4umO>^u#hqJ{6?JEiWf)S(eI4QFtH`} zb=X#nnHj#(d?DkM3bW3dzR5$C4}m}upP8TnsQ|^kl{`^QT0ArMOsz>Z&bE(NJ-;q_ zu`ynW5x8Y8e?lVgGJ1>qA5Wq+|TZwq@gVP-&rqC%5 z7g(lAfm0R=^O5?t*k40=xR%Eo09)l6K;MoHu?jSQUS$MnnA z0rhZ%e&(Db*GwHj0#;>-p6rBsPX|QJLx^`(DCX6Qp7`SYF&6yEA-8#dx|v{;XCQ$z z-1m=CtD)!C3Rmcsk!C=Fa585*Q5>>o*L*J|v2CW4BVKJ?qv?Ir>Nj`eXi$d)ewZJ| z4}LG$p(`6E-`5EJ>qJ@`%mM8m)g=qI%v?q6IvtADLIprl{ezsS0uV@RMc&&*8!~>T z3dx=VX9Pqi2NseNIgiNI*mRRlyGX=UWcBbMU4n+>7FQCPzjc66mn;wjx&j&!@RmCC>E}iSC3!K6{HYDEj;QBSv^9VxRXsA~ z(U-F&;lK(2QVvi88%gCmRW8LM4Y6`nttp70DMHtDaU@z>C05meVTPhBQ>4<)O za<&V18e*H=9slmBwsd1?XoG_qCNr8y^(Rt+?-(_}sJ|CxOpq<@1661CmhL8r0_9Sl~-yc$nZ=VMoZ<#oKm*4RGh%<_Kvo#``Fav48_cWH@@gr5 zRmDP++4dCGx-m+no)A8CwO^p-UO(1DkFU3J%}gtF#FNtWikdt;8sv8x2(Z+zKQo}F zhLA85F8r)u&5o1i$8$Bm6xgm2PUEw~o2wp2(yBhs3pg!i)T|O7a>4t@$3%iPFO8X5 z%(I(DoivBuRmtr&Uph6*^eC$r)&aSVj_DNuDbH(v;%2W%wXue}p-i~hr4-jsktQkr z>=jsZ6fl;Pq^3Tpg@hB=*lpz`7g@^0_JB>Ckmqjd&$u(P^O$426jm~U8=ZJW_?_*{ z%Nc1TeG2Fzd%366%K#h-3qE5|P>77IuC7$XDXXOauG^3tHy+2|e;?vKhe=qPS1!Tc zN$8kM|0^+fBMA~y6t$jQXeqNRs2oG6UEPxT4Q`wMn-~XXOfjw>#e3OE=8@0KauMVa z@2w#!Ov@s#f2nNY{kO;#uyn_`0;WBD6lkAng=&Ai5f%QF3K2VEMZK%YBYX|KI&ic_1*VRu)isA{SxB;{yb36-83{(!rcj1(Jww zs#59crZtJ1{)Y54ee4)5Xch6vGLF{O08g)0dFxL`fBwWR+0*~nQ#8TNy?+EbZ$*JH z7L+P&NV*%cAu%7c#oZ9-8V3!J=&o45Dq?vtgIy8<^h#}D87?hsAG!M&fuStkMYUbq z+S0je6s=W01m*U1Rpl1t4Mp=cRjR+k(;Ln;kjk~4aE(Jga&Sw?om!v|5x^kZ80h%Y zBoNdRs6+sEj}uHbqKw0z*SV@v5I_^`A8725rZ{s4ow>vOHsC~bbGWa+vcwnjpwN4JV^ z)#1CdvZ81S->&5(#eIW*Px^Wb`R1jjOYUP19&_afDn2>Wt%O_NNUjv&h@u7@Idk zj~%K^H?QsC=e<25|HmJoGxLLsfKLhkcL%j^yu>j?lspzQ1yhHthVK1Qa4`!<+&0Ej z8t6SgbJV}{?u0T7#0szy)Q@;_=c*ZYn11u3nF9Ka`S{8!*EKP-_h8|4he#bfvHye8 z@Nl6=z`00>;YpQ8t;7h+7+q1{GC0<1>mn=hZ%!30k6x&@8tRcj&((tWd9B&h`ACb^ ziO(LY~7qF0H#qqR;fjPc9nuqqgMYnM@v@R#BVm;s>a9m zw^D@GS5>(_BgKD78j->pSdI;at=TIll`>%aDOjdoK$XkazZ(SOq-o7YkoK#aOr(A6 zBWHe2m?HwkC&r&F!1BuLC@l{fYh3k1OH^A~B=lH`ckLwoJIH_qXuOPp(+Els`^Lx@ z!+7BZUgmKvHk?o8X>w!Z>i(=?gT>|zc)BK=G5xN9eG7<)MMBy2(#y46ihv{F*L4%u zn!HKW3?S;@r6c>J{y)0npi@dVtDmSUY-4xU$IZR%pq~CU>&xk!+`8P~d&Ik|=a%v$ zSk)Tn*wd#G0uSe7^UG7DrM~~vg{uY{7)a~C?ztNcGoy?&QVU9o%*cn7J#wHcPeu(a)Vc$+J>>{c~RUw>zYY+!)SNP5l^W0?Q^h> zilEzxci(X!7xUH7{L_6?1bDDBl%?6KPVehW_Gg2o`u&*$ZlNQBvTuqj3 zkw1+gfB_!)2Dn8F9)_3PMg1Dvj zRYF%Oqmy!TgFK?3_DGOycgHI2oxMIo1Pl%UZMTi*tO*-1&m&VrLrG+NCPGFn#<^^N zFnhSxCax@0?C6v7TZdJ@UV+C^G$GgIhaW4ENV7ncrcXt#-;2GC1Ajund(g&9k&2S8 z4?6ZgeX1&Z$>XKJz@w?nD;4p)TgvJF_RsT7tB8 zZCYo%4hDQ=I4elC?5+Q7_j&GP6eodrLVC8{QsQa8i>gnc8~S6lA`}mp>}lmE3F~M(@W1JW-_>3{ z&NC5nqd84q9xSV9KIS3PuUcO$E;aeTUYCh9%JRaCeP%UtoQZO9H#kGZR`zC%;>OQS zy}q*tY;(H%{jhtF>@r-K2qvL-E^05(6SpWk>dkn%_4xiKpK*VBO!skh8JGXdZJcm< zd^SMu)+W+Ozhx_70dOl9@}oE57~FQpC4EVCJ2&HjKRpkW6z+rKVTM{cu5K-ZZ>JO0 z9U57Y&tMPf;2!0r);kR|HSlHosW)o8H!PV^{u7gX;RGgZFTuyi8C98rWW=JeX=*UG z4$t_TEZMsYtIevh5ePE0x-$>VwJf$)oTh7#IA4Rt*ZT|w)%KbkE3&w*zD%~Nlds;M zAiRly-@7?|DKqOGXvqGmhFP_DF6tx*q1UL?U)oDqb4Bb6A8X1-poN$i;|gYt0PVD( zO52n*4rX-p(3ogD2ca}exgAl%j>f%`A8a?*KMTL_*9dcCIbeQ*mp>}lk#vCwV|ThM zoJ1{!J!^0#vN`fW$gRw z$hISv?7Y1E_l@3rV}09Ej@Q+~5-!_hgkclm>8F(dvkA6ng&Rqvo1@_C)Wxb{(^8_k z-BP!wj@L;rTbL1vPQzg4hk^}HeZB+1&AOVqSY#9#uCJ&t-Yqru_YWG>*zG4_on^9T zgBYv<{tmo2jeh9Cj%JzR_dGmJ(pv;Yt^M(GDG_Y!r4lNvE|qW@?_eJ`FaE!xVmzb0Ymxbr?e zl?r6Frov29YR9=$iddC8_2rB6WxiBW(;ydWG7zw#aN)fJ&o0r2&nW6vf%n;^oftON{9fu)v z-2KCUaENvVF8xwEM5w(d?L*8Dr5~U%q>KwMQSTzj>cLia0eX3u`!FD+cuRF&c&wiV zjiiEt(B{7I>w9G3N371jJX(ABk$mQUr#$1#BCyOfo_tU(y;z9zctf2+4`O2NSp$1S zO;dOO*s$erp(#$nm9M-Y%^8{hMNGZ(jv!SESrrb2-pjpvoBHAx2Z@1G;ix0*G)*xP zp$6{*Ii0-AaF@@;m0`Q@v5G6)9}Qsr{~T44H7)!C+NTsabe8#`<~v7JkH3Y29I7# zFs0e{gDJGPb|F8q!1UTiwY9cDqSl8}c(%tGAj36+KjxNPb{tlCEKpMAuDKL%5KHvPA z5feF@1zn;AIznmQR@W}t%Kx<&66!>no91!QeK&%tju?kzj|QwX==%qfd{j@hOTaNU zpcd8dkQlj8+o$<%k>=7HrTa$DdQDj$V1w<{YiO?yuj+$ie{5&Rc5&5G!&qNig!X>M zoUxrG-w7tRR`&PSh;J%hHSQhY38z@wyWfZwkx%+?da(RUOM>?u{LL`NeQz0LEF zWAnn~F0Ou2{X)r@id{->Jw2Psd)w&H!2Vb10Bd4%!GLWY7?sWOym{XC@;R_QO#5LY zLPYGt_|tD#BwVVXkV!foNC|b^6TfJGP01j;>Q4_({uk>6kvcjP0D2FB%x&z(dZ|-h z7)8aiK3|)^)y#d?aJ@Z{xm^28(I2Au{^Faf64ogFvBQ)8mW`cApxn(u^~Tb8VIn}A z`PnQwLTPGr!S?RU>V&h!P}C9Wj?lzpJ7L-%2Xf~&tVP1Zl%DI+z_0w;#ETeLwbpTbmFic^!HG4q-qzs%9CM+C_nXKDB)WKr zew0i;W18`viGv15IvKyf1v|Le|0uUsSzoIJDfXX=h1_4PrYmO&ukyTKay~7BFW&?w z%jjXwxGgp{x`&@>6u@ws?7zK`UcI$vK! zUcNZLgqgB-3FrUZjh3JbABRv{hU&DD5WTa%*YSga({tg5GL6rr4!-v}9{pvNBc5_% zeYt_N^v>I_rZ|=cnXS^7m3(_%D#@i5E0cR~op&TL%?P_>n%V8k2Fuil^c5su??s5d z2=FW$P&|YcIdqSd6|BB-A$UMly5?ESq5hY&w}_3Q%3oWXF4BVN{oH84(x zOPI4tGaOIOdzzzNx)uW_Klaziad!Nihe$G3e&+I{5dAHZ+gwy(p?w5sTS`6f*;bRy z0rEC(#iFG^gj1G!%_|Ju9M$Obt_^f?l|@24rijCUbq?ZQ*i*VI3sU2s56h|*zQ1@b zgl4RLD@VvexnnUXGO`cNctqj^2jL2$nArHi5>nmdsRNY3?uLEN<7UH|+xmi)%sp_6 zSBJEtUI8V{Hvb3(Z2J4K)r(gPF|-(E+#a%df*8<5`*Cleb){-^dXv9HvU`61m0IRH z$cLNLj`bs5W3*+C2*9t3&n0B16k3=PDO-#j?)E#R3k!%M!3qfbhBni2f$N)8Ff=It z3>{X{b$%)WOxEp1tth(nZI%F~1z}kvSndFLWY(b6e;o>ZopeetHo$pjZ+*{(U~t8pU}UZsPWmp8|E9v*VM9 z!Q8W5^lBACh{)n}{Z%?9DJW?7ka3ebyEpVh~kZtI-T$6%%69>5z#v! zA=9pe)Oti<3D=MEFN+{1F?ucZX5`sFrrM~`$W)T6w@)-sDydc+}Z_7UYV~X36SCcoB zk&mpWf$2hP&DH)j-_Pyo60bUJPPjS%A*>~RvPHB02+U+(zLFu@ z2F6HjU0LC1eV_;wY(e`j|9O(c7V)F_MBbu zJGPp(+wzi!uVd~rD`+X^MzTU8v3x*_f#Uj$tbJ^42I)XM?bQ=^FfvW0fWPR{<`}%>B)g@ks|I;j7-PpY*L9xwLbKzk_l{W*)8kFlx~v*Y2?{DxqJct>XycK%SD})& zMVvf;w!f^{H51NzZeda83?6S{&1>o!3Z?;5*Pwb(4zw*`>=*RS(`&bx2P(-m-AK0p zT#g6M0pZo;feARQ(uBuAkJ$*bDgZlG0&EnI^YF)&#s~A4-V8jntCCf0Ab1#98`!?x zY(FoLXGolZrWc1OkSH~PBV;-qeAb>aHD|sx5$zy^&rpx`&%XLtNXW&t4BJU#k;#D7 z4`-_$grplW-kEn;p{YYVa*vbC<5g#H2N2N}xov9T__#-v&C8-%ejrY|WfQIhX*>~PU%#pQ9o)1-`8sV(GBCh2|OBQ{;n6%den zH#l#D^eW{I13jgl3YW}|xdstF3i(&khP_2zNeBdYIl*B)*Me;p?`C_6;>G`Y5sQ9r z5<_1JM{JRQh9M7h9ge~jW$6vduJTI8K(^zA4~oU`w-N@+@O1V*0bmM{{e52vOW2Nm zWX+t5bfYpN4>p=LzpiPuKFW;7acu6bCx?^qQa!3wK`y+6Qu(jkNC*kNFt21R4>e=E^SWPCtW@xj8%V*uCZBp09M^APfN9JbxB@ z)5*E1QR4y++;Gp5zvHG@Ez|wuL{mGaw8L$=Ih^H!NX$`jGBM_Ukz|B3A&T4z4 zt1GUEplLR5_vlY6l(Db&d5pflJhp_)9FQ~4%zRn9sjActfj%(sYcrvBtC`xh1fsi? zw>~-6DR8z33O^v3c96`w$7P^>Lcd?z-`3)zEYgY?pwCe7-S5eo^*O&vA>$kJvpRBUh?0*(&)u$geJ=zDPlm^!X(LFYp%c}rRX z!=6{by-{FdFN3j|5o<9`T|=3sO|yIkR8lK*K>Q< zNjHMfNt2zkrUFp%PZewl!m_5TZL}q{Z+sLpZ!=53A6c8%v@DOc0aI|0R&Y?Hm5_rp zCez4Bzv-|-anU1-=aMX;Xo**=gvsx+!VkY$QF{-AnvHCimtGy0jRRO)UTeXJd^m|& z?u+N>cd3tQ$^2;@oDx=)*_Wf-V;e`=BamMxnlB2Gb+tF|d({2)qIzq=P4>M;TjfJ5 zsN(BAH+(>*9xsBztl>XN=^EThLqTlSnut&3$dhd^wIK3k=?&!5AI@%QP=H6or!SZ) ze>TV-n;r>fHFZ3-o*%iOY47IN?)+R&h4I0T#4FQ0_HCb(+fr5V+(x|T`ZXt%ee0Z4 zj7e6c4O)8tc9?yofvL5YoNIr`!zRLZs9NxaHt6_yD8L~{BnEdrPOmO5JgXt&1n_?K zUN(*po+t6Y&e*5K$EKHsAvt}U^LUPAqf)uU&DC#>sE@A{dv2bU@tmvT8OigYijN2j07iEvIRK)>tn9*lq?qFn(UCR%lM)=qRfq`<9g)r)> z(?S+%AEYRjOK<;PH7I_(ZsBW9ct7$<4fefJPL%`+w~y1^D~pZZk(oCJ40Ab$GoS4GH5oPG}5LG^ZG z(SPCr_o!im^U^RnmZ|k+;stJw_mHAs)~Ypsr*bKU!c9WZu3H8M(~zLckX%jv>xsbQ zPecyzUxoqHC_OIg>GkR#TD%}V%)Dc2ixi=>xx#%O!^!mHQLqruo1ny8QPW2I}|kX%pIm47F!xIBIX73RD#E8MPDq}QHYFZ`kGrV%MA^) zsbL;DYwR2AOYo4~ScAg7*A@fm5Lu)u9$xG=R5LaE>N{r26e~`s!<~P3Dey-pCdiYB%_2{bVj~OcD&Mwv{w#=QzTAfX- z&>Jqy45oCqT07kB$s%Pm{;O&M=D9*q=y5MJHFY63O~GP>G(r^aeYAeH^5QVFV^OwS z#*}i$V#y{7I~+e1*oGH1@{gDKk;m5%>?r%E6S1B9E}UET>Bh*-Rvo?7a_aHbxTpO* znDoAQ*x_@a3^cFLzMrHmzf4()(7B>W-Z;?J`c5gke0v;JaV=#DQ=v>YG>ME;iNxM1 zJrf6C#N3!vEzIuyd&4O|R^5PcL56afkLd#m^}y#}FQhAr&Dg8Dh93-n9*Jj({r%z6 z^L+lc>m%OIlds8tCf=ja=KZV!U(lsava75>mokvg@?Qx+$(4P=*4o}&y8kYSu=X#g z`Ppexo+U|)0p@5=8NmMek!hhlb!cqQzJfATsk3oDP3u2gVjO(H5+?@jGg_g)#Rp7o zd|#v9YBhXz)Mf^#<{I47+1NLNR1KfaS&FdQK@ZHjUT=*Dh zVw70cS&PDd#=qqmUH*UVeT7$5UAMO&5-LatC=G{hln{`RknTbp0B z5kxB0NU0K4Mk8MB6m^_J*%RFtKe6xS4A?v~p!9Djr)*KINdXg8YYidB?CX((iNurS7jdLRUgYmZszN=v4&8eb+M3ZNW(E$HYK z4XiAjuzrs2n<#9xTFQ@({y2HxMjIlwHgHBqf8rjm(qxDs>T6{SZ!TqHJ}<|(rdso2 zil-XQ&NB-95xw^fj3OetHtj{Sl5`8~cul^v)r0$hQdI3(<2%ECG~>Oa!EkT`HB@?y z?W8FAWl`R+7kg`-0(e~CaOH@#jI6j6jfCQEY1@O#N;}<8Sl!cL6poP+VW@mSoHN5` zfoy{yLVLwqe57_)qiVy$-VSi>kLUm^2{SyzjBGc_7ioDrG|wZW?^tcY(j?Q4KVtG! zz_1>Xyyi~+e!#`O*O=*h&f&;J*RU|x$XI1Hp=7I*;j#NMd-se6hC-$aKa= zFhzt+eN)t$yo6!Nklb4G1{27KCfN&30=@^sXaiIH&>ZiNz>(-1R4;LOE^N7m?lTW{ z-&{Bl(D#T$U7p8M#nN%=Z#SFs`x)gsQ;yNxe9^#Ebx(=Nv$Ad51D+t&p4u{HBJ$n= ziYBj1bs$7C=DWOizKNrabbD$}Ku_F2{b*Dwd1x0Vxu`#1^wT|4$V!fLcRB4TPfkhG zP(K3Ms_um~c^@~oNOyL!OZ}}Rq}Xm(@$5w8in+A$H0izw(lwt{Sl7b+D6zL!*ACS; zi&QD!>07mF^Oh|PBv@np@yIf<_X8vWWGxQCPKZ1qE#V~(l&__JX)d1@H9Jh6j`y(E#|F7<{7?G2c!u! z2QwWpJ)Z#!3vaE(^w@jrW%1#EPi<)p?)vH9?R^cU&OPdTrYLgXR%+TkfTZGnt(&)? z*;uB?o8;YxOLvFZYFg^2aiU`9`F2A08idX#r1rlH(mRdrN)fxeXz@)xKip6r}0#A;9TLELuIzjQn)GZd6zR+!WtsM zUg^cRu)6fZh-b=tT%IEK5W|W1a?;9R;hh3|yb`_<*Y#t_z`gl7e^8_Y3gX<*XZ2)( zhpf~pZ2y`yNo2WhN1T-C18IfRy4K~LeEMz zFPxU!NYh*2aWJ&i)|N-&D3&%ay%SN6@ZcDWl=qd0B29Yo%s;X@+-`n3A#i8UL$%>P zvW=NeVqrnTJmZnD@P&yM|9pG*qU!wzL3*%GiEfclvx8<{b;^?@(F3`e+bnMssA9YNeh*)=#)51;`KPXOcWeR7{?m-g$qWN>hb5AYn38hpw zY|o3&h1=VkpHXLn83)a``vNZ^@0&0XZCDxYcoA|KT@MFexz_3m+^Nm0sL--!N=Vvm z){ZCJW#+*VBcsU~7nPF1ZaP6O*?FdFni7L=Z%dAk5wWt`#T!mS#Ngkh3O+P!fq0V% zP^An{8>wxm+|k(|4-GG+h94N~7>fsYL@tDmVn!=GbKzaop7mKiV1vf3YXQ%uVg<>YSt^aA~$b5^7 zdLp0Vz<$Wkq+#}EqsAJEb(<{hg|gd zOx1XhU)gIdD5y@cZ}lH6E}y4A-}}yLUv>3;EE4@+MP>f`cQgZPT9zYXB+3*b&(+iM z>cm2De3udJT|h%W5SEgrQb0AmjM{(b9wE0H8dC6v+P48u)NxWYtjmCD*VKlp;#a9p zA3_xQOcMtit|85$N_%P0KiL&PqR@8&Uq4)rfhjz$btW1n2FA}|5F#LS;G^hId`8M= zy%z6-&yOxrb@{XKu-=H?audKkePx(7YgJQpEqv(8io&$RPMCM>B z=|O%4M9lxmLh==(RpvCd6~*XhElkh0qN2go0Y32rEd&(MP8AMz&2RSEq#zO^sI8@` zh|z${FZ53p(kxeeP&$+Jw{9V6eevmhupF4}jLY#noW6E>RZ4KZ*S@(-bYhuC9q{a< zQeo_z^r*RnPwF_niu`MGZ(M*1mcT9mW|Qfnx!H-km>sJ0 z>if9d$JoGhwlL$c%fb>|PJqnIDQN#86g zPOFOu5U6~;nffq26en@{d1cFkR_Ljy{_c;%7}2W z@%V86*^&5>_AXwzZ^mVLu!J*@qqE9_jr3u5{?57K z0+QA#{PtMH1r6}$o}xC)hiY+_#JjVVGx2;GJU@YJDA`2n*&ZENja}j1O?4Kaai4$| zF=Hw!GVhfOv1H7?HdlHItSKr3r{hJxTHKdwUmKjLO^ZABuHIG9^@Exnw}YO<%@OC2k97c5|JE3Ux8`)0Y?9 z(w7VFpNPhfDQmW(<+2o%X(cEyHG7o$kl!O8wk>*4Y;?r}f4(SNt9lFE3^0KNK z76OeI&?UbYb27tLzv_rNvES)vih{I8Uh{U1Xz-Jx9$=eYKMEe$r@LF`f?>I$wE!8~ z$VZ&Q0uP$3S{U;m3$|8@FC2}B>ckH1bANsDfG(5J-V994XWJByD*CW{gyRd|~1?*Gyfr_RfRd2KFEZHr7hw02Tb`mHC7{)9uGE*WVPxabEkF zoewx2Y`=0N{(e^CeYPcSAkOw% z6DLAZVS7&-NapGt(*?v(v}Df(6@3%-OgoI`D!fAj1&}N#dm**K!;}K_}SJCetBr1VOP6~rDYnUKnMVF5y zW=;`am}!Y1)ae}kSCd-dX0wLjqR8BYVtZy9lg7}HPmOo|^6`pi!tg?`o4n=pkU_^z z2A4cyn{mA_DyS7%Med62r>?Q7riravpFoJVN_`ecDL;GAkMhi-AJdNnXt|+WUcKq` zVgK@_apQ-jM`lIoq42hMX1-fGsfC+tCAnR8QwVgg--gmR*$H-BY#55W9(bc6=0}#ZGqXoD=s{9{NxT^XN_2C{!?=6h)6l7JwnzQ%*GrW%+ib(+Pt;z z6}U#1ALzPhV>NccG25GcI4u#kQdD0j=+)=}ufS+XFB38k0+|bfzdpM{nM@BV;9|>D zRdET87!IRiJR-i^c&B>vZoyMi#dYZVa884ZY>${caAu|9#Gf3nX!ZhIkaxxuWIted z*(C%L=<8V7kqgC(*%IOYRei9A%((Ynj# zAQs}&dJyhyBztgq$U?W6<9)F*s~5O^L)3;i9}J9j0vX2>@nkIM`Q^g9pSN2lZ0F68 z3WH&RQ|4Lk=KZ4FgM0QnPoKm_72ic$bv-nB+gGA^`Sds}ngP;d_r^%f;?9_@nm5x$ zR5z_fM#R?7ago@H*VLmt>Pv}gyEWmRK_1Hf$hS++2o^o9Hw|l_$w-vTsFhP`&+)eE z(rqn=;h9BsB~5<5;{IClj7?@E*gE*ai)=gUR(;1;>@Q^{=qfE9oHZF$J6my-(^b_t zKY7#bnBUOSL*?FhGt&<}C8%M$7Z6I*rWLOtJHX`{O1ON)jAB8_+(=x~r1P?*H=DU! zB44WcI;fCRWuLAY8I*LUCQ+Gl+nX++KZ-)0&!}UZ!)U3}F%-{2p#UQ`<)jSv-{Oa$_1 z`>#^wcer2c7a-q0sbgs!{A$HX0KX(Mu7mWuO?~P4DM)C}>-=Jvhd;Xc&I^7WuAj8> z6!T&n@ls7{%t0PG9lY(Xc4tLBnjZoI_~(G2?R`JucU^H8*3Iv+mcxQqUyP}kCYGjn zUoJ|4@a4Y&1?rR=&^Fkw!QQz%2u7RzblAX`sZa-4HtCvzM@`C%sl!b}nKqio*O9xl zh*Yk-6`=!Iai>?S8d5KO3iAY~`-(DaIPPnP;3-+lfwFX)RpHmlhB{BFVIncP(3&LA z8t7{pZUO^KV`E#!O$K_|shXtVg$&Ump6olqP2o*jXf89xh%=JU(75gOu*Y&gPNzy5 z=g2nZ=nqNmf!vj(B8_H@yUvS4o2&u(HTiZa9A}}r8=0;*(=}77u+F1*6>dkHqFiE9 z+-9H}tX%TQ-cJL=ZtAkXH~OVeIv{n6-uxxP1XS>K`bWBP=^CHU4W&OrQi3ZV0$YGgKYNTQjL%Iy1+ioMP+^a<&stCKbEv~ix%o}XjO9eQM7kq2$3 ztidz;rtFh*>1FI-kBjqHiANv3X)%|ZnF_b7*qap3Jz^zK1s56~UPf??Q6)4lI_eWQ zH%8AVKHyhT|GrU)n9QteIw3-6PeIyf%4}Y{=BrPnqu?E5tn0W(;e6$b(?|;6zKwm* zmSI@E7bZU!O(CcoD>{NVg;?h!0e}olXaiU5w6w;-7!Ht;Yn~p?Q+n0B_hG5$L4r7y zt3D zc=VNCS~Fbqd>|Bzknqzsx6=D|x&v1YwPZIDkA+i&KQx#|2v$awKun}eoOv~lqnqkQLZX{(x(x=CUb|~RJS6x&lV%e>T8#vo$c!z7@sUdPY z;9bM7J?#?KmJU+dai~}FI*)(nLNMOhF7YLK)Hc{_s3E7Sj$))C!^^UjZ$8{M@z>EO z*^CxAA2Ay_w*_L?q+ohQ^+{BoV*^1dzn}HDwNp1vl8aZt4N>1=k{EBp2WBZPf8SLa zV$qJ(B4D38y1G3#cA;WDmtIRq#XcK(=f*eoC%n!u^>vp10Bfz6Cq0jXgS-rg39Y8p1xa-HCq9J#-gzm@|E>utUVB!fnEKIJE|75aC?< zMyV>_c&eaTUYdie3i3|(kQ4PNwn;D7X^Z7qn10yjnI9$mEj^g**R2E;50+y#+yDz( zXuf^V?i--t3~>MQkiC5e?dF2C^BFxUxK~-CWvLU@mlCwE%NSq%fUp0|f<5EqdL8Ag z*l(5a_^G0Gd-`7Z|Ew#z?%nE5Zfu1pbC^1o?$0#r^Oz%dMaHcCj%k$0scQFjRh^WBqd$1i5pa^^b3V-~e&bA+Tn zKBRn{abWv}RX#0*mABiEInFaDkqvL2KU8E5hIP70Zi^!mAp@7|X58N#587<472Xax z{ie8;@1or`+~SGu1|yqnmn`O1eB}*bSsvE`>u|69?QijD?vH$XLGw)U?L%dcs%`Ge zzF#4&WS=vBEl+S`BlnwE29+jSKuQ$AgK_;!OUF(LiHwuopctL3vkzR1Fp_8bzhd zvovQ+|E`kp+}P$Ym&lp>-|C&-J4gf@em`EF!V8Dq_oU|Q9jrJ3 zU!!d!CPCw>3C`-gj8f#X`WjbN)*r|8990r@T++BqFd+Lg#R?bQ5?%JJrJOgXirN>S zKJ#nu>}gs3L3usvL!=v4`@-;V7VF>6m&_HchY?ej#{rcrymAty71J#7QfYL|+HXx{ zN%0wFP*?rCWXqsNh2>0ie2rK2GJ?h7=D$~+{D+3h(P*KvTLw?wS+G#>T-RaC01=0R zm+vchNj0mOgix8)KMlSKECdk}HZuy{CBys8uK9Zxc*u$>Nq3xVP-#55g0ZiS1o77A zdw$=?-%_*vYe-C}6QChH&?)R;_5@V((n2gOg6%gS&dqt=O%xpoX+$@r%4rG}QL!zO zEs#nJx_E$MtELP1G;uMHNU2S4M^%$Xd}K(Rb3VK6+*S3jT8V#C?C%ES8&pZAWA?LU zQ@LtQ$dnJZ`f*Ib;=8G&(GO^$=|1*iszQjyn&n{gZSeGDlJh^S0#tgw@dPSlGIkpJ zt4khoUrby0LmIBQu_j>(>ZZ$4ytK-BXa&(tt@-QLP@!yZi18!_@yz3~oACZO-GD~s zFxJE3srrk-o|)>8rBk;wdt;Khh(qqiO(%^3WBMpM?GvLa?3!vl&sS40bq{(!{X7esL zus!;FVQw}UT~Q_3j!EiJ7>?a8rY*(mJcsR)zHL1EOHTH2m1!ovaNrUam2FfK9YF{y z=|#*;<^LdZfVYfV`OtXxqh3zQnCzU9T!Z_#+fp19mOK`Tb~jzr^iq&^{9Tf@h)Y1n z*~en8?VEJJ*$xd79SLhhKMJjbf&;rpGb&n3{8m*RW@!V^Fs%E{#Zm7lPyu^2=19+6 zCrZ4D^K8Di26dfvsMrAJ-R$S@cIXFDnczlzoO-SiN|d8C-W7kI+no}p715$x1e|yq z)h1nGpL~XM80j1|`|B>)|8)Z7Z~ng7cu0vN7@vpPRc$dDht7s1nJG!2X$HU#_ZN8{+TPZ(PU)-u1Kp`zYbZ~&`eTr zT=^D8r##Z#oBEPg8550pLopsfZ7z|`a<&7Q+8oRQO_dM+;i?;454@}eDcb|ooL8I+ z;(Qs~4CzEqal7B-JWFfmN65Pd=&S~OMp91Mf=B_uG+|Z}edtM-BlB>=eyF>!X{+vf8Ga-vtZg?8 zrkP3ppB2w9PYR=slf#Vn)v@liT4_-bt8>A?4wm|OsM?4e&5YK}FR`kN_febHbI;(^ zQ7@aVnG2qDUqa}pCH!yQ+7U4Je1{(!;1?F1K8H6?HEkV1E`qsKc{a#6p4u?@+R!b; zX~~r?a}dPZchs2Cy#io2F4ubd&xE-^lhxfaI4ZHA8A*NCzbr}*W9MOWkO6Ze+6?4J}04Vo+f<>%&|+mxO%RR`1! z5z{-60=#!JZgV{~YgHhWS6F$s0^oLuGG%X#1i*g`O@{<=>VVe_T_~Ii73SfhFq*b)R9b0{Mnx zJ^Rd@FJ$+G#yv{9yBln0dQmaM@hbIy>zK%w;uo4htXD87$(0w$f*@p`RF8 zDh}9KJV;_h=>a>01hY|XbYO&3MOR4&d>+T}#5~sNZ;kVB4cQ>ksPEG=uU!T{krX=D zfYCPBoV0h#mAMWj@`cx)s}%g8J`imm5XODaiKSN>TM{j5n&H^c8TT=Yt=_u#;(uLa zth`aOgp<531Fm}3Nx?&0dxYV-wbv9)g=N~7UX7?@)zO}86Udhp6Ik6C*fM>!WK{0r zOHkGcFoDX^Jn@@H+i!vdV3G`*bQ)GFDb>HVnGohfa8fleqG zVZ(ByQRdxyl>az_|8^Sp(*njb7($QXx+qq>FMND^39WC8+_RAAa)hulXEwz~5*B;I5r0!M4#`j-dJr5R z)h;slr;s|s{U$P`r&ems5T`qO`@s?}e6Fz3Obk5bNOf|j1oiPWzZbceF*7W^jmBri zl%8KP@RpVTgriTWqH7RwFGwYIR;QHauj#UnhKAi38d1#5r}vV%OV0RIZ#^v*ci)m7 z5>TEX9%&%{r7P(DXY$Cr_AB&qE*N5ai*8&l^4r1;S7It}DU>%yU5<{Mr>DoVv&vWQPX6bz;#oIgx~KoDONlToq)*C zrM>pj{8x4Qo9z3q_PQ?`6!@bWYw23-V#PS zRN3CBXPN~s(?QHh&YZ5Km~0!w;=oN|CMu_1BdRp*zrvLN@mWc~)oCc#wJa=H-(`&r z|8Q$AKS4tv$$Vwk+QwD#xYR?jBf@E_D{zTnLH#&kL*<7|-cXr5M&+wGL{akvr-SZasss9NNeWpwN!G%rDgW>S01*s9Q@bbh-jSeeK}-c;IH$R3RXrak2?mFsxjmKop8ThNF#z@$*pq&A_USwl zQ*xD8JtOY(J+6FmT|V}N97s9=x#hq(_NLQQU!wuh{O3qAtfP{?oYl9*<4!C#jazT= zI)9#5Q1{gRse5aHoNt||%y`x|FoYwja72Pq3giuHfq-K36`lEXKb{#3bXi`!csd^Oxc?^^f%L+I%zijK=k-ctUYn%dly6 zDaVSeoc%wu48TXU_?c5F(zNZXcv_d`SgLy;O8-Sih{N zV1H-b6o_xkuDIeBkuW@zC{@WSG2pdCnCLi%P5epxrKy-uLK|hu-!vhn3U`H6LZ05E zP#l`=^G&vnX-Xjm!CcDMzh7C+l{e9$#KuBA*O^qEJJzj0ZVF-S0dO7PiYaKqh4Y4R zAN#*WuWq8{D7|PopYwM=^MOtgE)nBIun5_{wd_&9L!9z8gZzkE zo~NjoJ?xtL_og0-JJJ$H?>1L6B>x@jMy&3#X)$O7}(>Vzt|;}H|3r{6Qe#tXj+;vP5K zBDh||?L@XZPQ)}|r^RxE%0v}*gC(%dyz>t{y$9F}mcmE7hq;@Do|f;~oi z45xYa_`XQeo8qGD5nR`9K#P8vw$$3T}g1-Hv~j?Sx-C&kxaO)!)6d$w7UVz<4HddZ=X=(7xVOj6YqY zstYN7-C;|`_!)i_yhP4qdi!PQUCq;K(&bB5sBTX2w{3(69!>ZbHtQd!5={x9*Fn3% zOE2T&79WBO5>&8ryuYu%-dU_u5yj{+Q$cKcC zeG1FElQfs@3jUktvrUW_!t_dm*rx8krTyHnaHN0XFSpTZ+u^Cwb52&0_sux-&?SxZ zFy3&bVuO(FIhq(DQaac%Y&PM9PixyL>=jv~Z!Z{si$~qBF-R8E+bi`=aTs-;)6||& zXoJDRqQxJ$4ak22#FFojoRs1`znL zsWCD>#+!NFo~bj=;pFB!4RzBxC$?EGvzYy?J}ot-mKF?!oV= zNH@UjAtu22cPc>m^;|ol)224N3qhRA(066q1|c&CB;_B`i4z(BJwi#WL8iAi% zOIB9imL1Tw-&`$S%e`k6|3~^%FaVm)(>d6D98vZ`5CTfe8;RirG7HydEGu zsb1J{IX0amzhRkk64B)D%@?L_N2x4q3-4Kl{9%Nd9suNSQw+{c_L@Wci!DZr-@Q0( z)UMK}k$vf?w;VX3e1GnRF1pZz%BBGW;mwNcU`8~t%KvE1{CX*B4uF$h^7+wl9*o{) zY_JwrU`SOrBLZ8B5~i(dtIL_1_+C_GnfY=zIP}uth)vBUaT1sR&l-F^84%x+>9`f5 zSVXJSovc!a8ho!O=x#KIm!Vc=>{$udVR>_%y(%1CanI*qb?4dDE}mJn-@96Oev5P5 zVA*INTYyiHA1YkQBd+?l1PHOx7lH-wKH(^emiWg!8c=b?9z4jCuiDX*mMqt-t+>Cm zL&_y(Sg2tt_ZKujKZzLllT{AfLIx-SJ>~i@Wddr~@ze2*F7f26=vg3KEYCO=3tSqD zb8*k@2a8U(=%14g*RZNaq$e(Gm~#20m5rR*3SN-8RyRZ4Nh>x=qV9~7*kxI2;uzM+ zw7rJ5F(~|oIKTOqx(PC;W|kkIT%(YA4Q#-Y1hIclh`ga0|76Ad n-~0btf&ULzz&DF-?;7Pb8AV>0i1)}X;73MMQKCf5$nU=Zbx^EH literal 0 HcmV?d00001