├── .dependabot └── config.yml ├── .eslintrc.json ├── .github ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── changelog.txt ├── cli ├── cli.js ├── index.js ├── jsdoc.json ├── lib ├── field86structure.js ├── helperModels.js ├── parser.js └── tags.js ├── package-lock.json ├── package.json └── test ├── helpers.test.js ├── message-blocks.test.js ├── parser.test.js ├── structured.test.js ├── tags.test.js ├── test-with-NS.mt940x ├── test1.mt940 ├── test2.mt940x └── testX.mt940 /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | - package_manager: "javascript" 4 | directory: "/" 5 | update_schedule: "weekly" 6 | automerged_updates: 7 | - match: 8 | dependency_type: "all" 9 | update_type: "all" 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2019, 4 | "sourceType": "module" 5 | }, 6 | "env": { 7 | "browser": true, 8 | "node": true, 9 | "mocha": true, 10 | "es6": true 11 | }, 12 | "extends": [ 13 | "eslint:recommended" 14 | ], 15 | "rules": { 16 | "quotes": ["error", "single", { "avoidEscape": true }], 17 | "semi": ["error", "always", { "omitLastInOneLineBlock": true}], 18 | "no-console": "off", 19 | "no-trailing-spaces": ["error"], 20 | "indent": ["error", 2] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | time: "03:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test-and-lint: 13 | name: Test and lint 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: '12.x' 20 | - run: npm install 21 | - run: npm run test 22 | env: 23 | CI: true 24 | - run: npm run lint 25 | - name: coverage 26 | run: | 27 | npm run coverage 28 | npm run report-coverage 29 | - uses: codecov/codecov-action@v1 30 | with: 31 | file: ./coverage.lcov 32 | fail_ci_if_error: true 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | pdf/ 4 | coverage/ 5 | doc/ 6 | play.js 7 | .vscode/ 8 | .nyc_output/ 9 | coverage.lcov 10 | dist/ 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2016 Alexander Tsybulsky 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SWIFT MT940 bank statement format JS parser 2 | 3 | [![Build Status](https://travis-ci.org/a-fas/mt940js.svg?branch=master)](https://travis-ci.org/a-fas/mt940js) 4 | [![NPM version](https://badge.fury.io/js/mt940js.svg)](https://badge.fury.io/js/mt940js) 5 | [![codecov](https://codecov.io/gh/a-fas/mt940js/branch/master/graph/badge.svg)](https://codecov.io/gh/a-fas/mt940js) 6 | 7 | *[History of changes](/changelog.txt)* 8 | 9 | mt940js is a SWIFT mt940 bank statement format parser for javascript (ES2015). Takes in text of mt940 file, puts out array of parsed statements and transactions. 10 | See examples below. 11 | 12 | ## Installation 13 | 14 | ```bash 15 | npm install mt940js 16 | ``` 17 | 18 | ## API and usage 19 | 20 | Main parser class - `Parser` - parses input text (e.g. read from a file) into array of statements (a file may contain one or more). Each output statement contains a set of attributes, describing opening balance, statement number, etc and also an array of transactions. 21 | 22 | **Example** 23 | 24 | ```javascript 25 | const mt940js = require('mt940js'); 26 | const parser = new mt940js.Parser(); 27 | 28 | const statements = parser.parse(fs.readFileSync('./some_path', 'utf8')); 29 | 30 | for (let s of statements) { 31 | console.log(s.number.statement, s.statementDate); 32 | 33 | for (let t of s.transactions) { 34 | console.log(t.amount, t.currency); 35 | } 36 | } 37 | ``` 38 | 39 | ### Statement 40 | 41 | - `transactionReference` {string} - tag 20 reference 42 | - `relatedReference` {string} - tag 21 reference, *optional* 43 | - `accountIdentification` {string} - tag 25 own bank account identification 44 | - `number.statement` {string} - tag 28 main statement number 45 | - `number.sequence` {string} - tag 28 statement sub number (sequence), *optional* 46 | - `number.section` {string} - tag 28 statement sub sub number (present on some banks), *optional* 47 | - `openingBalanceDate` {Date} - tag 60 statement opening date 48 | - `closingBalanceDate` {Date} - tag 62 statement closing date 49 | - `closingAvailableBalanceDate` {Date} - tag 64 closing available balance date, default = closing date 50 | - `forwardAvailableBalanceDate` {Date} - tag 65 forward available balance date, default = closing available date 51 | - `statementDate` {Date} - abstraction for statement date = `closingBalanceDate` 52 | - `currency` {string} - statement currency (USD, EUR ...) 53 | - `openingBalance` {Number} - beginning balance of the statement (with sign, based on debit/credit mark) 54 | - `closingBalance` {Number} - ending balance of the statement (with sign, based on debit/credit mark) 55 | - `closingAvailableBalance` {Number} - tag 64 closing available balance, default = closing balance 56 | - `forwardAvailableBalance` {Number} - tag 65 forward available balance, default = closing available 57 | - `informationToAccountOwner` {string} - additional statement level information 58 | - `transactions` {array} - collection of transactions 59 | - `messageBlocks` {object} - statement message blocks, if present (EXPERIMENTAL) 60 | 61 | **Each Transaction contains data of tag 61 (and tag 86 for details)** 62 | 63 | - `date` {Date} - transaction date 64 | - `amount` {Number} - transaction amount (with sign, Credit+, Debit-) 65 | - `reversal` {Boolean} - transaction is a reversal 66 | - `currency` {string} - transaction currency (copy of statement currency) 67 | - `details` {string} - content of relevant 86 tag(s), may be multiline (`\n` separated) 68 | - `transactionType` {string} - MT940 transaction type code (e.g. NTRF ...) 69 | - `reference` {string} - payment reference field 70 | - `entryDate` {Date} - entry date field, *optional* 71 | - `fundsCode` {string} - funds code field, *optional* 72 | - `bankReference` {string} - bank reference, *optional* 73 | - `extraDetails` {string} - extra details (supplementary details), *optional* 74 | - `structuredDetails` {Object} - structured details if detected, in for of `{ subtag: value }` e.g. `{ '20': '123456' }` 75 | - `nonSwift` {string} - optional, content of NS tag which happened in the context of transaction (after tags 61 or 86), can be multiline (separated by `\n`) 76 | 77 | Each statement is validated for: 78 | 79 | - all strictly required tags 80 | - opening/closing balance currency is the same 81 | - opening balance + turnover = closing balance 82 | 83 | ### Invocation 84 | 85 | The `Parser` has just one method - `parse(data, withTags = false)` - which will convert raw mt940 string to an array of statements described above. The optional `withTags` parameter would preserve parsed tags to an additional `tags` attribute of a statement (for any additional further analysis). 86 | 87 | ### Support for field 86 structure 88 | 89 | Currently the library supports the following tag formats: 90 | - `'DD'`, where `` can be `'>'` or `'?'` 91 | - `'/TAG/value'`, where `TAG` is 2 to 4 uppercase chars. 92 | 93 | Example: 94 | 95 | ``` 96 | '>20some details >30more data' 97 | or 98 | '/ORDP/Smith Corp' 99 | ``` 100 | 101 | The parser attempts to detect if field 86 contains tags like these and, if yes, adds `structuredDetails` attribute to a statement line. Tag digits are not interpreted as they are not standardized among different banks. Parsing 86 structure can be force disabled by passing `{ no86Structure: true }` to the constructor. 102 | 103 | ```javascript 104 | // let incoming file contain one line with 86 field: 105 | // '>20some details>30more data' 106 | 107 | const statements = ... // parsing here 108 | 109 | for (let s of statements) { 110 | for (let t of s.transactions) { 111 | console.log(t.structuredDetails); 112 | // { '20': 'some details', 113 | // '30': 'more data' } 114 | } 115 | } 116 | ``` 117 | 118 | ### Middlewares 119 | 120 | **Currently experimental, may change** 121 | 122 | The library support post processing middlewares which is called before returning parsed result. To append a middleware call `usePostParse` passing `fn(statement, next)`. Middlewares are called in the order of appending. Middlewares modify statement object directly. Beware that input data may contain several statements, middlewares are called over each of them one by one. 123 | 124 | ```javascript 125 | const parser = new Parser(); 126 | parser.usePostParse((s, next) => { 127 | s.hasOverdraft = (s.closingBalance < 0); 128 | next(); 129 | }); 130 | ``` 131 | 132 | ## Contribution 133 | Contribution is welcomed :) 134 | 135 | ## TODO 136 | - pre parsing middlewares 137 | - parsing structure of block messages 138 | 139 | ## Author 140 | [Alexander Tsybulsky](https://github.com/a-fas) 141 | 142 | ## License 143 | The code is licensed under Apache-2.0 License. Please see [LICENSE](/LICENSE) for details. 144 | 145 | ## Credits 146 | Inspired by https://github.com/WoLpH/mt940 147 | 148 | ## Standard references 149 | - https://www2.swift.com/knowledgecentre/publications/us9m_20180720/2.0 150 | - https://www.paiementor.com/payment-messages/ 151 | - https://www.paiementor.com/swift-mt-message-structure-blocks-1-to-5/ 152 | - https://www.nordea.se/Images/39-16149/MT940-file-description.pdf -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | mt940-js changelog 2 | ================== 3 | 4 | Legend 5 | ------ 6 | * : fixed 7 | ! : changed 8 | + : added 9 | - : removed 10 | 11 | 2019-12-30 v1.3.4 12 | ------------------ 13 | * Dependencies update, npm audit fix 14 | 15 | 2019-12-03 v1.3.3 16 | ------------------ 17 | + Support for NS fields in the context of transactions (saved to 'nonSwift' attribute) 18 | + Support for GVC at the beginning of payment details (thanks to @artur-krueger) 19 | 20 | 2019-01-31 v1.3.1 21 | ------------------ 22 | + no86structure param to skip 86 tag structure detection 23 | * minor fixes and refactorings 24 | 25 | 2019-01-29 v1.3.0 26 | ------------------ 27 | + experimental messageBlocks detection and partial parsing '{1:...}' 28 | 29 | 2019-01-29 v1.2.1 30 | ------------------ 31 | * bug fixes: tag 61 extra details, leading spaces in tag 86, statement level informationToAccountOwner (thanks to @nickidk4) 32 | * potential bug fix: tags starts at the line beginning 33 | 34 | 2019-01-19 v1.2.0 35 | ------------------ 36 | + support for reversal flag, field 61 also contains isReversal attribute 37 | + support for fields 64 and 65 (closingAvailableBalance, forwardAvailableBalance) 38 | + support for /XXX/ field 86 subtags 39 | + support post parse middlewares 40 | 41 | 2016-09-08 v1.1.0 42 | ------------------ 43 | + added some support for structured 86 field 44 | 45 | 2016-12-11 v1.0.0 46 | ------------------ 47 | First release :tada: 48 | -------------------------------------------------------------------------------- /cli: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node cli.js $@ 3 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const MT940Parser = require('./lib/parser'); 3 | 4 | function banner() { 5 | console.log('Usage: node cli.js '); 6 | console.log('--'); 7 | console.log(' filename - mt940 text file in UTF8 encoding'); 8 | } 9 | 10 | const argv = process.argv.slice(2); 11 | let files = []; 12 | 13 | if (!argv.length) { 14 | banner(); 15 | process.exit(1); 16 | } 17 | 18 | argv.forEach(arg => { 19 | switch (arg) { 20 | case '--help': 21 | case '-h': 22 | banner(); 23 | process.exit(1); 24 | break; 25 | default: 26 | try { 27 | fs.accessSync(arg); 28 | files.push(arg); 29 | } catch (e) { 30 | console.error(`Cannot access file: ${arg}`); 31 | process.exit(1); 32 | } 33 | } 34 | }); 35 | 36 | files.forEach(file => { 37 | const parser = new MT940Parser(); 38 | const data = fs.readFileSync(file, { encoding: 'utf8' }); 39 | const statements = parser.parse(data); 40 | 41 | statements.forEach(stmt => { 42 | console.log('--'); 43 | console.log(JSON.stringify(stmt, null, ' ')); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MT940 parser 3 | * @module ./index 4 | */ 5 | 6 | const Parser = require('./lib/parser'); 7 | const Helpers = require('./lib/helperModels'); 8 | 9 | module.exports = { 10 | /** MT940 Parser - main class 11 | * @see {@link Parser} 12 | */ 13 | Parser, 14 | 15 | /** Optional helper classes 16 | * @see {@link lib/helperModels} 17 | */ 18 | Helpers, 19 | }; 20 | -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "include": [ "./lib/", "index.js" ], 4 | "includePattern": ".+\\.js(doc)?$" 5 | }, 6 | "opts": { 7 | "destination": "./doc/", 8 | "readme": "./README.md" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/field86structure.js: -------------------------------------------------------------------------------- 1 | class Field86StructureParser { 2 | static buildTagRe(details) { 3 | const prefix = details.charAt(); 4 | 5 | // check first symbol is known separator 6 | let tagRe; 7 | if (!prefix) { 8 | return; 9 | } else if (prefix === '/') { // assume /XXX/ fields 10 | tagRe = '\\/[0-9A-Z]{2,4}\\/'; 11 | } else if ('>?'.includes(prefix)) { // assume >DD fields 12 | tagRe = `\\${prefix}\\d{2}`; 13 | } else return; // known separator not found 14 | 15 | return { 16 | detect: new RegExp(`^${tagRe}`), // line must begin with a tag 17 | match: new RegExp(`(${tagRe})(.*?)(?=(${tagRe})|$)`, 'g'), // matcher 18 | // item: new RegExp(`^(${tagRe})(.*)`), 19 | strip: new RegExp(`\\${prefix}`, 'g'), 20 | }; 21 | } 22 | 23 | /** 24 | * Detects if field 86 is structured and attempts to parse it 25 | */ 26 | static parse(details) { 27 | details = details.replace(/\n/g, '').trim(); 28 | 29 | const parsedStruc = {}; 30 | 31 | if (details.match(/^\d\d\d[?>]/)) { 32 | parsedStruc.gvc = details.substr(0,3); 33 | details = details.substr(3); 34 | } 35 | 36 | const rule = Field86StructureParser.buildTagRe(details); 37 | if (!rule) return; 38 | if (!rule.detect.test(details)) return; // string must start with tag 39 | let match = rule.match.exec(details); 40 | while (match) { 41 | const subTag = match[1].replace(rule.strip, ''); 42 | parsedStruc[subTag] = match[2]; 43 | match = rule.match.exec(details); 44 | } 45 | 46 | return parsedStruc; 47 | } 48 | } 49 | 50 | module.exports = Field86StructureParser; 51 | -------------------------------------------------------------------------------- /lib/helperModels.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper models 3 | * @module lib/helperModels 4 | */ 5 | 6 | /** helper class to parse date based on 2-digit year */ 7 | class BankDate { 8 | /** 9 | * Parses date 10 | * @param {string} year - 4-digit or 2-digit year, 20xx assumed for the latter 11 | * @param {string} month - month number (starting from 1 = January) 12 | * @param {string} day - day number 13 | * @return {Date} a Date object 14 | * @static 15 | */ 16 | static parse(year, month, day) { 17 | let fullyear = Number.parseInt(year, 10); 18 | if (fullyear < 100) { 19 | fullyear += 2000; 20 | } 21 | return new Date(Date.UTC(fullyear, Number.parseInt(month, 10) - 1, day)); 22 | } 23 | } 24 | 25 | /** helper class to parse amount and identify it's sign based on Debit/Credit mark */ 26 | class BankAmount { 27 | 28 | /** 29 | * Parses amount, identifies sign based on Debit or Credit mark. 30 | * @param {string} dcmark - D or C = Debit or credit (C = positive), prefix 'R' -> change of sign, reversed 31 | * @param {string} amoutStr - string with positive float number 32 | * @return {float} amount, rounded to 2 fractional digits, with sign 33 | * @static 34 | */ 35 | static parse(dcmark, amountStr) { 36 | let rev, dc = dcmark; 37 | if (dcmark.length === 2) { 38 | rev = dcmark[0]; 39 | dc = dcmark[1]; 40 | } 41 | if (rev && rev !== 'R') throw Error( `Wrong reversal mark: ${dcmark}` ); 42 | if (! (dc === 'D' || dc === 'C') ) throw Error( `Wrong debit/credit mark: ${dcmark}` ); 43 | 44 | let amount = Number.parseFloat(amountStr.replace(',', '.')); 45 | if (Number.isNaN(amount)) { throw Error( `Amount cannot be parsed: ${amountStr}` ) } 46 | if (amount < 0) { throw Error( `Positive amount string expected: ${amountStr}` ) } 47 | 48 | if (dc === 'D') amount = -amount; // Bank debit = minus 49 | if (rev) amount = -amount; 50 | amount = Math.round(amount * 100) / 100; 51 | return amount; 52 | } 53 | 54 | /** 55 | * Compares amounts (floats in fact), returns True if difference < 0.001 56 | * @param {float} a - number 1 57 | * @param {float} b - number 2 58 | * @static 59 | */ 60 | static isEqual(a, b) { 61 | return Math.abs(a - b) < 0.001; 62 | } 63 | } 64 | 65 | module.exports = { 66 | /** Bank amount, parses debit/credit mark + amount string */ 67 | Amount: BankAmount, 68 | 69 | /** Bank date, parses date with 2digit year */ 70 | Date: BankDate 71 | }; 72 | -------------------------------------------------------------------------------- /lib/parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MT940 parser class 3 | * @module lib/parser 4 | */ 5 | 6 | const Tags = require('./tags'); 7 | const helperModels = require('./helperModels'); 8 | const Field86Structure = require('./field86structure'); 9 | 10 | /** 11 | * Main parser class, parses input text (e.g. read from a file) into array of statements. 12 | * Each statement is validated for: all strictly required tags, 13 | * opening/closing balance currency is the same, opening balance + turnover = closing balance. 14 | * One input may return one or more statements (as array). Each statement contains transactions 15 | * array, where each contains data of tag 61 (and tag 86 for details). 16 | *

Output statement contains:

17 | * @property {string} transactionReference - tag 20 reference 18 | * @property {string} relatedReference - tag 21 reference, optional 19 | * @property {string} accountIdentification - tag 25 own bank account identification 20 | * @property {string} number.statement - tag 28 main statement number 21 | * @property {string} number.sequence - tag 28 statement sub number (sequence) 22 | * @property {string} number.section - tag 28 statement sub sub number (present on some banks) 23 | * @property {Date} openingBalanceDate - tag 60 statement opening date 24 | * @property {Date} closingBalanceDate - tag 62 statement closing date 25 | * @property {Date} closingAvailableBalanceDate - closing available balance date (field 64) 26 | * @property {Date} forwardAvailableBalanceDate - forward available balance date (field 65) 27 | * @property {Date} statementDate - abstraction for statement date = `closingBalanceDate` 28 | * @property {string} currency - statement currency 29 | * @property {Number} openingBalance - beginning balance of the statement 30 | * @property {Number} closingBalance - ending balance of the statement 31 | * @property {Number} closingAvailableBalance - closing available balance (field 64) 32 | * @property {Number} forwardAvailableBalance - forward available balance (field 65) 33 | * @property {string} informationToAccountOwner - statement level additional details 34 | * @property {object} messageBlocks - statement message blocks, if present (EXPERIMENTAL) 35 | * 36 | * @property {array} transactions - collection of transactions 37 | * @property {Date} transaction.date - transaction date 38 | * @property {Number} transaction.amount - transaction amount (with sign, Credit+, Debit-) 39 | * @property {Boolean} transaction.isReversal - reversal transaction 40 | * @property {string} transaction.currency - transaction currency (copy of statement currency) 41 | * @property {string} transaction.details - content of relevant 86 tag(s), may be multiline (`\n` separated) 42 | * @property {string} transaction.transactionType - MT940 transaction type code (e.g. NTRF ...) 43 | * @property {string} transaction.reference - payment reference field 44 | * @property {Date} transaction.entryDate - optional, entry date field 45 | * @property {string} transaction.fundsCode - optional, funds code field 46 | * @property {string} transaction.bankReference - optional, bank reference 47 | * @property {string} transaction.extraDetails - optional, extra details (supplementary details) 48 | * @property {Object} transaction.structuredDetails - optional, if detected, parsed details in form of { subtag: value } 49 | * @property {string} transaction.nonSwift - optional, content of NS tags which happened in the context of transaction (after tags 61 or 86), can be multiline (separated by `\n`) 50 | * @example 51 | * const mt940parser = new Parser(); 52 | * const statements = parser.parse(fs.readFileSync(path, 'utf8')); 53 | * for (let i of statements) { 54 | * console.log(i.number.statement, i.statementDate); 55 | * for (let t of i.transactions) { 56 | * console.log(t.amount, t.currency); 57 | * } 58 | * } 59 | */ 60 | class Parser { 61 | /** 62 | * Constructor, params are given as object fields { no86Structure: true } 63 | * @constructor 64 | * @param {boolean} no86Structure - don't parse 86 field structure 65 | */ 66 | constructor ({ no86Structure } = {}) { 67 | this.params = { 68 | no86Structure, 69 | }; 70 | this.postParseMiddlewareStack = []; 71 | } 72 | 73 | /** 74 | * Parse text data into array of statements 75 | * @param {string} data - text unparsed bank statement in MT940 format 76 | * @param {boolean} withTags - tags will be copied to output statements in `tags` attribute for further analysis 77 | * @return {array} Array of statements @see class documentation for details 78 | */ 79 | parse(data, withTags = false) { 80 | const factory = new Tags.TagFactory(); 81 | const dataLines = this._splitAndNormalize(data); 82 | const tagLines = [...this._parseLines(dataLines)]; 83 | const tags = tagLines.map(i => factory.createTag(i.id, i.subId, i.data.join('\n'))); 84 | const tagGroups = this._groupTags(tags); 85 | const statements = tagGroups.map((grp, idx) => { 86 | this._validateGroup(grp, idx+1); 87 | return this._buildStatement(grp, withTags); 88 | }); 89 | 90 | for (let s of statements) { 91 | this._applyPostParseMiddlewares(s); 92 | } 93 | 94 | return statements; 95 | } 96 | 97 | /** 98 | * usePostParse - use middleware(s) after parsing, before result return 99 | * @param {function} fn - middleware fn(statement, next) 100 | */ 101 | usePostParse(fn) { 102 | if (typeof fn !== 'function') throw Error('middleware must be a function'); 103 | this.postParseMiddlewareStack.push(fn); 104 | } 105 | 106 | /** 107 | * _aaplyPostParse - internal apply post parse middlewares 108 | * @param {object} statement - statement to process 109 | */ 110 | _applyPostParseMiddlewares(statement) { 111 | if (this.postParseMiddlewareStack.length === 0) return; 112 | const chainFn = this.postParseMiddlewareStack 113 | .reverse() 114 | .reduce((next, fn) => fn.bind(null, statement, next), () => {}); 115 | chainFn(statement); 116 | } 117 | 118 | /** 119 | * Split text into lines, replace clutter, remove empty lines ... 120 | * @private 121 | */ 122 | _splitAndNormalize(data) { 123 | return data 124 | .split(/\r?\n/) 125 | .filter(line => !!line && line !== '-'); 126 | } 127 | 128 | /** 129 | * Convert lines into separate tags 130 | * @private 131 | */ 132 | *_parseLines(lines) { 133 | const reTag = /^:([0-9]{2}|NS)([A-Z])?:/; 134 | let tag = null; 135 | 136 | for (let i of lines) { 137 | 138 | // Detect new tag start 139 | const match = i.match(reTag); 140 | if (match || i.startsWith('-}') || i.startsWith('{')) { 141 | if (tag) yield tag; // Yield previous 142 | tag = match // Start new tag 143 | ? { 144 | id: match[1], 145 | subId: match[2] || '', 146 | data: [i.substr(match[0].length)] 147 | } 148 | : { 149 | id: 'MB', 150 | subId: '', 151 | data: [i.trim()], 152 | }; 153 | } else { // Add a line to previous tag 154 | tag.data.push(i); 155 | } 156 | } 157 | 158 | if (tag) { yield tag } // Yield last 159 | } 160 | 161 | /** 162 | * Group tags into statements 163 | * @private 164 | */ 165 | _groupTags(tags) { 166 | if (tags.length === 0) return []; 167 | const hasMessageBlocks = (tags[0] instanceof Tags.TagMessageBlock); 168 | const groups = []; 169 | let curGroup; 170 | 171 | for (let i of tags) { 172 | if (hasMessageBlocks && i instanceof Tags.TagMessageBlock && i.isStarting || 173 | !hasMessageBlocks && i instanceof Tags.TagTransactionReferenceNumber) { 174 | groups.push(curGroup = []); // Statement starting tag -> start new group 175 | } 176 | curGroup.push(i); 177 | } 178 | return groups; 179 | } 180 | 181 | /** 182 | * Validate group of tags (required tags present, currency is consistent, consistent balances vs turnover) 183 | * @private 184 | */ 185 | _validateGroup(group, idx) { 186 | // Check mandatory tags 187 | const mandatoryTags = [ 188 | Tags.TagTransactionReferenceNumber, //20 189 | Tags.TagAccountIdentification, //25 190 | Tags.TagStatementNumber, //28 191 | Tags.TagOpeningBalance, //60 192 | Tags.TagClosingBalance //62 193 | ]; 194 | for (let Tag of mandatoryTags) { 195 | if (!group.find(t => t instanceof Tag)) { 196 | throw Error(`Mandatory tag ${Tag.ID} is missing in group ${idx}`); 197 | } 198 | } 199 | 200 | // Check same currency 201 | let currency = ''; 202 | for (let i of group.filter(i => i instanceof Tags.TagBalance)) { 203 | if (!currency) { 204 | currency = i.fields.currency; 205 | } else if (currency !== i.fields.currency) { 206 | throw Error(`Currency markers are differ [${currency}, ${i.fields.currency}] in group ${idx}`); 207 | } 208 | } 209 | 210 | // Check turnover 211 | const ob = group.find(i => i instanceof Tags.TagOpeningBalance); 212 | const cb = group.find(i => i instanceof Tags.TagClosingBalance); 213 | const turnover = cb.fields.amount - ob.fields.amount; 214 | 215 | const sumLines = group 216 | .filter(i => i instanceof Tags.TagStatementLine) 217 | .reduce((prev, cur) => prev + cur.fields.amount, 0.0); 218 | 219 | if (!helperModels.Amount.isEqual(sumLines, turnover)) { 220 | throw Error(`Sum of lines (${sumLines}) != turnover (${turnover}) in group ${idx}`); 221 | } 222 | } 223 | 224 | /** 225 | * Build statement objects 226 | * @private 227 | */ 228 | _buildStatement(group, withTags) { 229 | let statement = { 230 | transactionReference: '', 231 | relatedReference: '', 232 | accountIdentification: '', 233 | number: { 234 | statement: '', 235 | sequence: '', 236 | section: '' 237 | }, 238 | statementDate: null, 239 | openingBalanceDate: null, 240 | closingBalanceDate: null, 241 | currency: '', 242 | openingBalance: 0.0, 243 | closingBalance: 0.0, 244 | transactions: [], 245 | closingAvailableBalanceDate: null, 246 | forwardAvailableBalanceDate: null, 247 | closingAvailableBalance: 0.0, 248 | forwardAvailableBalance: 0.0, 249 | }; 250 | 251 | let prevTag; 252 | for (let tag of group) { 253 | if (tag instanceof Tags.TagMessageBlock) { 254 | if (!statement.messageBlocks) statement.messageBlocks = {}; 255 | for (let [key, value] of Object.entries(tag.fields)) { 256 | if (!value || key === 'EOB') continue; 257 | statement.messageBlocks[key] = { value }; 258 | } 259 | } 260 | if (tag instanceof Tags.TagTransactionReferenceNumber) { 261 | statement.transactionReference = tag.fields.transactionReference; 262 | } 263 | if (tag instanceof Tags.TagRelatedReference) { 264 | statement.relatedReference = tag.fields.relatedReference; 265 | } 266 | if (tag instanceof Tags.TagAccountIdentification) { 267 | statement.accountIdentification = tag.fields.accountIdentification; 268 | } 269 | if (tag instanceof Tags.TagStatementNumber) { 270 | statement.number.statement = tag.fields.statementNumber; 271 | statement.number.sequence = tag.fields.sequenceNumber; 272 | statement.number.section = tag.fields.sectionNumber; 273 | } 274 | if (tag instanceof Tags.TagOpeningBalance) { 275 | statement.openingBalanceDate = tag.fields.date; 276 | statement.openingBalance = tag.fields.amount; 277 | statement.currency = tag.fields.currency; 278 | } 279 | if (tag instanceof Tags.TagClosingBalance) { 280 | statement.closingBalanceDate = tag.fields.date; 281 | statement.statementDate = tag.fields.date; 282 | statement.closingBalance = tag.fields.amount; 283 | } 284 | if (tag instanceof Tags.TagClosingAvailableBalance) { 285 | statement.closingAvailableBalanceDate = tag.fields.date; 286 | statement.closingAvailableBalance = tag.fields.amount; 287 | } 288 | if (tag instanceof Tags.TagForwardAvailableBalance) { 289 | statement.forwardAvailableBalanceDate = tag.fields.date; 290 | statement.forwardAvailableBalance = tag.fields.amount; 291 | } 292 | if (tag instanceof Tags.TagStatementLine) { 293 | statement.transactions.push(Object.assign({}, 294 | tag.fields, 295 | { 296 | currency: statement.currency, 297 | details: '' 298 | } 299 | )); 300 | } 301 | if (tag instanceof Tags.TagTransactionDetails) { 302 | if (prevTag instanceof Tags.TagStatementLine) { 303 | let t = statement.transactions[statement.transactions.length - 1]; 304 | t.details += (t.details && '\n') + tag.fields.transactionDetails; 305 | } else { 306 | if (!statement.informationToAccountOwner) statement.informationToAccountOwner = ''; 307 | else statement.informationToAccountOwner += '\n'; 308 | statement.informationToAccountOwner += tag.fields.transactionDetails; 309 | } 310 | } 311 | if (tag instanceof Tags.TagNonSwift) { 312 | if (prevTag instanceof Tags.TagStatementLine || prevTag instanceof Tags.TagTransactionDetails) { 313 | let t = statement.transactions[statement.transactions.length - 1]; 314 | t.nonSwift = tag.data; 315 | } 316 | } 317 | if (!(tag instanceof Tags.TagNonSwift)) prevTag = tag; 318 | } 319 | 320 | for (let [messageId, message] of Object.entries(statement.messageBlocks || {})) { 321 | // EXPERIMENTAL, subject for change !!! 322 | const fields = this._parseMessageBlockFields(messageId, message.value); 323 | if (fields) message.fields = fields; 324 | } 325 | if (!this.params.no86Structure) { 326 | for (let t of statement.transactions) { 327 | let structuredDetails = Field86Structure.parse(t.details); 328 | if (structuredDetails) t.structuredDetails = structuredDetails; 329 | } 330 | } 331 | if (withTags) { statement.tags = group } // preserve tags 332 | if (!statement.closingAvailableBalanceDate) { 333 | statement.closingAvailableBalanceDate = new Date(statement.closingBalanceDate); 334 | statement.closingAvailableBalance = statement.closingBalance; 335 | } 336 | if (!statement.forwardAvailableBalanceDate) { 337 | statement.forwardAvailableBalanceDate = new Date(statement.closingAvailableBalanceDate); 338 | statement.forwardAvailableBalance = statement.closingAvailableBalance; 339 | } 340 | 341 | return statement; 342 | } 343 | 344 | /** 345 | * parses message blocks 346 | * @private 347 | */ 348 | _parseMessageBlockFields(messageId, value) { //eslint-disable-line no-unused-vars 349 | // TODO somethings like: 350 | // messageBlockFactory.createTag(messageId, value) 351 | // returns { field1: '', field2: '', subTags: { 108: { fieldA: '', fieldB: '' } } } 352 | } 353 | } 354 | 355 | module.exports = Parser; 356 | -------------------------------------------------------------------------------- /lib/tags.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tags parsing 3 | * @module lib/tags 4 | */ 5 | 6 | const helperModels = require('./helperModels'); 7 | 8 | /** 9 | * Builds a proper tag based on id, subid and tag content 10 | */ 11 | class TagFactory { 12 | /** constructor - Builds tag map */ 13 | constructor () { 14 | this.tagMap = [ 15 | TagTransactionReferenceNumber, 16 | TagRelatedReference, 17 | TagAccountIdentification, 18 | TagStatementNumber, 19 | TagNonSwift, 20 | TagOpeningBalance, 21 | TagClosingBalance, 22 | TagStatementLine, 23 | TagTransactionDetails, 24 | TagClosingAvailableBalance, 25 | TagForwardAvailableBalance, 26 | TagMessageBlock, 27 | ].reduce((map, i) => map.set(i.ID, i), new Map()); 28 | } 29 | 30 | /** 31 | * Create proper tag instance 32 | * @param {string} id - tag id (21, 61 ...) 33 | * @param {string} subId - optional tag sub Id (C, F ...) 34 | * @param {string} data - tag content (without id part) 35 | * @return {Tag} new Tag (specific subclass) instance 36 | */ 37 | createTag(id, subId, data) { 38 | const tagId = isNaN(id) ? id : Number.parseInt(id, 10); 39 | const fullTagId = tagId.toString() + (subId ? subId.toString() : ''); 40 | const tagClass = this.tagMap.get(fullTagId) || this.tagMap.get(tagId); 41 | 42 | if (!tagClass) { throw new Error(`Unknown tag ${fullTagId}`) } 43 | 44 | return new tagClass(data); 45 | } 46 | } 47 | 48 | 49 | /** 50 | * Abstract Tag base class 51 | * @abstract 52 | */ 53 | class Tag { 54 | /** Tag ID */ 55 | static get ID() { return 0 } 56 | /** Tag data regex pattern */ 57 | static get PATTERN() { return /^(.*)/ } 58 | 59 | constructor(data) { 60 | if (new.target === Tag) { 61 | throw new TypeError('Cannot construct Tag instances directly'); 62 | } 63 | this.id = this.constructor.ID; 64 | this.re = this.constructor.PATTERN; 65 | this.data = data; 66 | this._parse(); 67 | } 68 | 69 | /** 70 | * parses tag data nad saves it as `fields` attribute 71 | * @private 72 | */ 73 | _parse() { 74 | const match = this._nextMatch(); 75 | if (!match) { throw Error(`Cannot parse tag ${this.id}: ${this.data}`) } 76 | this.fields = this._extractFields(match); 77 | } 78 | 79 | _nextMatch() { 80 | return this.re.exec(this.data); 81 | } 82 | 83 | _extractFields(match) { return {} } // eslint-disable-line no-unused-vars 84 | } 85 | 86 | class TagTransactionReferenceNumber extends Tag { 87 | static get ID() { return 20 } 88 | static get PATTERN() { return /^(.{0,16})/ } 89 | _extractFields(match) { 90 | return { 91 | transactionReference: match[1] 92 | }; 93 | } 94 | } 95 | 96 | class TagRelatedReference extends Tag { 97 | static get ID() { return 21 } 98 | static get PATTERN() { return /^(.{0,16})/ } 99 | _extractFields(match) { 100 | return { 101 | relatedReference: match[1] 102 | }; 103 | } 104 | } 105 | 106 | class TagAccountIdentification extends Tag { 107 | static get ID() { return 25 } 108 | static get PATTERN() { return /^(.{0,35})/ } 109 | _extractFields(match) { 110 | return { 111 | accountIdentification: match[1] 112 | }; 113 | } 114 | } 115 | 116 | class TagStatementNumber extends Tag { 117 | static get ID() { return 28 } 118 | static get PATTERN() { return /^(\d{1,5})(\/(\d{1,5}))?(\/(\d{1,5}))?/ } 119 | _extractFields(match) { 120 | return { 121 | statementNumber: match[1], 122 | sequenceNumber: match[3] || '', 123 | sectionNumber: match[5] || '' 124 | }; 125 | } 126 | } 127 | 128 | class TagNonSwift extends Tag { 129 | static get ID() { return 'NS' } 130 | static get PATTERN() { return /^(.*)/ } 131 | _extractFields(match) { 132 | return { 133 | nonSwift: match[1] 134 | }; 135 | } 136 | } 137 | 138 | class TagBalance extends Tag { 139 | static get PATTERN() { 140 | const re = '^([DC])' // DC indicator 141 | + '(\\d{2})(\\d{2})(\\d{2})' // Date 142 | + '([A-Z]{3})' // Currency 143 | + '([0-9,]{0,16})'; // Amount 144 | return new RegExp(re); 145 | } 146 | constructor(data) { 147 | 148 | super(data); 149 | if (new.target === TagBalance) { 150 | throw new TypeError('Cannot construct TagBalance instances directly'); 151 | } 152 | } 153 | _extractFields(match) { 154 | return { 155 | date: helperModels.Date.parse(match[2], match[3], match[4]), 156 | currency: match[5], 157 | amount: helperModels.Amount.parse(match[1], match[6]) 158 | }; 159 | } 160 | } 161 | 162 | class TagOpeningBalance extends TagBalance { static get ID() { return 60 } } 163 | class TagClosingBalance extends TagBalance { static get ID() { return 62 } } 164 | class TagClosingAvailableBalance extends TagBalance { static get ID() { return 64 } } 165 | class TagForwardAvailableBalance extends TagBalance { static get ID() { return 65 } } 166 | 167 | class TagStatementLine extends Tag { 168 | static get ID() { return 61 } 169 | static get PATTERN() { 170 | const re = '^(\\d{2})(\\d{2})(\\d{2})' // Date 171 | + '((\\d{2})(\\d{2}))?' // Entry date 172 | + '(R?[DC])([A-Z])?' // DC indicator + funds code 173 | + '([0-9,]{0,16})' // Amount 174 | + '([A-Z][A-Z0-9]{3})' // Transaction type 175 | + '([^/\\n]{0,16})' // Customer reference 176 | + '(//(.{0,16}))?' // Bank reference 177 | + '(\\n(.{0,34}))?'; // Extra 178 | return new RegExp(re); 179 | } 180 | _extractFields(match) { 181 | return { 182 | date: helperModels.Date.parse(match[1], match[2], match[3]), 183 | entryDate: match[4] && helperModels.Date.parse(match[1], match[5], match[6]) || '', 184 | fundsCode: match[8] || '', 185 | amount: helperModels.Amount.parse(match[7], match[9]), 186 | isReversal: match[7][0] === 'R', 187 | transactionType: match[10], 188 | reference: match[11], 189 | bankReference: match[13] || '', 190 | extraDetails: match[15] || '' 191 | }; 192 | } 193 | } 194 | 195 | class TagTransactionDetails extends Tag { 196 | static get ID() { return 86 } 197 | static get PATTERN() { return /^([\s\S]{0,390})/ } 198 | _extractFields(match) { 199 | return { 200 | transactionDetails: match[1] 201 | }; 202 | } 203 | } 204 | 205 | class TagMessageBlock extends Tag { 206 | static get ID() { return 'MB' } 207 | static get PATTERN() { 208 | const re = 209 | '(^-\\})|(' 210 | + '\\{(\\d):' 211 | + '(.*?)' 212 | + '($|\\}(?=(\\{\\d:)|$))' 213 | + ')'; 214 | return new RegExp(re, 'g'); 215 | } 216 | _extractFields(match) { 217 | const fields = {}; 218 | while (match) { 219 | if (match[0] === '-}') { 220 | fields['EOB'] = ''; 221 | } else { 222 | fields[match[3]] = match[4]; 223 | } 224 | match = this._nextMatch(); 225 | } 226 | this.isStarting = (fields['1'] !== undefined); // has message 1 227 | return fields; 228 | } 229 | } 230 | 231 | module.exports = { 232 | TagFactory, 233 | Tag, 234 | TagTransactionReferenceNumber, 235 | TagRelatedReference, 236 | TagAccountIdentification, 237 | TagStatementNumber, 238 | TagNonSwift, 239 | TagBalance, 240 | TagOpeningBalance, 241 | TagClosingBalance, 242 | TagStatementLine, 243 | TagTransactionDetails, 244 | TagClosingAvailableBalance, 245 | TagForwardAvailableBalance, 246 | TagMessageBlock, 247 | }; 248 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mt940js", 3 | "version": "1.3.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.10.1", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", 10 | "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.1" 14 | } 15 | }, 16 | "@babel/core": { 17 | "version": "7.10.2", 18 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", 19 | "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", 20 | "dev": true, 21 | "requires": { 22 | "@babel/code-frame": "^7.10.1", 23 | "@babel/generator": "^7.10.2", 24 | "@babel/helper-module-transforms": "^7.10.1", 25 | "@babel/helpers": "^7.10.1", 26 | "@babel/parser": "^7.10.2", 27 | "@babel/template": "^7.10.1", 28 | "@babel/traverse": "^7.10.1", 29 | "@babel/types": "^7.10.2", 30 | "convert-source-map": "^1.7.0", 31 | "debug": "^4.1.0", 32 | "gensync": "^1.0.0-beta.1", 33 | "json5": "^2.1.2", 34 | "lodash": "^4.17.13", 35 | "resolve": "^1.3.2", 36 | "semver": "^5.4.1", 37 | "source-map": "^0.5.0" 38 | }, 39 | "dependencies": { 40 | "@babel/parser": { 41 | "version": "7.10.2", 42 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", 43 | "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", 44 | "dev": true 45 | }, 46 | "debug": { 47 | "version": "4.1.1", 48 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 49 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 50 | "dev": true, 51 | "requires": { 52 | "ms": "^2.1.1" 53 | } 54 | }, 55 | "resolve": { 56 | "version": "1.17.0", 57 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 58 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 59 | "dev": true, 60 | "requires": { 61 | "path-parse": "^1.0.6" 62 | } 63 | }, 64 | "semver": { 65 | "version": "5.7.1", 66 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 67 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 68 | "dev": true 69 | }, 70 | "source-map": { 71 | "version": "0.5.7", 72 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 73 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 74 | "dev": true 75 | } 76 | } 77 | }, 78 | "@babel/generator": { 79 | "version": "7.10.2", 80 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", 81 | "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", 82 | "dev": true, 83 | "requires": { 84 | "@babel/types": "^7.10.2", 85 | "jsesc": "^2.5.1", 86 | "lodash": "^4.17.13", 87 | "source-map": "^0.5.0" 88 | }, 89 | "dependencies": { 90 | "source-map": { 91 | "version": "0.5.7", 92 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 93 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 94 | "dev": true 95 | } 96 | } 97 | }, 98 | "@babel/helper-function-name": { 99 | "version": "7.10.1", 100 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", 101 | "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", 102 | "dev": true, 103 | "requires": { 104 | "@babel/helper-get-function-arity": "^7.10.1", 105 | "@babel/template": "^7.10.1", 106 | "@babel/types": "^7.10.1" 107 | } 108 | }, 109 | "@babel/helper-get-function-arity": { 110 | "version": "7.10.1", 111 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", 112 | "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", 113 | "dev": true, 114 | "requires": { 115 | "@babel/types": "^7.10.1" 116 | } 117 | }, 118 | "@babel/helper-member-expression-to-functions": { 119 | "version": "7.10.1", 120 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", 121 | "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", 122 | "dev": true, 123 | "requires": { 124 | "@babel/types": "^7.10.1" 125 | } 126 | }, 127 | "@babel/helper-module-imports": { 128 | "version": "7.10.1", 129 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", 130 | "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", 131 | "dev": true, 132 | "requires": { 133 | "@babel/types": "^7.10.1" 134 | } 135 | }, 136 | "@babel/helper-module-transforms": { 137 | "version": "7.10.1", 138 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", 139 | "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", 140 | "dev": true, 141 | "requires": { 142 | "@babel/helper-module-imports": "^7.10.1", 143 | "@babel/helper-replace-supers": "^7.10.1", 144 | "@babel/helper-simple-access": "^7.10.1", 145 | "@babel/helper-split-export-declaration": "^7.10.1", 146 | "@babel/template": "^7.10.1", 147 | "@babel/types": "^7.10.1", 148 | "lodash": "^4.17.13" 149 | } 150 | }, 151 | "@babel/helper-optimise-call-expression": { 152 | "version": "7.10.1", 153 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", 154 | "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", 155 | "dev": true, 156 | "requires": { 157 | "@babel/types": "^7.10.1" 158 | } 159 | }, 160 | "@babel/helper-replace-supers": { 161 | "version": "7.10.1", 162 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", 163 | "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", 164 | "dev": true, 165 | "requires": { 166 | "@babel/helper-member-expression-to-functions": "^7.10.1", 167 | "@babel/helper-optimise-call-expression": "^7.10.1", 168 | "@babel/traverse": "^7.10.1", 169 | "@babel/types": "^7.10.1" 170 | } 171 | }, 172 | "@babel/helper-simple-access": { 173 | "version": "7.10.1", 174 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", 175 | "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", 176 | "dev": true, 177 | "requires": { 178 | "@babel/template": "^7.10.1", 179 | "@babel/types": "^7.10.1" 180 | } 181 | }, 182 | "@babel/helper-split-export-declaration": { 183 | "version": "7.10.1", 184 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", 185 | "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", 186 | "dev": true, 187 | "requires": { 188 | "@babel/types": "^7.10.1" 189 | } 190 | }, 191 | "@babel/helper-validator-identifier": { 192 | "version": "7.10.1", 193 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", 194 | "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", 195 | "dev": true 196 | }, 197 | "@babel/helpers": { 198 | "version": "7.10.1", 199 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", 200 | "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", 201 | "dev": true, 202 | "requires": { 203 | "@babel/template": "^7.10.1", 204 | "@babel/traverse": "^7.10.1", 205 | "@babel/types": "^7.10.1" 206 | } 207 | }, 208 | "@babel/highlight": { 209 | "version": "7.10.1", 210 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", 211 | "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", 212 | "dev": true, 213 | "requires": { 214 | "@babel/helper-validator-identifier": "^7.10.1", 215 | "chalk": "^2.0.0", 216 | "js-tokens": "^4.0.0" 217 | } 218 | }, 219 | "@babel/parser": { 220 | "version": "7.14.8", 221 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.8.tgz", 222 | "integrity": "sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==", 223 | "dev": true 224 | }, 225 | "@babel/template": { 226 | "version": "7.10.1", 227 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", 228 | "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", 229 | "dev": true, 230 | "requires": { 231 | "@babel/code-frame": "^7.10.1", 232 | "@babel/parser": "^7.10.1", 233 | "@babel/types": "^7.10.1" 234 | }, 235 | "dependencies": { 236 | "@babel/parser": { 237 | "version": "7.10.2", 238 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", 239 | "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", 240 | "dev": true 241 | } 242 | } 243 | }, 244 | "@babel/traverse": { 245 | "version": "7.10.1", 246 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", 247 | "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", 248 | "dev": true, 249 | "requires": { 250 | "@babel/code-frame": "^7.10.1", 251 | "@babel/generator": "^7.10.1", 252 | "@babel/helper-function-name": "^7.10.1", 253 | "@babel/helper-split-export-declaration": "^7.10.1", 254 | "@babel/parser": "^7.10.1", 255 | "@babel/types": "^7.10.1", 256 | "debug": "^4.1.0", 257 | "globals": "^11.1.0", 258 | "lodash": "^4.17.13" 259 | }, 260 | "dependencies": { 261 | "@babel/parser": { 262 | "version": "7.10.2", 263 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", 264 | "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", 265 | "dev": true 266 | }, 267 | "debug": { 268 | "version": "4.1.1", 269 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 270 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 271 | "dev": true, 272 | "requires": { 273 | "ms": "^2.1.1" 274 | } 275 | } 276 | } 277 | }, 278 | "@babel/types": { 279 | "version": "7.10.2", 280 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", 281 | "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", 282 | "dev": true, 283 | "requires": { 284 | "@babel/helper-validator-identifier": "^7.10.1", 285 | "lodash": "^4.17.13", 286 | "to-fast-properties": "^2.0.0" 287 | } 288 | }, 289 | "@eslint/eslintrc": { 290 | "version": "0.4.3", 291 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", 292 | "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", 293 | "dev": true, 294 | "requires": { 295 | "ajv": "^6.12.4", 296 | "debug": "^4.1.1", 297 | "espree": "^7.3.0", 298 | "globals": "^13.9.0", 299 | "ignore": "^4.0.6", 300 | "import-fresh": "^3.2.1", 301 | "js-yaml": "^3.13.1", 302 | "minimatch": "^3.0.4", 303 | "strip-json-comments": "^3.1.1" 304 | }, 305 | "dependencies": { 306 | "globals": { 307 | "version": "13.10.0", 308 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", 309 | "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", 310 | "dev": true, 311 | "requires": { 312 | "type-fest": "^0.20.2" 313 | } 314 | }, 315 | "strip-json-comments": { 316 | "version": "3.1.1", 317 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 318 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 319 | "dev": true 320 | }, 321 | "type-fest": { 322 | "version": "0.20.2", 323 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 324 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 325 | "dev": true 326 | } 327 | } 328 | }, 329 | "@humanwhocodes/config-array": { 330 | "version": "0.5.0", 331 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", 332 | "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", 333 | "dev": true, 334 | "requires": { 335 | "@humanwhocodes/object-schema": "^1.2.0", 336 | "debug": "^4.1.1", 337 | "minimatch": "^3.0.4" 338 | } 339 | }, 340 | "@humanwhocodes/object-schema": { 341 | "version": "1.2.0", 342 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", 343 | "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", 344 | "dev": true 345 | }, 346 | "@istanbuljs/load-nyc-config": { 347 | "version": "1.1.0", 348 | "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", 349 | "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", 350 | "dev": true, 351 | "requires": { 352 | "camelcase": "^5.3.1", 353 | "find-up": "^4.1.0", 354 | "get-package-type": "^0.1.0", 355 | "js-yaml": "^3.13.1", 356 | "resolve-from": "^5.0.0" 357 | } 358 | }, 359 | "@istanbuljs/schema": { 360 | "version": "0.1.2", 361 | "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", 362 | "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", 363 | "dev": true 364 | }, 365 | "@types/color-name": { 366 | "version": "1.1.1", 367 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 368 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 369 | "dev": true 370 | }, 371 | "@ungap/promise-all-settled": { 372 | "version": "1.1.2", 373 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 374 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 375 | "dev": true 376 | }, 377 | "acorn": { 378 | "version": "7.4.1", 379 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 380 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 381 | "dev": true 382 | }, 383 | "acorn-jsx": { 384 | "version": "5.3.2", 385 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 386 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 387 | "dev": true 388 | }, 389 | "aggregate-error": { 390 | "version": "3.0.1", 391 | "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", 392 | "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", 393 | "dev": true, 394 | "requires": { 395 | "clean-stack": "^2.0.0", 396 | "indent-string": "^4.0.0" 397 | } 398 | }, 399 | "ajv": { 400 | "version": "6.12.6", 401 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 402 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 403 | "dev": true, 404 | "requires": { 405 | "fast-deep-equal": "^3.1.1", 406 | "fast-json-stable-stringify": "^2.0.0", 407 | "json-schema-traverse": "^0.4.1", 408 | "uri-js": "^4.2.2" 409 | } 410 | }, 411 | "ansi-colors": { 412 | "version": "4.1.1", 413 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 414 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 415 | "dev": true 416 | }, 417 | "ansi-regex": { 418 | "version": "3.0.0", 419 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 420 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 421 | "dev": true 422 | }, 423 | "ansi-styles": { 424 | "version": "3.2.1", 425 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 426 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 427 | "dev": true, 428 | "requires": { 429 | "color-convert": "^1.9.0" 430 | } 431 | }, 432 | "anymatch": { 433 | "version": "3.1.2", 434 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 435 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 436 | "dev": true, 437 | "requires": { 438 | "normalize-path": "^3.0.0", 439 | "picomatch": "^2.0.4" 440 | } 441 | }, 442 | "append-transform": { 443 | "version": "2.0.0", 444 | "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", 445 | "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", 446 | "dev": true, 447 | "requires": { 448 | "default-require-extensions": "^3.0.0" 449 | } 450 | }, 451 | "archy": { 452 | "version": "1.0.0", 453 | "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", 454 | "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", 455 | "dev": true 456 | }, 457 | "argparse": { 458 | "version": "1.0.9", 459 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 460 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 461 | "dev": true, 462 | "requires": { 463 | "sprintf-js": "~1.0.2" 464 | } 465 | }, 466 | "assertion-error": { 467 | "version": "1.1.0", 468 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 469 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 470 | "dev": true 471 | }, 472 | "astral-regex": { 473 | "version": "2.0.0", 474 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 475 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 476 | "dev": true 477 | }, 478 | "balanced-match": { 479 | "version": "1.0.0", 480 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 481 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 482 | "dev": true 483 | }, 484 | "binary-extensions": { 485 | "version": "2.2.0", 486 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 487 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 488 | "dev": true 489 | }, 490 | "bluebird": { 491 | "version": "3.7.2", 492 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 493 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", 494 | "dev": true 495 | }, 496 | "brace-expansion": { 497 | "version": "1.1.8", 498 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 499 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 500 | "dev": true, 501 | "requires": { 502 | "balanced-match": "^1.0.0", 503 | "concat-map": "0.0.1" 504 | } 505 | }, 506 | "braces": { 507 | "version": "3.0.2", 508 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 509 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 510 | "dev": true, 511 | "requires": { 512 | "fill-range": "^7.0.1" 513 | } 514 | }, 515 | "browser-stdout": { 516 | "version": "1.3.1", 517 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 518 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 519 | "dev": true 520 | }, 521 | "caching-transform": { 522 | "version": "4.0.0", 523 | "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", 524 | "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", 525 | "dev": true, 526 | "requires": { 527 | "hasha": "^5.0.0", 528 | "make-dir": "^3.0.0", 529 | "package-hash": "^4.0.0", 530 | "write-file-atomic": "^3.0.0" 531 | } 532 | }, 533 | "callsites": { 534 | "version": "3.1.0", 535 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 536 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 537 | "dev": true 538 | }, 539 | "camelcase": { 540 | "version": "5.3.1", 541 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 542 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 543 | "dev": true 544 | }, 545 | "catharsis": { 546 | "version": "0.9.0", 547 | "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", 548 | "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", 549 | "dev": true, 550 | "requires": { 551 | "lodash": "^4.17.15" 552 | } 553 | }, 554 | "chai": { 555 | "version": "4.3.4", 556 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", 557 | "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", 558 | "dev": true, 559 | "requires": { 560 | "assertion-error": "^1.1.0", 561 | "check-error": "^1.0.2", 562 | "deep-eql": "^3.0.1", 563 | "get-func-name": "^2.0.0", 564 | "pathval": "^1.1.1", 565 | "type-detect": "^4.0.5" 566 | } 567 | }, 568 | "chalk": { 569 | "version": "2.4.2", 570 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 571 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 572 | "dev": true, 573 | "requires": { 574 | "ansi-styles": "^3.2.1", 575 | "escape-string-regexp": "^1.0.5", 576 | "supports-color": "^5.3.0" 577 | }, 578 | "dependencies": { 579 | "escape-string-regexp": { 580 | "version": "1.0.5", 581 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 582 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 583 | "dev": true 584 | }, 585 | "has-flag": { 586 | "version": "3.0.0", 587 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 588 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 589 | "dev": true 590 | }, 591 | "supports-color": { 592 | "version": "5.5.0", 593 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 594 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 595 | "dev": true, 596 | "requires": { 597 | "has-flag": "^3.0.0" 598 | } 599 | } 600 | } 601 | }, 602 | "check-error": { 603 | "version": "1.0.2", 604 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 605 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 606 | "dev": true 607 | }, 608 | "chokidar": { 609 | "version": "3.5.2", 610 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", 611 | "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", 612 | "dev": true, 613 | "requires": { 614 | "anymatch": "~3.1.2", 615 | "braces": "~3.0.2", 616 | "fsevents": "~2.3.2", 617 | "glob-parent": "~5.1.2", 618 | "is-binary-path": "~2.1.0", 619 | "is-glob": "~4.0.1", 620 | "normalize-path": "~3.0.0", 621 | "readdirp": "~3.6.0" 622 | } 623 | }, 624 | "clean-stack": { 625 | "version": "2.2.0", 626 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", 627 | "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", 628 | "dev": true 629 | }, 630 | "cliui": { 631 | "version": "7.0.4", 632 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 633 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 634 | "dev": true, 635 | "requires": { 636 | "string-width": "^4.2.0", 637 | "strip-ansi": "^6.0.0", 638 | "wrap-ansi": "^7.0.0" 639 | }, 640 | "dependencies": { 641 | "ansi-regex": { 642 | "version": "5.0.0", 643 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 644 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 645 | "dev": true 646 | }, 647 | "is-fullwidth-code-point": { 648 | "version": "3.0.0", 649 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 650 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 651 | "dev": true 652 | }, 653 | "string-width": { 654 | "version": "4.2.2", 655 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 656 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 657 | "dev": true, 658 | "requires": { 659 | "emoji-regex": "^8.0.0", 660 | "is-fullwidth-code-point": "^3.0.0", 661 | "strip-ansi": "^6.0.0" 662 | } 663 | }, 664 | "strip-ansi": { 665 | "version": "6.0.0", 666 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 667 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 668 | "dev": true, 669 | "requires": { 670 | "ansi-regex": "^5.0.0" 671 | } 672 | } 673 | } 674 | }, 675 | "color-convert": { 676 | "version": "1.9.3", 677 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 678 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 679 | "dev": true, 680 | "requires": { 681 | "color-name": "1.1.3" 682 | } 683 | }, 684 | "color-name": { 685 | "version": "1.1.3", 686 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 687 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 688 | "dev": true 689 | }, 690 | "commondir": { 691 | "version": "1.0.1", 692 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 693 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 694 | "dev": true 695 | }, 696 | "concat-map": { 697 | "version": "0.0.1", 698 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 699 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 700 | "dev": true 701 | }, 702 | "convert-source-map": { 703 | "version": "1.7.0", 704 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", 705 | "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", 706 | "dev": true, 707 | "requires": { 708 | "safe-buffer": "~5.1.1" 709 | } 710 | }, 711 | "cross-spawn": { 712 | "version": "7.0.3", 713 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 714 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 715 | "dev": true, 716 | "requires": { 717 | "path-key": "^3.1.0", 718 | "shebang-command": "^2.0.0", 719 | "which": "^2.0.1" 720 | }, 721 | "dependencies": { 722 | "which": { 723 | "version": "2.0.2", 724 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 725 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 726 | "dev": true, 727 | "requires": { 728 | "isexe": "^2.0.0" 729 | } 730 | } 731 | } 732 | }, 733 | "debug": { 734 | "version": "4.3.1", 735 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 736 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 737 | "dev": true, 738 | "requires": { 739 | "ms": "2.1.2" 740 | } 741 | }, 742 | "decamelize": { 743 | "version": "1.2.0", 744 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 745 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 746 | "dev": true 747 | }, 748 | "deep-eql": { 749 | "version": "3.0.1", 750 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 751 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 752 | "dev": true, 753 | "requires": { 754 | "type-detect": "^4.0.0" 755 | } 756 | }, 757 | "deep-is": { 758 | "version": "0.1.3", 759 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 760 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 761 | "dev": true 762 | }, 763 | "default-require-extensions": { 764 | "version": "3.0.0", 765 | "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", 766 | "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", 767 | "dev": true, 768 | "requires": { 769 | "strip-bom": "^4.0.0" 770 | } 771 | }, 772 | "diff": { 773 | "version": "5.0.0", 774 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 775 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 776 | "dev": true 777 | }, 778 | "doctrine": { 779 | "version": "3.0.0", 780 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 781 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 782 | "dev": true, 783 | "requires": { 784 | "esutils": "^2.0.2" 785 | } 786 | }, 787 | "emoji-regex": { 788 | "version": "8.0.0", 789 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 790 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 791 | "dev": true 792 | }, 793 | "enquirer": { 794 | "version": "2.3.6", 795 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 796 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 797 | "dev": true, 798 | "requires": { 799 | "ansi-colors": "^4.1.1" 800 | } 801 | }, 802 | "entities": { 803 | "version": "2.0.3", 804 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", 805 | "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", 806 | "dev": true 807 | }, 808 | "es6-error": { 809 | "version": "4.1.1", 810 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 811 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 812 | "dev": true 813 | }, 814 | "escalade": { 815 | "version": "3.1.1", 816 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 817 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 818 | "dev": true 819 | }, 820 | "escape-string-regexp": { 821 | "version": "2.0.0", 822 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", 823 | "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", 824 | "dev": true 825 | }, 826 | "eslint": { 827 | "version": "7.32.0", 828 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", 829 | "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", 830 | "dev": true, 831 | "requires": { 832 | "@babel/code-frame": "7.12.11", 833 | "@eslint/eslintrc": "^0.4.3", 834 | "@humanwhocodes/config-array": "^0.5.0", 835 | "ajv": "^6.10.0", 836 | "chalk": "^4.0.0", 837 | "cross-spawn": "^7.0.2", 838 | "debug": "^4.0.1", 839 | "doctrine": "^3.0.0", 840 | "enquirer": "^2.3.5", 841 | "escape-string-regexp": "^4.0.0", 842 | "eslint-scope": "^5.1.1", 843 | "eslint-utils": "^2.1.0", 844 | "eslint-visitor-keys": "^2.0.0", 845 | "espree": "^7.3.1", 846 | "esquery": "^1.4.0", 847 | "esutils": "^2.0.2", 848 | "fast-deep-equal": "^3.1.3", 849 | "file-entry-cache": "^6.0.1", 850 | "functional-red-black-tree": "^1.0.1", 851 | "glob-parent": "^5.1.2", 852 | "globals": "^13.6.0", 853 | "ignore": "^4.0.6", 854 | "import-fresh": "^3.0.0", 855 | "imurmurhash": "^0.1.4", 856 | "is-glob": "^4.0.0", 857 | "js-yaml": "^3.13.1", 858 | "json-stable-stringify-without-jsonify": "^1.0.1", 859 | "levn": "^0.4.1", 860 | "lodash.merge": "^4.6.2", 861 | "minimatch": "^3.0.4", 862 | "natural-compare": "^1.4.0", 863 | "optionator": "^0.9.1", 864 | "progress": "^2.0.0", 865 | "regexpp": "^3.1.0", 866 | "semver": "^7.2.1", 867 | "strip-ansi": "^6.0.0", 868 | "strip-json-comments": "^3.1.0", 869 | "table": "^6.0.9", 870 | "text-table": "^0.2.0", 871 | "v8-compile-cache": "^2.0.3" 872 | }, 873 | "dependencies": { 874 | "@babel/code-frame": { 875 | "version": "7.12.11", 876 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 877 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 878 | "dev": true, 879 | "requires": { 880 | "@babel/highlight": "^7.10.4" 881 | } 882 | }, 883 | "@babel/helper-validator-identifier": { 884 | "version": "7.14.9", 885 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", 886 | "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", 887 | "dev": true 888 | }, 889 | "@babel/highlight": { 890 | "version": "7.14.5", 891 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", 892 | "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", 893 | "dev": true, 894 | "requires": { 895 | "@babel/helper-validator-identifier": "^7.14.5", 896 | "chalk": "^2.0.0", 897 | "js-tokens": "^4.0.0" 898 | }, 899 | "dependencies": { 900 | "chalk": { 901 | "version": "2.4.2", 902 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 903 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 904 | "dev": true, 905 | "requires": { 906 | "ansi-styles": "^3.2.1", 907 | "escape-string-regexp": "^1.0.5", 908 | "supports-color": "^5.3.0" 909 | } 910 | }, 911 | "escape-string-regexp": { 912 | "version": "1.0.5", 913 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 914 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 915 | "dev": true 916 | } 917 | } 918 | }, 919 | "ansi-regex": { 920 | "version": "5.0.0", 921 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 922 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 923 | "dev": true 924 | }, 925 | "chalk": { 926 | "version": "4.1.2", 927 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 928 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 929 | "dev": true, 930 | "requires": { 931 | "ansi-styles": "^4.1.0", 932 | "supports-color": "^7.1.0" 933 | }, 934 | "dependencies": { 935 | "ansi-styles": { 936 | "version": "4.3.0", 937 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 938 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 939 | "dev": true, 940 | "requires": { 941 | "color-convert": "^2.0.1" 942 | } 943 | }, 944 | "has-flag": { 945 | "version": "4.0.0", 946 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 947 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 948 | "dev": true 949 | }, 950 | "supports-color": { 951 | "version": "7.2.0", 952 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 953 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 954 | "dev": true, 955 | "requires": { 956 | "has-flag": "^4.0.0" 957 | } 958 | } 959 | } 960 | }, 961 | "color-convert": { 962 | "version": "2.0.1", 963 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 964 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 965 | "dev": true, 966 | "requires": { 967 | "color-name": "~1.1.4" 968 | } 969 | }, 970 | "color-name": { 971 | "version": "1.1.4", 972 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 973 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 974 | "dev": true 975 | }, 976 | "escape-string-regexp": { 977 | "version": "4.0.0", 978 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 979 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 980 | "dev": true 981 | }, 982 | "globals": { 983 | "version": "13.10.0", 984 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", 985 | "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", 986 | "dev": true, 987 | "requires": { 988 | "type-fest": "^0.20.2" 989 | } 990 | }, 991 | "has-flag": { 992 | "version": "3.0.0", 993 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 994 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 995 | "dev": true 996 | }, 997 | "semver": { 998 | "version": "7.3.5", 999 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1000 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1001 | "dev": true, 1002 | "requires": { 1003 | "lru-cache": "^6.0.0" 1004 | } 1005 | }, 1006 | "strip-ansi": { 1007 | "version": "6.0.0", 1008 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1009 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1010 | "dev": true, 1011 | "requires": { 1012 | "ansi-regex": "^5.0.0" 1013 | } 1014 | }, 1015 | "supports-color": { 1016 | "version": "5.5.0", 1017 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1018 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1019 | "dev": true, 1020 | "requires": { 1021 | "has-flag": "^3.0.0" 1022 | } 1023 | }, 1024 | "type-fest": { 1025 | "version": "0.20.2", 1026 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1027 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1028 | "dev": true 1029 | } 1030 | } 1031 | }, 1032 | "eslint-scope": { 1033 | "version": "5.1.1", 1034 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1035 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1036 | "dev": true, 1037 | "requires": { 1038 | "esrecurse": "^4.3.0", 1039 | "estraverse": "^4.1.1" 1040 | } 1041 | }, 1042 | "eslint-utils": { 1043 | "version": "2.1.0", 1044 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 1045 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 1046 | "dev": true, 1047 | "requires": { 1048 | "eslint-visitor-keys": "^1.1.0" 1049 | }, 1050 | "dependencies": { 1051 | "eslint-visitor-keys": { 1052 | "version": "1.3.0", 1053 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1054 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1055 | "dev": true 1056 | } 1057 | } 1058 | }, 1059 | "eslint-visitor-keys": { 1060 | "version": "2.1.0", 1061 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1062 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1063 | "dev": true 1064 | }, 1065 | "espree": { 1066 | "version": "7.3.1", 1067 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 1068 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 1069 | "dev": true, 1070 | "requires": { 1071 | "acorn": "^7.4.0", 1072 | "acorn-jsx": "^5.3.1", 1073 | "eslint-visitor-keys": "^1.3.0" 1074 | }, 1075 | "dependencies": { 1076 | "eslint-visitor-keys": { 1077 | "version": "1.3.0", 1078 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1079 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1080 | "dev": true 1081 | } 1082 | } 1083 | }, 1084 | "esquery": { 1085 | "version": "1.4.0", 1086 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 1087 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 1088 | "dev": true, 1089 | "requires": { 1090 | "estraverse": "^5.1.0" 1091 | }, 1092 | "dependencies": { 1093 | "estraverse": { 1094 | "version": "5.2.0", 1095 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1096 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1097 | "dev": true 1098 | } 1099 | } 1100 | }, 1101 | "esrecurse": { 1102 | "version": "4.3.0", 1103 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1104 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1105 | "dev": true, 1106 | "requires": { 1107 | "estraverse": "^5.2.0" 1108 | }, 1109 | "dependencies": { 1110 | "estraverse": { 1111 | "version": "5.2.0", 1112 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1113 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1114 | "dev": true 1115 | } 1116 | } 1117 | }, 1118 | "estraverse": { 1119 | "version": "4.3.0", 1120 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1121 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1122 | "dev": true 1123 | }, 1124 | "esutils": { 1125 | "version": "2.0.3", 1126 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1127 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1128 | "dev": true 1129 | }, 1130 | "fast-deep-equal": { 1131 | "version": "3.1.3", 1132 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1133 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1134 | "dev": true 1135 | }, 1136 | "fast-json-stable-stringify": { 1137 | "version": "2.1.0", 1138 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1139 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1140 | "dev": true 1141 | }, 1142 | "fast-levenshtein": { 1143 | "version": "2.0.6", 1144 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1145 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1146 | "dev": true 1147 | }, 1148 | "file-entry-cache": { 1149 | "version": "6.0.1", 1150 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1151 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1152 | "dev": true, 1153 | "requires": { 1154 | "flat-cache": "^3.0.4" 1155 | } 1156 | }, 1157 | "fill-range": { 1158 | "version": "7.0.1", 1159 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1160 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1161 | "dev": true, 1162 | "requires": { 1163 | "to-regex-range": "^5.0.1" 1164 | } 1165 | }, 1166 | "find-cache-dir": { 1167 | "version": "3.3.1", 1168 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", 1169 | "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", 1170 | "dev": true, 1171 | "requires": { 1172 | "commondir": "^1.0.1", 1173 | "make-dir": "^3.0.2", 1174 | "pkg-dir": "^4.1.0" 1175 | } 1176 | }, 1177 | "find-up": { 1178 | "version": "4.1.0", 1179 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1180 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1181 | "dev": true, 1182 | "requires": { 1183 | "locate-path": "^5.0.0", 1184 | "path-exists": "^4.0.0" 1185 | } 1186 | }, 1187 | "flat": { 1188 | "version": "5.0.2", 1189 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 1190 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 1191 | "dev": true 1192 | }, 1193 | "flat-cache": { 1194 | "version": "3.0.4", 1195 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1196 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1197 | "dev": true, 1198 | "requires": { 1199 | "flatted": "^3.1.0", 1200 | "rimraf": "^3.0.2" 1201 | } 1202 | }, 1203 | "flatted": { 1204 | "version": "3.2.2", 1205 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", 1206 | "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", 1207 | "dev": true 1208 | }, 1209 | "foreground-child": { 1210 | "version": "2.0.0", 1211 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", 1212 | "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", 1213 | "dev": true, 1214 | "requires": { 1215 | "cross-spawn": "^7.0.0", 1216 | "signal-exit": "^3.0.2" 1217 | } 1218 | }, 1219 | "fromentries": { 1220 | "version": "1.2.0", 1221 | "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", 1222 | "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", 1223 | "dev": true 1224 | }, 1225 | "fs.realpath": { 1226 | "version": "1.0.0", 1227 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1228 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1229 | "dev": true 1230 | }, 1231 | "fsevents": { 1232 | "version": "2.3.2", 1233 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1234 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1235 | "dev": true, 1236 | "optional": true 1237 | }, 1238 | "functional-red-black-tree": { 1239 | "version": "1.0.1", 1240 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1241 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1242 | "dev": true 1243 | }, 1244 | "gensync": { 1245 | "version": "1.0.0-beta.1", 1246 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", 1247 | "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", 1248 | "dev": true 1249 | }, 1250 | "get-caller-file": { 1251 | "version": "2.0.5", 1252 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1253 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1254 | "dev": true 1255 | }, 1256 | "get-func-name": { 1257 | "version": "2.0.0", 1258 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 1259 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 1260 | "dev": true 1261 | }, 1262 | "get-package-type": { 1263 | "version": "0.1.0", 1264 | "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", 1265 | "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", 1266 | "dev": true 1267 | }, 1268 | "glob": { 1269 | "version": "7.1.7", 1270 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 1271 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 1272 | "dev": true, 1273 | "requires": { 1274 | "fs.realpath": "^1.0.0", 1275 | "inflight": "^1.0.4", 1276 | "inherits": "2", 1277 | "minimatch": "^3.0.4", 1278 | "once": "^1.3.0", 1279 | "path-is-absolute": "^1.0.0" 1280 | } 1281 | }, 1282 | "glob-parent": { 1283 | "version": "5.1.2", 1284 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1285 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1286 | "dev": true, 1287 | "requires": { 1288 | "is-glob": "^4.0.1" 1289 | } 1290 | }, 1291 | "globals": { 1292 | "version": "11.12.0", 1293 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1294 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 1295 | "dev": true 1296 | }, 1297 | "graceful-fs": { 1298 | "version": "4.2.4", 1299 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 1300 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 1301 | "dev": true 1302 | }, 1303 | "growl": { 1304 | "version": "1.10.5", 1305 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 1306 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 1307 | "dev": true 1308 | }, 1309 | "has-flag": { 1310 | "version": "4.0.0", 1311 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1312 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1313 | "dev": true 1314 | }, 1315 | "hasha": { 1316 | "version": "5.2.0", 1317 | "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", 1318 | "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", 1319 | "dev": true, 1320 | "requires": { 1321 | "is-stream": "^2.0.0", 1322 | "type-fest": "^0.8.0" 1323 | } 1324 | }, 1325 | "he": { 1326 | "version": "1.2.0", 1327 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 1328 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 1329 | "dev": true 1330 | }, 1331 | "html-escaper": { 1332 | "version": "2.0.2", 1333 | "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", 1334 | "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", 1335 | "dev": true 1336 | }, 1337 | "ignore": { 1338 | "version": "4.0.6", 1339 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1340 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1341 | "dev": true 1342 | }, 1343 | "import-fresh": { 1344 | "version": "3.3.0", 1345 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1346 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1347 | "dev": true, 1348 | "requires": { 1349 | "parent-module": "^1.0.0", 1350 | "resolve-from": "^4.0.0" 1351 | }, 1352 | "dependencies": { 1353 | "resolve-from": { 1354 | "version": "4.0.0", 1355 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1356 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1357 | "dev": true 1358 | } 1359 | } 1360 | }, 1361 | "imurmurhash": { 1362 | "version": "0.1.4", 1363 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1364 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1365 | "dev": true 1366 | }, 1367 | "indent-string": { 1368 | "version": "4.0.0", 1369 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 1370 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", 1371 | "dev": true 1372 | }, 1373 | "inflight": { 1374 | "version": "1.0.6", 1375 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1376 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1377 | "dev": true, 1378 | "requires": { 1379 | "once": "^1.3.0", 1380 | "wrappy": "1" 1381 | } 1382 | }, 1383 | "inherits": { 1384 | "version": "2.0.3", 1385 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1386 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 1387 | "dev": true 1388 | }, 1389 | "is-binary-path": { 1390 | "version": "2.1.0", 1391 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1392 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1393 | "dev": true, 1394 | "requires": { 1395 | "binary-extensions": "^2.0.0" 1396 | } 1397 | }, 1398 | "is-extglob": { 1399 | "version": "2.1.1", 1400 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1401 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1402 | "dev": true 1403 | }, 1404 | "is-fullwidth-code-point": { 1405 | "version": "2.0.0", 1406 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1407 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1408 | "dev": true 1409 | }, 1410 | "is-glob": { 1411 | "version": "4.0.1", 1412 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1413 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1414 | "dev": true, 1415 | "requires": { 1416 | "is-extglob": "^2.1.1" 1417 | } 1418 | }, 1419 | "is-number": { 1420 | "version": "7.0.0", 1421 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1422 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1423 | "dev": true 1424 | }, 1425 | "is-plain-obj": { 1426 | "version": "2.1.0", 1427 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 1428 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 1429 | "dev": true 1430 | }, 1431 | "is-stream": { 1432 | "version": "2.0.0", 1433 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 1434 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", 1435 | "dev": true 1436 | }, 1437 | "is-typedarray": { 1438 | "version": "1.0.0", 1439 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1440 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1441 | "dev": true 1442 | }, 1443 | "is-unicode-supported": { 1444 | "version": "0.1.0", 1445 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 1446 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 1447 | "dev": true 1448 | }, 1449 | "is-windows": { 1450 | "version": "1.0.2", 1451 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1452 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", 1453 | "dev": true 1454 | }, 1455 | "isexe": { 1456 | "version": "2.0.0", 1457 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1458 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1459 | "dev": true 1460 | }, 1461 | "istanbul-lib-coverage": { 1462 | "version": "3.0.0", 1463 | "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", 1464 | "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", 1465 | "dev": true 1466 | }, 1467 | "istanbul-lib-hook": { 1468 | "version": "3.0.0", 1469 | "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", 1470 | "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", 1471 | "dev": true, 1472 | "requires": { 1473 | "append-transform": "^2.0.0" 1474 | } 1475 | }, 1476 | "istanbul-lib-instrument": { 1477 | "version": "4.0.3", 1478 | "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", 1479 | "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", 1480 | "dev": true, 1481 | "requires": { 1482 | "@babel/core": "^7.7.5", 1483 | "@istanbuljs/schema": "^0.1.2", 1484 | "istanbul-lib-coverage": "^3.0.0", 1485 | "semver": "^6.3.0" 1486 | } 1487 | }, 1488 | "istanbul-lib-processinfo": { 1489 | "version": "2.0.2", 1490 | "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", 1491 | "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", 1492 | "dev": true, 1493 | "requires": { 1494 | "archy": "^1.0.0", 1495 | "cross-spawn": "^7.0.0", 1496 | "istanbul-lib-coverage": "^3.0.0-alpha.1", 1497 | "make-dir": "^3.0.0", 1498 | "p-map": "^3.0.0", 1499 | "rimraf": "^3.0.0", 1500 | "uuid": "^3.3.3" 1501 | } 1502 | }, 1503 | "istanbul-lib-report": { 1504 | "version": "3.0.0", 1505 | "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", 1506 | "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", 1507 | "dev": true, 1508 | "requires": { 1509 | "istanbul-lib-coverage": "^3.0.0", 1510 | "make-dir": "^3.0.0", 1511 | "supports-color": "^7.1.0" 1512 | }, 1513 | "dependencies": { 1514 | "has-flag": { 1515 | "version": "4.0.0", 1516 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1517 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1518 | "dev": true 1519 | }, 1520 | "supports-color": { 1521 | "version": "7.1.0", 1522 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 1523 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 1524 | "dev": true, 1525 | "requires": { 1526 | "has-flag": "^4.0.0" 1527 | } 1528 | } 1529 | } 1530 | }, 1531 | "istanbul-lib-source-maps": { 1532 | "version": "4.0.0", 1533 | "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", 1534 | "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", 1535 | "dev": true, 1536 | "requires": { 1537 | "debug": "^4.1.1", 1538 | "istanbul-lib-coverage": "^3.0.0", 1539 | "source-map": "^0.6.1" 1540 | }, 1541 | "dependencies": { 1542 | "debug": { 1543 | "version": "4.1.1", 1544 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1545 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1546 | "dev": true, 1547 | "requires": { 1548 | "ms": "^2.1.1" 1549 | } 1550 | }, 1551 | "source-map": { 1552 | "version": "0.6.1", 1553 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1554 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1555 | "dev": true 1556 | } 1557 | } 1558 | }, 1559 | "istanbul-reports": { 1560 | "version": "3.0.2", 1561 | "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", 1562 | "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", 1563 | "dev": true, 1564 | "requires": { 1565 | "html-escaper": "^2.0.0", 1566 | "istanbul-lib-report": "^3.0.0" 1567 | } 1568 | }, 1569 | "js-tokens": { 1570 | "version": "4.0.0", 1571 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1572 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1573 | "dev": true 1574 | }, 1575 | "js-yaml": { 1576 | "version": "3.13.1", 1577 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1578 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1579 | "dev": true, 1580 | "requires": { 1581 | "argparse": "^1.0.7", 1582 | "esprima": "^4.0.0" 1583 | }, 1584 | "dependencies": { 1585 | "esprima": { 1586 | "version": "4.0.1", 1587 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1588 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1589 | "dev": true 1590 | } 1591 | } 1592 | }, 1593 | "js2xmlparser": { 1594 | "version": "4.0.1", 1595 | "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", 1596 | "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", 1597 | "dev": true, 1598 | "requires": { 1599 | "xmlcreate": "^2.0.3" 1600 | } 1601 | }, 1602 | "jsdoc": { 1603 | "version": "3.6.7", 1604 | "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", 1605 | "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", 1606 | "dev": true, 1607 | "requires": { 1608 | "@babel/parser": "^7.9.4", 1609 | "bluebird": "^3.7.2", 1610 | "catharsis": "^0.9.0", 1611 | "escape-string-regexp": "^2.0.0", 1612 | "js2xmlparser": "^4.0.1", 1613 | "klaw": "^3.0.0", 1614 | "markdown-it": "^10.0.0", 1615 | "markdown-it-anchor": "^5.2.7", 1616 | "marked": "^2.0.3", 1617 | "mkdirp": "^1.0.4", 1618 | "requizzle": "^0.2.3", 1619 | "strip-json-comments": "^3.1.0", 1620 | "taffydb": "2.6.2", 1621 | "underscore": "~1.13.1" 1622 | } 1623 | }, 1624 | "jsesc": { 1625 | "version": "2.5.2", 1626 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1627 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1628 | "dev": true 1629 | }, 1630 | "json-schema-traverse": { 1631 | "version": "0.4.1", 1632 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1633 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1634 | "dev": true 1635 | }, 1636 | "json-stable-stringify-without-jsonify": { 1637 | "version": "1.0.1", 1638 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1639 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1640 | "dev": true 1641 | }, 1642 | "json5": { 1643 | "version": "2.1.3", 1644 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", 1645 | "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", 1646 | "dev": true, 1647 | "requires": { 1648 | "minimist": "^1.2.5" 1649 | }, 1650 | "dependencies": { 1651 | "minimist": { 1652 | "version": "1.2.5", 1653 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1654 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1655 | "dev": true 1656 | } 1657 | } 1658 | }, 1659 | "klaw": { 1660 | "version": "3.0.0", 1661 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", 1662 | "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", 1663 | "dev": true, 1664 | "requires": { 1665 | "graceful-fs": "^4.1.9" 1666 | } 1667 | }, 1668 | "levn": { 1669 | "version": "0.4.1", 1670 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1671 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1672 | "dev": true, 1673 | "requires": { 1674 | "prelude-ls": "^1.2.1", 1675 | "type-check": "~0.4.0" 1676 | } 1677 | }, 1678 | "linkify-it": { 1679 | "version": "2.2.0", 1680 | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", 1681 | "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", 1682 | "dev": true, 1683 | "requires": { 1684 | "uc.micro": "^1.0.1" 1685 | } 1686 | }, 1687 | "locate-path": { 1688 | "version": "5.0.0", 1689 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1690 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1691 | "dev": true, 1692 | "requires": { 1693 | "p-locate": "^4.1.0" 1694 | } 1695 | }, 1696 | "lodash": { 1697 | "version": "4.17.21", 1698 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1699 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1700 | "dev": true 1701 | }, 1702 | "lodash.clonedeep": { 1703 | "version": "4.5.0", 1704 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", 1705 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", 1706 | "dev": true 1707 | }, 1708 | "lodash.flattendeep": { 1709 | "version": "4.4.0", 1710 | "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", 1711 | "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", 1712 | "dev": true 1713 | }, 1714 | "lodash.merge": { 1715 | "version": "4.6.2", 1716 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1717 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1718 | "dev": true 1719 | }, 1720 | "lodash.truncate": { 1721 | "version": "4.4.2", 1722 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", 1723 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", 1724 | "dev": true 1725 | }, 1726 | "log-symbols": { 1727 | "version": "4.1.0", 1728 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1729 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1730 | "dev": true, 1731 | "requires": { 1732 | "chalk": "^4.1.0", 1733 | "is-unicode-supported": "^0.1.0" 1734 | }, 1735 | "dependencies": { 1736 | "ansi-styles": { 1737 | "version": "4.3.0", 1738 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1739 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1740 | "dev": true, 1741 | "requires": { 1742 | "color-convert": "^2.0.1" 1743 | } 1744 | }, 1745 | "chalk": { 1746 | "version": "4.1.2", 1747 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1748 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1749 | "dev": true, 1750 | "requires": { 1751 | "ansi-styles": "^4.1.0", 1752 | "supports-color": "^7.1.0" 1753 | } 1754 | }, 1755 | "color-convert": { 1756 | "version": "2.0.1", 1757 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1758 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1759 | "dev": true, 1760 | "requires": { 1761 | "color-name": "~1.1.4" 1762 | } 1763 | }, 1764 | "color-name": { 1765 | "version": "1.1.4", 1766 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1767 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1768 | "dev": true 1769 | }, 1770 | "supports-color": { 1771 | "version": "7.2.0", 1772 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1773 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1774 | "dev": true, 1775 | "requires": { 1776 | "has-flag": "^4.0.0" 1777 | } 1778 | } 1779 | } 1780 | }, 1781 | "lru-cache": { 1782 | "version": "6.0.0", 1783 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1784 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1785 | "dev": true, 1786 | "requires": { 1787 | "yallist": "^4.0.0" 1788 | } 1789 | }, 1790 | "make-dir": { 1791 | "version": "3.1.0", 1792 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1793 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1794 | "dev": true, 1795 | "requires": { 1796 | "semver": "^6.0.0" 1797 | } 1798 | }, 1799 | "markdown-it": { 1800 | "version": "10.0.0", 1801 | "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", 1802 | "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", 1803 | "dev": true, 1804 | "requires": { 1805 | "argparse": "^1.0.7", 1806 | "entities": "~2.0.0", 1807 | "linkify-it": "^2.0.0", 1808 | "mdurl": "^1.0.1", 1809 | "uc.micro": "^1.0.5" 1810 | } 1811 | }, 1812 | "markdown-it-anchor": { 1813 | "version": "5.3.0", 1814 | "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", 1815 | "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", 1816 | "dev": true 1817 | }, 1818 | "marked": { 1819 | "version": "2.1.3", 1820 | "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", 1821 | "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", 1822 | "dev": true 1823 | }, 1824 | "mdurl": { 1825 | "version": "1.0.1", 1826 | "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", 1827 | "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", 1828 | "dev": true 1829 | }, 1830 | "minimatch": { 1831 | "version": "3.0.4", 1832 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1833 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1834 | "dev": true, 1835 | "requires": { 1836 | "brace-expansion": "^1.1.7" 1837 | } 1838 | }, 1839 | "mkdirp": { 1840 | "version": "1.0.4", 1841 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 1842 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 1843 | "dev": true 1844 | }, 1845 | "mocha": { 1846 | "version": "9.1.1", 1847 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", 1848 | "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", 1849 | "dev": true, 1850 | "requires": { 1851 | "@ungap/promise-all-settled": "1.1.2", 1852 | "ansi-colors": "4.1.1", 1853 | "browser-stdout": "1.3.1", 1854 | "chokidar": "3.5.2", 1855 | "debug": "4.3.1", 1856 | "diff": "5.0.0", 1857 | "escape-string-regexp": "4.0.0", 1858 | "find-up": "5.0.0", 1859 | "glob": "7.1.7", 1860 | "growl": "1.10.5", 1861 | "he": "1.2.0", 1862 | "js-yaml": "4.1.0", 1863 | "log-symbols": "4.1.0", 1864 | "minimatch": "3.0.4", 1865 | "ms": "2.1.3", 1866 | "nanoid": "3.1.23", 1867 | "serialize-javascript": "6.0.0", 1868 | "strip-json-comments": "3.1.1", 1869 | "supports-color": "8.1.1", 1870 | "which": "2.0.2", 1871 | "wide-align": "1.1.3", 1872 | "workerpool": "6.1.5", 1873 | "yargs": "16.2.0", 1874 | "yargs-parser": "20.2.4", 1875 | "yargs-unparser": "2.0.0" 1876 | }, 1877 | "dependencies": { 1878 | "argparse": { 1879 | "version": "2.0.1", 1880 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1881 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1882 | "dev": true 1883 | }, 1884 | "escape-string-regexp": { 1885 | "version": "4.0.0", 1886 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1887 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1888 | "dev": true 1889 | }, 1890 | "find-up": { 1891 | "version": "5.0.0", 1892 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1893 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1894 | "dev": true, 1895 | "requires": { 1896 | "locate-path": "^6.0.0", 1897 | "path-exists": "^4.0.0" 1898 | } 1899 | }, 1900 | "js-yaml": { 1901 | "version": "4.1.0", 1902 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1903 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1904 | "dev": true, 1905 | "requires": { 1906 | "argparse": "^2.0.1" 1907 | } 1908 | }, 1909 | "locate-path": { 1910 | "version": "6.0.0", 1911 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1912 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1913 | "dev": true, 1914 | "requires": { 1915 | "p-locate": "^5.0.0" 1916 | } 1917 | }, 1918 | "ms": { 1919 | "version": "2.1.3", 1920 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1921 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1922 | "dev": true 1923 | }, 1924 | "p-limit": { 1925 | "version": "3.1.0", 1926 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1927 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1928 | "dev": true, 1929 | "requires": { 1930 | "yocto-queue": "^0.1.0" 1931 | } 1932 | }, 1933 | "p-locate": { 1934 | "version": "5.0.0", 1935 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1936 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1937 | "dev": true, 1938 | "requires": { 1939 | "p-limit": "^3.0.2" 1940 | } 1941 | }, 1942 | "strip-json-comments": { 1943 | "version": "3.1.1", 1944 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1945 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1946 | "dev": true 1947 | } 1948 | } 1949 | }, 1950 | "ms": { 1951 | "version": "2.1.2", 1952 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1953 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1954 | "dev": true 1955 | }, 1956 | "nanoid": { 1957 | "version": "3.1.23", 1958 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", 1959 | "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", 1960 | "dev": true 1961 | }, 1962 | "natural-compare": { 1963 | "version": "1.4.0", 1964 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1965 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1966 | "dev": true 1967 | }, 1968 | "node-preload": { 1969 | "version": "0.2.1", 1970 | "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", 1971 | "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", 1972 | "dev": true, 1973 | "requires": { 1974 | "process-on-spawn": "^1.0.0" 1975 | } 1976 | }, 1977 | "normalize-path": { 1978 | "version": "3.0.0", 1979 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1980 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1981 | "dev": true 1982 | }, 1983 | "nyc": { 1984 | "version": "15.1.0", 1985 | "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", 1986 | "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", 1987 | "dev": true, 1988 | "requires": { 1989 | "@istanbuljs/load-nyc-config": "^1.0.0", 1990 | "@istanbuljs/schema": "^0.1.2", 1991 | "caching-transform": "^4.0.0", 1992 | "convert-source-map": "^1.7.0", 1993 | "decamelize": "^1.2.0", 1994 | "find-cache-dir": "^3.2.0", 1995 | "find-up": "^4.1.0", 1996 | "foreground-child": "^2.0.0", 1997 | "get-package-type": "^0.1.0", 1998 | "glob": "^7.1.6", 1999 | "istanbul-lib-coverage": "^3.0.0", 2000 | "istanbul-lib-hook": "^3.0.0", 2001 | "istanbul-lib-instrument": "^4.0.0", 2002 | "istanbul-lib-processinfo": "^2.0.2", 2003 | "istanbul-lib-report": "^3.0.0", 2004 | "istanbul-lib-source-maps": "^4.0.0", 2005 | "istanbul-reports": "^3.0.2", 2006 | "make-dir": "^3.0.0", 2007 | "node-preload": "^0.2.1", 2008 | "p-map": "^3.0.0", 2009 | "process-on-spawn": "^1.0.0", 2010 | "resolve-from": "^5.0.0", 2011 | "rimraf": "^3.0.0", 2012 | "signal-exit": "^3.0.2", 2013 | "spawn-wrap": "^2.0.0", 2014 | "test-exclude": "^6.0.0", 2015 | "yargs": "^15.0.2" 2016 | }, 2017 | "dependencies": { 2018 | "ansi-regex": { 2019 | "version": "5.0.0", 2020 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2021 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2022 | "dev": true 2023 | }, 2024 | "ansi-styles": { 2025 | "version": "4.2.1", 2026 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 2027 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 2028 | "dev": true, 2029 | "requires": { 2030 | "@types/color-name": "^1.1.1", 2031 | "color-convert": "^2.0.1" 2032 | } 2033 | }, 2034 | "cliui": { 2035 | "version": "6.0.0", 2036 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 2037 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 2038 | "dev": true, 2039 | "requires": { 2040 | "string-width": "^4.2.0", 2041 | "strip-ansi": "^6.0.0", 2042 | "wrap-ansi": "^6.2.0" 2043 | } 2044 | }, 2045 | "color-convert": { 2046 | "version": "2.0.1", 2047 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2048 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2049 | "dev": true, 2050 | "requires": { 2051 | "color-name": "~1.1.4" 2052 | } 2053 | }, 2054 | "color-name": { 2055 | "version": "1.1.4", 2056 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2057 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2058 | "dev": true 2059 | }, 2060 | "emoji-regex": { 2061 | "version": "8.0.0", 2062 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2063 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2064 | "dev": true 2065 | }, 2066 | "glob": { 2067 | "version": "7.1.6", 2068 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 2069 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 2070 | "dev": true, 2071 | "requires": { 2072 | "fs.realpath": "^1.0.0", 2073 | "inflight": "^1.0.4", 2074 | "inherits": "2", 2075 | "minimatch": "^3.0.4", 2076 | "once": "^1.3.0", 2077 | "path-is-absolute": "^1.0.0" 2078 | } 2079 | }, 2080 | "is-fullwidth-code-point": { 2081 | "version": "3.0.0", 2082 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2083 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2084 | "dev": true 2085 | }, 2086 | "string-width": { 2087 | "version": "4.2.0", 2088 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 2089 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 2090 | "dev": true, 2091 | "requires": { 2092 | "emoji-regex": "^8.0.0", 2093 | "is-fullwidth-code-point": "^3.0.0", 2094 | "strip-ansi": "^6.0.0" 2095 | } 2096 | }, 2097 | "strip-ansi": { 2098 | "version": "6.0.0", 2099 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2100 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2101 | "dev": true, 2102 | "requires": { 2103 | "ansi-regex": "^5.0.0" 2104 | } 2105 | }, 2106 | "wrap-ansi": { 2107 | "version": "6.2.0", 2108 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 2109 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 2110 | "dev": true, 2111 | "requires": { 2112 | "ansi-styles": "^4.0.0", 2113 | "string-width": "^4.1.0", 2114 | "strip-ansi": "^6.0.0" 2115 | } 2116 | }, 2117 | "y18n": { 2118 | "version": "4.0.3", 2119 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 2120 | "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", 2121 | "dev": true 2122 | }, 2123 | "yargs": { 2124 | "version": "15.3.1", 2125 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", 2126 | "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", 2127 | "dev": true, 2128 | "requires": { 2129 | "cliui": "^6.0.0", 2130 | "decamelize": "^1.2.0", 2131 | "find-up": "^4.1.0", 2132 | "get-caller-file": "^2.0.1", 2133 | "require-directory": "^2.1.1", 2134 | "require-main-filename": "^2.0.0", 2135 | "set-blocking": "^2.0.0", 2136 | "string-width": "^4.2.0", 2137 | "which-module": "^2.0.0", 2138 | "y18n": "^4.0.0", 2139 | "yargs-parser": "^18.1.1" 2140 | } 2141 | }, 2142 | "yargs-parser": { 2143 | "version": "18.1.3", 2144 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2145 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2146 | "dev": true, 2147 | "requires": { 2148 | "camelcase": "^5.0.0", 2149 | "decamelize": "^1.2.0" 2150 | } 2151 | } 2152 | } 2153 | }, 2154 | "once": { 2155 | "version": "1.4.0", 2156 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2157 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2158 | "dev": true, 2159 | "requires": { 2160 | "wrappy": "1" 2161 | } 2162 | }, 2163 | "optionator": { 2164 | "version": "0.9.1", 2165 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 2166 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 2167 | "dev": true, 2168 | "requires": { 2169 | "deep-is": "^0.1.3", 2170 | "fast-levenshtein": "^2.0.6", 2171 | "levn": "^0.4.1", 2172 | "prelude-ls": "^1.2.1", 2173 | "type-check": "^0.4.0", 2174 | "word-wrap": "^1.2.3" 2175 | } 2176 | }, 2177 | "p-limit": { 2178 | "version": "2.3.0", 2179 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2180 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2181 | "dev": true, 2182 | "requires": { 2183 | "p-try": "^2.0.0" 2184 | } 2185 | }, 2186 | "p-locate": { 2187 | "version": "4.1.0", 2188 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2189 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2190 | "dev": true, 2191 | "requires": { 2192 | "p-limit": "^2.2.0" 2193 | } 2194 | }, 2195 | "p-map": { 2196 | "version": "3.0.0", 2197 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", 2198 | "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", 2199 | "dev": true, 2200 | "requires": { 2201 | "aggregate-error": "^3.0.0" 2202 | } 2203 | }, 2204 | "p-try": { 2205 | "version": "2.2.0", 2206 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2207 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 2208 | "dev": true 2209 | }, 2210 | "package-hash": { 2211 | "version": "4.0.0", 2212 | "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", 2213 | "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", 2214 | "dev": true, 2215 | "requires": { 2216 | "graceful-fs": "^4.1.15", 2217 | "hasha": "^5.0.0", 2218 | "lodash.flattendeep": "^4.4.0", 2219 | "release-zalgo": "^1.0.0" 2220 | } 2221 | }, 2222 | "parent-module": { 2223 | "version": "1.0.1", 2224 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2225 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2226 | "dev": true, 2227 | "requires": { 2228 | "callsites": "^3.0.0" 2229 | } 2230 | }, 2231 | "path-exists": { 2232 | "version": "4.0.0", 2233 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2234 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2235 | "dev": true 2236 | }, 2237 | "path-is-absolute": { 2238 | "version": "1.0.1", 2239 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2240 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2241 | "dev": true 2242 | }, 2243 | "path-key": { 2244 | "version": "3.1.1", 2245 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2246 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2247 | "dev": true 2248 | }, 2249 | "path-parse": { 2250 | "version": "1.0.7", 2251 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2252 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2253 | "dev": true 2254 | }, 2255 | "pathval": { 2256 | "version": "1.1.1", 2257 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 2258 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 2259 | "dev": true 2260 | }, 2261 | "picomatch": { 2262 | "version": "2.3.0", 2263 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 2264 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 2265 | "dev": true 2266 | }, 2267 | "pkg-dir": { 2268 | "version": "4.2.0", 2269 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2270 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2271 | "dev": true, 2272 | "requires": { 2273 | "find-up": "^4.0.0" 2274 | } 2275 | }, 2276 | "prelude-ls": { 2277 | "version": "1.2.1", 2278 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2279 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2280 | "dev": true 2281 | }, 2282 | "process-on-spawn": { 2283 | "version": "1.0.0", 2284 | "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", 2285 | "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", 2286 | "dev": true, 2287 | "requires": { 2288 | "fromentries": "^1.2.0" 2289 | } 2290 | }, 2291 | "progress": { 2292 | "version": "2.0.3", 2293 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2294 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2295 | "dev": true 2296 | }, 2297 | "punycode": { 2298 | "version": "2.1.1", 2299 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2300 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2301 | "dev": true 2302 | }, 2303 | "randombytes": { 2304 | "version": "2.1.0", 2305 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 2306 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 2307 | "dev": true, 2308 | "requires": { 2309 | "safe-buffer": "^5.1.0" 2310 | } 2311 | }, 2312 | "readdirp": { 2313 | "version": "3.6.0", 2314 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2315 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2316 | "dev": true, 2317 | "requires": { 2318 | "picomatch": "^2.2.1" 2319 | } 2320 | }, 2321 | "regexpp": { 2322 | "version": "3.2.0", 2323 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2324 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2325 | "dev": true 2326 | }, 2327 | "release-zalgo": { 2328 | "version": "1.0.0", 2329 | "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", 2330 | "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", 2331 | "dev": true, 2332 | "requires": { 2333 | "es6-error": "^4.0.1" 2334 | } 2335 | }, 2336 | "require-directory": { 2337 | "version": "2.1.1", 2338 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2339 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 2340 | "dev": true 2341 | }, 2342 | "require-from-string": { 2343 | "version": "2.0.2", 2344 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 2345 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 2346 | "dev": true 2347 | }, 2348 | "require-main-filename": { 2349 | "version": "2.0.0", 2350 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 2351 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 2352 | "dev": true 2353 | }, 2354 | "requizzle": { 2355 | "version": "0.2.3", 2356 | "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", 2357 | "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", 2358 | "dev": true, 2359 | "requires": { 2360 | "lodash": "^4.17.14" 2361 | } 2362 | }, 2363 | "resolve-from": { 2364 | "version": "5.0.0", 2365 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 2366 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 2367 | "dev": true 2368 | }, 2369 | "rimraf": { 2370 | "version": "3.0.2", 2371 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2372 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2373 | "dev": true, 2374 | "requires": { 2375 | "glob": "^7.1.3" 2376 | }, 2377 | "dependencies": { 2378 | "glob": { 2379 | "version": "7.1.6", 2380 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 2381 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 2382 | "dev": true, 2383 | "requires": { 2384 | "fs.realpath": "^1.0.0", 2385 | "inflight": "^1.0.4", 2386 | "inherits": "2", 2387 | "minimatch": "^3.0.4", 2388 | "once": "^1.3.0", 2389 | "path-is-absolute": "^1.0.0" 2390 | } 2391 | } 2392 | } 2393 | }, 2394 | "safe-buffer": { 2395 | "version": "5.1.2", 2396 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2397 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 2398 | "dev": true 2399 | }, 2400 | "semver": { 2401 | "version": "6.3.0", 2402 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 2403 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 2404 | "dev": true 2405 | }, 2406 | "serialize-javascript": { 2407 | "version": "6.0.0", 2408 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 2409 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 2410 | "dev": true, 2411 | "requires": { 2412 | "randombytes": "^2.1.0" 2413 | } 2414 | }, 2415 | "set-blocking": { 2416 | "version": "2.0.0", 2417 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2418 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 2419 | "dev": true 2420 | }, 2421 | "shebang-command": { 2422 | "version": "2.0.0", 2423 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2424 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2425 | "dev": true, 2426 | "requires": { 2427 | "shebang-regex": "^3.0.0" 2428 | } 2429 | }, 2430 | "shebang-regex": { 2431 | "version": "3.0.0", 2432 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2433 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2434 | "dev": true 2435 | }, 2436 | "signal-exit": { 2437 | "version": "3.0.3", 2438 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 2439 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 2440 | "dev": true 2441 | }, 2442 | "slice-ansi": { 2443 | "version": "4.0.0", 2444 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 2445 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 2446 | "dev": true, 2447 | "requires": { 2448 | "ansi-styles": "^4.0.0", 2449 | "astral-regex": "^2.0.0", 2450 | "is-fullwidth-code-point": "^3.0.0" 2451 | }, 2452 | "dependencies": { 2453 | "ansi-styles": { 2454 | "version": "4.3.0", 2455 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2456 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2457 | "dev": true, 2458 | "requires": { 2459 | "color-convert": "^2.0.1" 2460 | } 2461 | }, 2462 | "color-convert": { 2463 | "version": "2.0.1", 2464 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2465 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2466 | "dev": true, 2467 | "requires": { 2468 | "color-name": "~1.1.4" 2469 | } 2470 | }, 2471 | "color-name": { 2472 | "version": "1.1.4", 2473 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2474 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2475 | "dev": true 2476 | }, 2477 | "is-fullwidth-code-point": { 2478 | "version": "3.0.0", 2479 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2480 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2481 | "dev": true 2482 | } 2483 | } 2484 | }, 2485 | "spawn-wrap": { 2486 | "version": "2.0.0", 2487 | "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", 2488 | "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", 2489 | "dev": true, 2490 | "requires": { 2491 | "foreground-child": "^2.0.0", 2492 | "is-windows": "^1.0.2", 2493 | "make-dir": "^3.0.0", 2494 | "rimraf": "^3.0.0", 2495 | "signal-exit": "^3.0.2", 2496 | "which": "^2.0.1" 2497 | }, 2498 | "dependencies": { 2499 | "which": { 2500 | "version": "2.0.2", 2501 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2502 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2503 | "dev": true, 2504 | "requires": { 2505 | "isexe": "^2.0.0" 2506 | } 2507 | } 2508 | } 2509 | }, 2510 | "sprintf-js": { 2511 | "version": "1.0.3", 2512 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2513 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2514 | "dev": true 2515 | }, 2516 | "string-width": { 2517 | "version": "2.1.1", 2518 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 2519 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 2520 | "dev": true, 2521 | "requires": { 2522 | "is-fullwidth-code-point": "^2.0.0", 2523 | "strip-ansi": "^4.0.0" 2524 | } 2525 | }, 2526 | "strip-ansi": { 2527 | "version": "4.0.0", 2528 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2529 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2530 | "dev": true, 2531 | "requires": { 2532 | "ansi-regex": "^3.0.0" 2533 | } 2534 | }, 2535 | "strip-bom": { 2536 | "version": "4.0.0", 2537 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", 2538 | "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", 2539 | "dev": true 2540 | }, 2541 | "strip-json-comments": { 2542 | "version": "3.1.0", 2543 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", 2544 | "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", 2545 | "dev": true 2546 | }, 2547 | "supports-color": { 2548 | "version": "8.1.1", 2549 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 2550 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 2551 | "dev": true, 2552 | "requires": { 2553 | "has-flag": "^4.0.0" 2554 | } 2555 | }, 2556 | "table": { 2557 | "version": "6.7.1", 2558 | "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", 2559 | "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", 2560 | "dev": true, 2561 | "requires": { 2562 | "ajv": "^8.0.1", 2563 | "lodash.clonedeep": "^4.5.0", 2564 | "lodash.truncate": "^4.4.2", 2565 | "slice-ansi": "^4.0.0", 2566 | "string-width": "^4.2.0", 2567 | "strip-ansi": "^6.0.0" 2568 | }, 2569 | "dependencies": { 2570 | "ajv": { 2571 | "version": "8.6.2", 2572 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", 2573 | "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", 2574 | "dev": true, 2575 | "requires": { 2576 | "fast-deep-equal": "^3.1.1", 2577 | "json-schema-traverse": "^1.0.0", 2578 | "require-from-string": "^2.0.2", 2579 | "uri-js": "^4.2.2" 2580 | } 2581 | }, 2582 | "ansi-regex": { 2583 | "version": "5.0.0", 2584 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2585 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2586 | "dev": true 2587 | }, 2588 | "is-fullwidth-code-point": { 2589 | "version": "3.0.0", 2590 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2591 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2592 | "dev": true 2593 | }, 2594 | "json-schema-traverse": { 2595 | "version": "1.0.0", 2596 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 2597 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 2598 | "dev": true 2599 | }, 2600 | "string-width": { 2601 | "version": "4.2.2", 2602 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2603 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2604 | "dev": true, 2605 | "requires": { 2606 | "emoji-regex": "^8.0.0", 2607 | "is-fullwidth-code-point": "^3.0.0", 2608 | "strip-ansi": "^6.0.0" 2609 | } 2610 | }, 2611 | "strip-ansi": { 2612 | "version": "6.0.0", 2613 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2614 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2615 | "dev": true, 2616 | "requires": { 2617 | "ansi-regex": "^5.0.0" 2618 | } 2619 | } 2620 | } 2621 | }, 2622 | "taffydb": { 2623 | "version": "2.6.2", 2624 | "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", 2625 | "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", 2626 | "dev": true 2627 | }, 2628 | "test-exclude": { 2629 | "version": "6.0.0", 2630 | "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", 2631 | "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", 2632 | "dev": true, 2633 | "requires": { 2634 | "@istanbuljs/schema": "^0.1.2", 2635 | "glob": "^7.1.4", 2636 | "minimatch": "^3.0.4" 2637 | }, 2638 | "dependencies": { 2639 | "glob": { 2640 | "version": "7.1.6", 2641 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 2642 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 2643 | "dev": true, 2644 | "requires": { 2645 | "fs.realpath": "^1.0.0", 2646 | "inflight": "^1.0.4", 2647 | "inherits": "2", 2648 | "minimatch": "^3.0.4", 2649 | "once": "^1.3.0", 2650 | "path-is-absolute": "^1.0.0" 2651 | } 2652 | } 2653 | } 2654 | }, 2655 | "text-table": { 2656 | "version": "0.2.0", 2657 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2658 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2659 | "dev": true 2660 | }, 2661 | "to-fast-properties": { 2662 | "version": "2.0.0", 2663 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2664 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 2665 | "dev": true 2666 | }, 2667 | "to-regex-range": { 2668 | "version": "5.0.1", 2669 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2670 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2671 | "dev": true, 2672 | "requires": { 2673 | "is-number": "^7.0.0" 2674 | } 2675 | }, 2676 | "type-check": { 2677 | "version": "0.4.0", 2678 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2679 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2680 | "dev": true, 2681 | "requires": { 2682 | "prelude-ls": "^1.2.1" 2683 | } 2684 | }, 2685 | "type-detect": { 2686 | "version": "4.0.8", 2687 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 2688 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 2689 | "dev": true 2690 | }, 2691 | "type-fest": { 2692 | "version": "0.8.1", 2693 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 2694 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 2695 | "dev": true 2696 | }, 2697 | "typedarray-to-buffer": { 2698 | "version": "3.1.5", 2699 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 2700 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 2701 | "dev": true, 2702 | "requires": { 2703 | "is-typedarray": "^1.0.0" 2704 | } 2705 | }, 2706 | "uc.micro": { 2707 | "version": "1.0.6", 2708 | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", 2709 | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", 2710 | "dev": true 2711 | }, 2712 | "underscore": { 2713 | "version": "1.13.1", 2714 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", 2715 | "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", 2716 | "dev": true 2717 | }, 2718 | "uri-js": { 2719 | "version": "4.4.1", 2720 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2721 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2722 | "dev": true, 2723 | "requires": { 2724 | "punycode": "^2.1.0" 2725 | } 2726 | }, 2727 | "uuid": { 2728 | "version": "3.4.0", 2729 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 2730 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 2731 | "dev": true 2732 | }, 2733 | "v8-compile-cache": { 2734 | "version": "2.3.0", 2735 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2736 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2737 | "dev": true 2738 | }, 2739 | "which": { 2740 | "version": "2.0.2", 2741 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2742 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2743 | "dev": true, 2744 | "requires": { 2745 | "isexe": "^2.0.0" 2746 | } 2747 | }, 2748 | "which-module": { 2749 | "version": "2.0.0", 2750 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2751 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2752 | "dev": true 2753 | }, 2754 | "wide-align": { 2755 | "version": "1.1.3", 2756 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 2757 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 2758 | "dev": true, 2759 | "requires": { 2760 | "string-width": "^1.0.2 || 2" 2761 | } 2762 | }, 2763 | "word-wrap": { 2764 | "version": "1.2.3", 2765 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2766 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2767 | "dev": true 2768 | }, 2769 | "workerpool": { 2770 | "version": "6.1.5", 2771 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", 2772 | "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", 2773 | "dev": true 2774 | }, 2775 | "wrap-ansi": { 2776 | "version": "7.0.0", 2777 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2778 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2779 | "dev": true, 2780 | "requires": { 2781 | "ansi-styles": "^4.0.0", 2782 | "string-width": "^4.1.0", 2783 | "strip-ansi": "^6.0.0" 2784 | }, 2785 | "dependencies": { 2786 | "ansi-regex": { 2787 | "version": "5.0.0", 2788 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2789 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2790 | "dev": true 2791 | }, 2792 | "ansi-styles": { 2793 | "version": "4.3.0", 2794 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2795 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2796 | "dev": true, 2797 | "requires": { 2798 | "color-convert": "^2.0.1" 2799 | } 2800 | }, 2801 | "color-convert": { 2802 | "version": "2.0.1", 2803 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2804 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2805 | "dev": true, 2806 | "requires": { 2807 | "color-name": "~1.1.4" 2808 | } 2809 | }, 2810 | "color-name": { 2811 | "version": "1.1.4", 2812 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2813 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2814 | "dev": true 2815 | }, 2816 | "is-fullwidth-code-point": { 2817 | "version": "3.0.0", 2818 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2819 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2820 | "dev": true 2821 | }, 2822 | "string-width": { 2823 | "version": "4.2.2", 2824 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2825 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2826 | "dev": true, 2827 | "requires": { 2828 | "emoji-regex": "^8.0.0", 2829 | "is-fullwidth-code-point": "^3.0.0", 2830 | "strip-ansi": "^6.0.0" 2831 | } 2832 | }, 2833 | "strip-ansi": { 2834 | "version": "6.0.0", 2835 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2836 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2837 | "dev": true, 2838 | "requires": { 2839 | "ansi-regex": "^5.0.0" 2840 | } 2841 | } 2842 | } 2843 | }, 2844 | "wrappy": { 2845 | "version": "1.0.2", 2846 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2847 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2848 | "dev": true 2849 | }, 2850 | "write-file-atomic": { 2851 | "version": "3.0.3", 2852 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2853 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2854 | "dev": true, 2855 | "requires": { 2856 | "imurmurhash": "^0.1.4", 2857 | "is-typedarray": "^1.0.0", 2858 | "signal-exit": "^3.0.2", 2859 | "typedarray-to-buffer": "^3.1.5" 2860 | } 2861 | }, 2862 | "xmlcreate": { 2863 | "version": "2.0.3", 2864 | "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", 2865 | "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", 2866 | "dev": true 2867 | }, 2868 | "y18n": { 2869 | "version": "5.0.8", 2870 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2871 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 2872 | "dev": true 2873 | }, 2874 | "yallist": { 2875 | "version": "4.0.0", 2876 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2877 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2878 | "dev": true 2879 | }, 2880 | "yargs": { 2881 | "version": "16.2.0", 2882 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 2883 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 2884 | "dev": true, 2885 | "requires": { 2886 | "cliui": "^7.0.2", 2887 | "escalade": "^3.1.1", 2888 | "get-caller-file": "^2.0.5", 2889 | "require-directory": "^2.1.1", 2890 | "string-width": "^4.2.0", 2891 | "y18n": "^5.0.5", 2892 | "yargs-parser": "^20.2.2" 2893 | }, 2894 | "dependencies": { 2895 | "ansi-regex": { 2896 | "version": "5.0.0", 2897 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2898 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2899 | "dev": true 2900 | }, 2901 | "is-fullwidth-code-point": { 2902 | "version": "3.0.0", 2903 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2904 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2905 | "dev": true 2906 | }, 2907 | "string-width": { 2908 | "version": "4.2.2", 2909 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2910 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2911 | "dev": true, 2912 | "requires": { 2913 | "emoji-regex": "^8.0.0", 2914 | "is-fullwidth-code-point": "^3.0.0", 2915 | "strip-ansi": "^6.0.0" 2916 | } 2917 | }, 2918 | "strip-ansi": { 2919 | "version": "6.0.0", 2920 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2921 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2922 | "dev": true, 2923 | "requires": { 2924 | "ansi-regex": "^5.0.0" 2925 | } 2926 | } 2927 | } 2928 | }, 2929 | "yargs-parser": { 2930 | "version": "20.2.4", 2931 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 2932 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 2933 | "dev": true 2934 | }, 2935 | "yargs-unparser": { 2936 | "version": "2.0.0", 2937 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 2938 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 2939 | "dev": true, 2940 | "requires": { 2941 | "camelcase": "^6.0.0", 2942 | "decamelize": "^4.0.0", 2943 | "flat": "^5.0.2", 2944 | "is-plain-obj": "^2.1.0" 2945 | }, 2946 | "dependencies": { 2947 | "camelcase": { 2948 | "version": "6.2.0", 2949 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 2950 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 2951 | "dev": true 2952 | }, 2953 | "decamelize": { 2954 | "version": "4.0.0", 2955 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 2956 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 2957 | "dev": true 2958 | } 2959 | } 2960 | }, 2961 | "yocto-queue": { 2962 | "version": "0.1.0", 2963 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2964 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2965 | "dev": true 2966 | } 2967 | } 2968 | } 2969 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mt940js", 3 | "version": "1.3.5", 4 | "description": "javascript mt940 bank statement parser", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha", 8 | "testw": "mocha --watch", 9 | "testcov": "nyc mocha", 10 | "lint": "eslint lib test cli.js index.js", 11 | "doc": "jsdoc -c jsdoc.json", 12 | "report-coverage": "nyc report --reporter=text-lcov > coverage.lcov", 13 | "coverage": "nyc --reporter=html --reporter=text mocha" 14 | }, 15 | "keywords": [ 16 | "mt940", 17 | "swift", 18 | "bank", 19 | "statement", 20 | "parser" 21 | ], 22 | "author": "Alexander Tsybulsky", 23 | "license": "Apache-2.0", 24 | "homepage": "https://github.com/a-fas/mt940js.git", 25 | "repository": "https://github.com/a-fas/mt940js.git", 26 | "devDependencies": { 27 | "chai": "^4.2.0", 28 | "eslint": "^7.3.0", 29 | "jsdoc": "^3.6.4", 30 | "mocha": "^9.0.3", 31 | "nyc": "^15.1.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/helpers.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | const helpers = require('../lib/helperModels'); 3 | 4 | describe('Helpers', () => { 5 | describe('Bank date parser', () => { 6 | it('should work at all (with full date)', () => { 7 | assert.equal('2016-12-01', helpers.Date.parse(2016,12,1).toISOString().substr(0, 10)); 8 | assert.equal('1996-12-01', helpers.Date.parse(1996,12,1).toISOString().substr(0, 10)); 9 | }); 10 | 11 | it('should work with YY (2-digit) year', () => { 12 | assert.equal('2016-12-01', helpers.Date.parse(16,12,1).toISOString().substr(0, 10)); 13 | }); 14 | }); 15 | 16 | describe('Bank amount', () => { 17 | describe('Parse', () => { 18 | it('should parse debit amount -> negative', () => { 19 | assert.equal(helpers.Amount.parse('D', '123.34'), -123.34); 20 | }); 21 | 22 | it('should parse credit amount -> positive', () => { 23 | assert.equal(helpers.Amount.parse('C', '123.34'), 123.34); 24 | }); 25 | 26 | it('should parse debit amount reversal -> positive', () => { 27 | assert.equal(helpers.Amount.parse('RD', '123.34'), 123.34); 28 | }); 29 | 30 | it('should parse credit amount reversal -> negative', () => { 31 | assert.equal(helpers.Amount.parse('RC', '123.34'), -123.34); 32 | }); 33 | 34 | it('should parse amount with ,', () => { 35 | assert.equal(helpers.Amount.parse('C', '123,34'), 123.34); 36 | }); 37 | 38 | it('should round to 2 fractional digits', () => { 39 | assert.equal(helpers.Amount.parse('C', '123,345'), 123.35); 40 | }); 41 | 42 | it('should fail if wrong indicator passed', () => { 43 | assert.throws(helpers.Amount.parse.bind(null, 'X', '123,34'), /Wrong debit/); 44 | }); 45 | 46 | it('should fail if wrong indicator passed / reversal', () => { 47 | assert.throws(helpers.Amount.parse.bind(null, 'XZ', '123,34'), /Wrong reversal/); 48 | }); 49 | 50 | it('should fail if wrong indicator passed / reversal 2', () => { 51 | assert.throws(helpers.Amount.parse.bind(null, 'RZ', '123,34'), /Wrong debit/); 52 | }); 53 | 54 | it('should fail if wrong amount passed', () => { 55 | assert.throws(helpers.Amount.parse.bind(null, 'D', 'XXXXXX'), /Amount cannot be parsed/); 56 | }); 57 | 58 | it('should fail for negative amount string', () => { 59 | assert.throws(helpers.Amount.parse.bind(null, 'D', '-123.78'), /Positive amount/); 60 | }); 61 | }); 62 | 63 | describe('isEqual', () => { 64 | it('Basic checks', () => { 65 | assert.isTrue(helpers.Amount.isEqual(123.23, 123.2301)); 66 | assert.isFalse(helpers.Amount.isEqual(123.23, 123.235)); 67 | }); 68 | }); 69 | }); 70 | 71 | 72 | }); 73 | -------------------------------------------------------------------------------- /test/message-blocks.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | const tags = require('../lib/tags'); 3 | const tf = new tags.TagFactory(); 4 | 5 | describe('Message blocks', () => { 6 | describe('high level parsing', () => { 7 | it('should detect starting message', () => { 8 | const text = '{1:F01NDEASESSAXXX0833510237}{2:O9400325050701NDEANOKKBXXX12706189060507010325N}{3:108:34}{4:'; 9 | const tag = tf.createTag('MB', null, text); 10 | assert.deepEqual(tag.fields, { 11 | '1': 'F01NDEASESSAXXX0833510237', 12 | '2': 'O9400325050701NDEANOKKBXXX12706189060507010325N', 13 | '3': '108:34', 14 | '4': '', 15 | }); 16 | }); 17 | it('should skip empty ending message', () => { 18 | const text = '-}'; 19 | const tag = tf.createTag('MB', null, text); 20 | // console.log(tag.fields); 21 | assert.deepEqual(tag.fields, { 22 | 'EOB': '', 23 | }); 24 | }); 25 | it('should detect ending message', () => { 26 | const text = '-}{5:{MAC:12345678}{CHK:123456789ABC}}'; 27 | const tag = tf.createTag('MB', null, text); 28 | assert.deepEqual(tag.fields, { 29 | 'EOB': '', 30 | '5': '{MAC:12345678}{CHK:123456789ABC}', 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/parser.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | const Parser = require('../lib/parser'); 3 | const Tags = require('../lib/tags'); 4 | const helpers = require('../lib/helperModels'); 5 | 6 | const DUMMY_STATEMENT_LINES = [ 7 | ':20:B4E08MS9D00A0009', 8 | ':21:X', 9 | ':25:123456789', 10 | ':28C:123/1', 11 | ':60F:C140507EUR0,00', 12 | ':61:1405070507C500,00NTRFNONREF//AUXREF', 13 | ':86:LINE1', 14 | 'LINE2', 15 | ':62F:C140508EUR500,00', 16 | ]; 17 | 18 | const DUMMY_STATEMENT_LINES_WITH_STRUCTURE = [ 19 | ':20:B4E08MS9D00A0009', 20 | ':21:X', 21 | ':25:123456789', 22 | ':28C:123/1', 23 | ':60F:C140507EUR0,00', 24 | ':61:1405070507C500,00NTRFNONREF//AUXREF', 25 | ':86:?20some?21data', 26 | ':62F:C140508EUR500,00', 27 | ]; 28 | 29 | const DUMMY_STATEMENT_LINES_61_64_65 = [ 30 | ':20:B4E08MS9D00A0009', 31 | ':21:X', 32 | ':25:123456789', 33 | ':28C:123/1', 34 | ':60F:C140507EUR0,00', 35 | ':61:1405070507C500,00NTRFNONREF//AUXREF', 36 | 'SUPPLEMENTARY61', 37 | ':86:LINE1', 38 | 'LINE2', 39 | ':62F:C140508EUR500,00', 40 | ':64:C140509EUR600,00', 41 | ':65:C140510EUR700,00', 42 | ':86:statement', 43 | 'comment', 44 | ]; 45 | 46 | const DUMMY_STATEMENT_W_MESSAGE_BLOCKS = [ 47 | '{1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4:', 48 | ':20:B4E08MS9D00A0009', 49 | ':21:X', 50 | ':25:123456789', 51 | ':28C:123/1', 52 | ':60F:C140507EUR0,00', 53 | ':61:1405070507C500,00NTRFNONREF//AUXREF', 54 | ':86:LINE1', 55 | 'LINE2', 56 | ':62F:C140508EUR500,00', 57 | '-}', 58 | '{1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4:', 59 | ':20:B4E08MS9D00A0009', 60 | ':21:X', 61 | ':25:123456789', 62 | ':28C:123/2', 63 | ':60F:C140508EUR500,00', 64 | ':62F:C140508EUR500,00', 65 | '-}{5:{CAC:VALIDATION SUCCESS}}' 66 | ]; 67 | 68 | function expectedStatement() { 69 | return { 70 | transactionReference: 'B4E08MS9D00A0009', 71 | relatedReference: 'X', 72 | accountIdentification: '123456789', 73 | number: { 74 | statement: '123', 75 | sequence: '1', 76 | section: '' 77 | }, 78 | statementDate: helpers.Date.parse('14', '05', '08'), 79 | openingBalanceDate: helpers.Date.parse('14', '05', '07'), 80 | closingBalanceDate: helpers.Date.parse('14', '05', '08'), 81 | currency: 'EUR', 82 | openingBalance: 0.0, 83 | closingBalance: 500.0, 84 | closingAvailableBalanceDate: helpers.Date.parse('14', '05', '08'), 85 | forwardAvailableBalanceDate: helpers.Date.parse('14', '05', '08'), 86 | closingAvailableBalance: 500.0, 87 | forwardAvailableBalance: 500.0, 88 | transactions: [ 89 | { 90 | amount: 500.00, 91 | isReversal: false, 92 | currency: 'EUR', 93 | reference: 'NONREF', 94 | bankReference: 'AUXREF', 95 | transactionType: 'NTRF', 96 | date: helpers.Date.parse('14', '05', '07'), 97 | entryDate: helpers.Date.parse('14', '05', '07'), 98 | details: 'LINE1\nLINE2', 99 | extraDetails: '', 100 | fundsCode: '', 101 | } 102 | ]}; 103 | } 104 | 105 | const DUMMY_GROUP_SIMPLE = [ 106 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 107 | new Tags.TagAccountIdentification('123456789'), 108 | new Tags.TagStatementNumber('123/1'), 109 | new Tags.TagOpeningBalance('C140507EUR0,00'), 110 | new Tags.TagStatementLine('1405070507C500,00NTRFNONREF//AUXREF'), 111 | new Tags.TagTransactionDetails('DETAILS'), 112 | new Tags.TagClosingBalance('C140508EUR500,00') 113 | ]; 114 | const DUMMY_GROUP_STRUCTURED = [ 115 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 116 | new Tags.TagAccountIdentification('123456789'), 117 | new Tags.TagStatementNumber('123/1'), 118 | new Tags.TagOpeningBalance('C140507EUR0,00'), 119 | new Tags.TagStatementLine('1405070507C500,00NTRFNONREF//AUXREF'), 120 | new Tags.TagTransactionDetails('?20Hello?30World'), 121 | new Tags.TagClosingBalance('C140508EUR500,00') 122 | ]; 123 | const DUMMY_GROUP_COMPLEX = [ // 2 detail lines and 2 transactions 124 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 125 | new Tags.TagRelatedReference('X'), 126 | new Tags.TagAccountIdentification('123456789'), 127 | new Tags.TagStatementNumber('123/1'), 128 | new Tags.TagOpeningBalance('C140507EUR0,00'), 129 | new Tags.TagStatementLine('1405070507C500,00NTRFNONREF//AUXREF'), 130 | new Tags.TagTransactionDetails('LINE1\nLINE2'), 131 | new Tags.TagStatementLine('1405070507C0,00NTRFNONREF2'), 132 | new Tags.TagTransactionDetails('LINE1'), 133 | new Tags.TagClosingBalance('C140508EUR500,00') 134 | ]; 135 | 136 | /////////////////////////////////////////////////////////////////////////////// 137 | // TESTS 138 | /////////////////////////////////////////////////////////////////////////////// 139 | 140 | describe('Parser', () => { 141 | describe('Parser methods', () => { 142 | 143 | it('_splitAndNormalize', () => { 144 | const parser = new Parser(); 145 | const result = parser._splitAndNormalize('abc \r\n\r\n-'); 146 | assert.deepEqual(result, ['abc ']); 147 | }); 148 | 149 | it('_parseLines', () => { 150 | const parser = new Parser(); 151 | const result = [...parser._parseLines(DUMMY_STATEMENT_LINES)]; 152 | assert.equal(8, result.length); 153 | assert.deepEqual(result[0], {id: '20', subId: '', data: ['B4E08MS9D00A0009']}); 154 | assert.deepEqual(result[1], {id: '21', subId: '', data: ['X']}); 155 | assert.deepEqual(result[2], {id: '25', subId: '', data: ['123456789']}); 156 | assert.deepEqual(result[3], {id: '28', subId: 'C', data: ['123/1']}); 157 | assert.deepEqual(result[4], {id: '60', subId: 'F', data: ['C140507EUR0,00']}); 158 | assert.deepEqual(result[5], {id: '61', subId: '', data: ['1405070507C500,00NTRFNONREF//AUXREF']}); 159 | assert.deepEqual(result[6], {id: '86', subId: '', data: ['LINE1', 'LINE2']}); 160 | assert.deepEqual(result[7], {id: '62', subId: 'F', data: ['C140508EUR500,00']}); 161 | }); 162 | 163 | it('_groupTags', () => { 164 | const parser = new Parser(); 165 | const groups = [DUMMY_GROUP_SIMPLE, DUMMY_GROUP_COMPLEX]; 166 | const result = parser._groupTags([...DUMMY_GROUP_SIMPLE, ...DUMMY_GROUP_COMPLEX]); 167 | assert.deepEqual(result, groups); 168 | }); 169 | 170 | it('_buildStatement', () => { 171 | const parser = new Parser(); 172 | const group = DUMMY_GROUP_COMPLEX; 173 | let result = parser._buildStatement(group); 174 | 175 | let exp = expectedStatement(); 176 | exp.transactions.push({ // patch 177 | amount: 0.00, 178 | currency: 'EUR', 179 | isReversal: false, 180 | reference: 'NONREF2', 181 | bankReference: '', 182 | transactionType: 'NTRF', 183 | date: helpers.Date.parse('14', '05', '07'), 184 | entryDate: helpers.Date.parse('14', '05', '07'), 185 | details: 'LINE1', 186 | extraDetails: '', 187 | fundsCode: '', 188 | }); 189 | assert.deepEqual(result, exp); 190 | assert.isUndefined(result.tags); 191 | assert.isUndefined(result.structuredDetails); 192 | 193 | // with Tags 194 | result = parser._buildStatement(group, true); 195 | assert.deepEqual(result.tags, group); 196 | }); 197 | 198 | it('_buildStatement structured', () => { 199 | const parser = new Parser(); 200 | const result = parser._buildStatement(DUMMY_GROUP_STRUCTURED); 201 | assert.deepEqual(result.transactions[0].structuredDetails, { 202 | '20': 'Hello', 203 | '30': 'World', 204 | }); 205 | }); 206 | 207 | it('_validateGroup throws', () => { 208 | const parser = new Parser(); 209 | assert.throws(parser._validateGroup.bind(parser, [ // missing tags 210 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 211 | ]), /Mandatory tag/); 212 | assert.throws(parser._validateGroup.bind(parser, [ // missing tags 213 | new Tags.TagClosingBalance('C140508EUR500,00') 214 | ]), /Mandatory tag/); 215 | assert.throws(parser._validateGroup.bind(parser, [ // missing tags 216 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 217 | new Tags.TagOpeningBalance('C140507EUR0,00'), 218 | new Tags.TagClosingBalance('C140508EUR500,00') 219 | ]), /Mandatory tag/); 220 | assert.throws(parser._validateGroup.bind(parser, [ // inconsistent currency 221 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 222 | new Tags.TagAccountIdentification('123456789'), 223 | new Tags.TagStatementNumber('123/1'), 224 | new Tags.TagOpeningBalance('C140507EUR0,00'), 225 | new Tags.TagStatementLine('1405070507C500,00NTRFNONREF//AUXREF'), 226 | new Tags.TagTransactionDetails('DETAILS'), 227 | new Tags.TagClosingBalance('C140508USD500,00') 228 | ]), /Currency markers/); 229 | assert.throws(parser._validateGroup.bind(parser, [ // inconsistent balances 230 | new Tags.TagTransactionReferenceNumber('B4E08MS9D00A0009'), 231 | new Tags.TagAccountIdentification('123456789'), 232 | new Tags.TagStatementNumber('123/1'), 233 | new Tags.TagOpeningBalance('C140507EUR0,00'), 234 | new Tags.TagStatementLine('1405070507C400,00NTRFNONREF//AUXREF'), 235 | new Tags.TagTransactionDetails('DETAILS'), 236 | new Tags.TagClosingBalance('C140508EUR500,00') 237 | ]), /Sum of lines/); 238 | }); 239 | }); 240 | 241 | /* MIDDLEWARES */ 242 | describe('Middlewares', () => { 243 | it('post parse wrong fn throws', () => { 244 | const parser = new Parser(); 245 | assert.throws(() => parser.usePostParse(1), /middleware must be a function/); 246 | }); 247 | it('post parse middleware', () => { 248 | const parser = new Parser(); 249 | parser.usePostParse((s, next) => { 250 | s.dummyMarker = true; 251 | next(); 252 | }); 253 | parser.usePostParse((s, next) => { 254 | if (s.dummyMarker) s.dummyMarker2 = true; 255 | next(); 256 | }); 257 | 258 | const result = parser.parse(DUMMY_STATEMENT_LINES.join('\n')); 259 | assert.isDefined(result); 260 | assert.isTrue(result[0].dummyMarker); 261 | assert.isTrue(result[0].dummyMarker2); 262 | }); 263 | }); 264 | 265 | /* INTEGRATION TEST */ 266 | describe('Integration test', () => { 267 | it('typical statement', () => { 268 | const parser = new Parser(); 269 | const result = parser.parse(DUMMY_STATEMENT_LINES.join('\n')); 270 | assert.equal(result.length, 1); 271 | assert.deepEqual(result[0], expectedStatement()); 272 | }); 273 | 274 | it('statement with structured 86', () => { 275 | let parser = new Parser(); 276 | let result = parser.parse(DUMMY_STATEMENT_LINES_WITH_STRUCTURE.join('\n')); 277 | assert.equal(result.length, 1); 278 | 279 | const exp = expectedStatement(); 280 | exp.transactions[0].details = '?20some?21data'; 281 | exp.transactions[0].structuredDetails = { 282 | '20': 'some', 283 | '21': 'data', 284 | }; 285 | assert.deepEqual(result[0], exp); 286 | 287 | parser = new Parser({ no86Structure: true }); 288 | result = parser.parse(DUMMY_STATEMENT_LINES_WITH_STRUCTURE.join('\n')); 289 | delete exp.transactions[0].structuredDetails; 290 | assert.deepEqual(result[0], exp); 291 | }); 292 | 293 | it('statement with fields 64, 65, long 61 and statement comment', () => { 294 | const parser = new Parser(); 295 | const exp = expectedStatement(); 296 | 297 | // patch data 298 | exp.closingAvailableBalanceDate = helpers.Date.parse('14', '05', '09'); 299 | exp.forwardAvailableBalanceDate = helpers.Date.parse('14', '05', '10'); 300 | exp.closingAvailableBalance = 600.0; 301 | exp.forwardAvailableBalance = 700.0; 302 | exp.transactions[0].extraDetails = 'SUPPLEMENTARY61'; 303 | exp.informationToAccountOwner = 'statement\ncomment'; 304 | 305 | const result = parser.parse(DUMMY_STATEMENT_LINES_61_64_65.join('\n')); 306 | assert.equal(result.length, 1); 307 | assert.deepEqual(result[0], exp); 308 | }); 309 | 310 | it('multiple statements with message blocks', () => { 311 | const parser = new Parser(); 312 | const exp1 = expectedStatement(); 313 | const exp2 = expectedStatement(); 314 | 315 | // patch data 316 | exp1.messageBlocks = { 317 | '1': { value: 'F01KNABNL2HAXXX0000000000' }, 318 | '2': { value: 'I940KNABNL2HXXXXN3020' }, 319 | }; 320 | exp2.messageBlocks = { 321 | '1': { value: 'F01KNABNL2HAXXX0000000000' }, 322 | '2': { value: 'I940KNABNL2HXXXXN3020' }, 323 | '5': { value: '{CAC:VALIDATION SUCCESS}' }, 324 | }; 325 | exp2.openingBalance = exp2.closingBalance; 326 | exp2.openingBalanceDate = exp2.closingBalanceDate; 327 | exp2.number.sequence = '2'; 328 | exp2.transactions = []; 329 | 330 | const result = parser.parse(DUMMY_STATEMENT_W_MESSAGE_BLOCKS.join('\n')); 331 | assert.equal(result.length, 2); 332 | assert.deepEqual(result[0], exp1); 333 | assert.deepEqual(result[1], exp2); 334 | }); 335 | }); 336 | 337 | /* NS TESTS */ 338 | describe('NS tests', () => { 339 | 340 | const DUMMY_STATEMENT_LINES_WITH_NS = [ 341 | ':20:B4E08MS9D00A0009', 342 | ':21:X', 343 | ':25:123456789', 344 | ':28C:123/1', 345 | ':60F:C140507EUR0,00', 346 | ':61:1405070507C100,00NTRFNONREF//AUXREF', 347 | ':86:LINE1', 348 | ':61:1405070507C200,00NTRFNONREF//AUXREF', 349 | ':NS:Hello world', 350 | ':86:LINE2', 351 | ':61:1405070507C300,00NTRFNONREF//AUXREF', 352 | ':86:LINE3', 353 | ':NS:Hello', 354 | 'bank info', 355 | ':62F:C140508EUR600,00', 356 | ]; 357 | 358 | it('_parseLines with NS', () => { 359 | const parser = new Parser(); 360 | const result = [...parser._parseLines(DUMMY_STATEMENT_LINES_WITH_NS)]; 361 | assert.deepEqual(result, [ 362 | {id: '20', subId: '', data: ['B4E08MS9D00A0009']}, 363 | {id: '21', subId: '', data: ['X']}, 364 | {id: '25', subId: '', data: ['123456789']}, 365 | {id: '28', subId: 'C', data: ['123/1']}, 366 | {id: '60', subId: 'F', data: ['C140507EUR0,00']}, 367 | {id: '61', subId: '', data: ['1405070507C100,00NTRFNONREF//AUXREF']}, 368 | {id: '86', subId: '', data: ['LINE1']}, 369 | {id: '61', subId: '', data: ['1405070507C200,00NTRFNONREF//AUXREF']}, 370 | {id: 'NS', subId: '', data: ['Hello world']}, 371 | {id: '86', subId: '', data: ['LINE2']}, 372 | {id: '61', subId: '', data: ['1405070507C300,00NTRFNONREF//AUXREF']}, 373 | {id: '86', subId: '', data: ['LINE3']}, 374 | {id: 'NS', subId: '', data: ['Hello', 'bank info']}, 375 | {id: '62', subId: 'F', data: ['C140508EUR600,00']}, 376 | ]); 377 | }); 378 | 379 | it('statement with NS', () => { 380 | const parser = new Parser(); 381 | const result = parser.parse(DUMMY_STATEMENT_LINES_WITH_NS.join('\n')); 382 | assert.equal(result.length, 1); 383 | assert.deepEqual(result[0], { 384 | transactionReference: 'B4E08MS9D00A0009', 385 | relatedReference: 'X', 386 | accountIdentification: '123456789', 387 | number: { 388 | statement: '123', 389 | sequence: '1', 390 | section: '' 391 | }, 392 | statementDate: helpers.Date.parse('14', '05', '08'), 393 | openingBalanceDate: helpers.Date.parse('14', '05', '07'), 394 | closingBalanceDate: helpers.Date.parse('14', '05', '08'), 395 | currency: 'EUR', 396 | openingBalance: 0.0, 397 | closingBalance: 600.0, 398 | closingAvailableBalanceDate: helpers.Date.parse('14', '05', '08'), 399 | forwardAvailableBalanceDate: helpers.Date.parse('14', '05', '08'), 400 | closingAvailableBalance: 600.0, 401 | forwardAvailableBalance: 600.0, 402 | transactions: [ 403 | { 404 | amount: 100.00, 405 | isReversal: false, 406 | currency: 'EUR', 407 | reference: 'NONREF', 408 | bankReference: 'AUXREF', 409 | transactionType: 'NTRF', 410 | date: helpers.Date.parse('14', '05', '07'), 411 | entryDate: helpers.Date.parse('14', '05', '07'), 412 | details: 'LINE1', 413 | extraDetails: '', 414 | fundsCode: '', 415 | }, 416 | { 417 | amount: 200.00, 418 | isReversal: false, 419 | currency: 'EUR', 420 | reference: 'NONREF', 421 | bankReference: 'AUXREF', 422 | transactionType: 'NTRF', 423 | date: helpers.Date.parse('14', '05', '07'), 424 | entryDate: helpers.Date.parse('14', '05', '07'), 425 | details: 'LINE2', 426 | extraDetails: '', 427 | fundsCode: '', 428 | nonSwift: 'Hello world', 429 | }, 430 | { 431 | amount: 300.00, 432 | isReversal: false, 433 | currency: 'EUR', 434 | reference: 'NONREF', 435 | bankReference: 'AUXREF', 436 | transactionType: 'NTRF', 437 | date: helpers.Date.parse('14', '05', '07'), 438 | entryDate: helpers.Date.parse('14', '05', '07'), 439 | details: 'LINE3', 440 | extraDetails: '', 441 | fundsCode: '', 442 | nonSwift: 'Hello\nbank info', 443 | }, 444 | ]}); 445 | }); 446 | 447 | }); 448 | 449 | }); 450 | -------------------------------------------------------------------------------- /test/structured.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | const Field86Parser = require('../lib/field86structure'); 3 | 4 | function run(details) { 5 | return Field86Parser.parse(details); 6 | } 7 | 8 | describe('Field86Structure', () => { 9 | it('Detects no structure', () => { 10 | assert.isUndefined(run('some arbitrary text')); 11 | assert.isUndefined(run('>some arbitrary text')); 12 | assert.isUndefined(run('?some arbitrary text')); 13 | assert.isUndefined(run('so?20me arbitrary text')); 14 | assert.isUndefined(run('/some arbitrary text')); 15 | assert.isUndefined(run('/some/ arbitrary text')); // lower case 16 | assert.isUndefined(run('some /ATTR/ arbitrary text')); 17 | assert.isUndefined(run('')); // empty string 18 | }); 19 | 20 | it('Detects > structure', () => { 21 | assert.deepEqual(run('>20Details 123>30123232421>31'), { 22 | '20': 'Details 123', 23 | '30': '123232421', 24 | '31': '' 25 | }); 26 | assert.deepEqual(run('>20Details 123\n>30123232421>31'), { 27 | '20': 'Details 123', 28 | '30': '123232421', 29 | '31': '' 30 | }); 31 | }); 32 | 33 | it('Detects structure, with beginning spaces', () => { 34 | assert.deepEqual(run(' >20Details 123>30123232421>31'), { 35 | '20': 'Details 123', 36 | '30': '123232421', 37 | '31': '' 38 | }); 39 | }); 40 | 41 | it('Detects ? structure', () => { 42 | assert.deepEqual(run('?20Details 123?30123232421?31'), { 43 | '20': 'Details 123', 44 | '30': '123232421', 45 | '31': '' 46 | }); 47 | assert.deepEqual(run('?20Details? 123?30123232421?31'), { 48 | '20': 'Details? 123', 49 | '30': '123232421', 50 | '31': '' 51 | }); 52 | }); 53 | 54 | it('Detects /XXX/ structure', () => { 55 | assert.deepEqual(run('/ATR/Details 123/ATR2/123232421/ATR3/'), { 56 | 'ATR': 'Details 123', 57 | 'ATR2': '123232421', 58 | 'ATR3': '' 59 | }); 60 | }); 61 | 62 | it('complex detect', () => { 63 | const tag = [ 64 | ' /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL)', 65 | ' /ORDP/XX XXXXXX XXXXX XXXX N.A.25 XXXX XXXXX, CANARY WHARF', 66 | ' /REMI/UBERWEISUNG OUR REF: 03MT181024144353', 67 | 'YOUR REF: P6363103 240 1 M CA O/XXXXGB2L', 68 | '/ACC/INST/XXXXGB2L /6231400604', 69 | 'BIC:XXXXGB2L', 70 | ].join(''); 71 | 72 | const parsed = run(tag); 73 | 74 | assert.deepEqual(parsed, { 75 | 'XXXX': '/100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) ', 76 | 'ORDP': 'XX XXXXXX XXXXX XXXX N.A.25 XXXX XXXXX, CANARY WHARF ', 77 | 'REMI': 'UBERWEISUNG OUR REF: 03MT181024144353YOUR REF: P6363103 240 1 M CA O/XXXXGB2L', 78 | 'ACC': 'INST/XXXXGB2L /6231400604BIC:XXXXGB2L' 79 | }); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /test/tags.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | const tags = require('../lib/tags'); 3 | const tf = new tags.TagFactory(); 4 | 5 | describe('Tags', () => { 6 | describe('TagFactory', () => { 7 | 8 | it('should create tag 20 (TransactionReferenceNumber)', () => { 9 | const ref = 'REFERENCE'; 10 | const tag = tf.createTag('20', null, ref); 11 | assert.equal(tag.fields.transactionReference, ref); 12 | }); 13 | 14 | it('should create tag 21 (RelatedReference)', () => { 15 | const ref = 'REFERENCE'; 16 | const tag = tf.createTag('21', null, ref); 17 | assert.equal(tag.fields.relatedReference, ref); 18 | }); 19 | 20 | it('should create tag 25 (AccountIdentification)', () => { 21 | const account = '123456789'; 22 | const tag = tf.createTag('25', null, account); 23 | assert.equal(tag.fields.accountIdentification, account); 24 | }); 25 | 26 | it('should create tag 28 (StatementNumber)', () => { 27 | const str = '998/1'; 28 | const tag = tf.createTag('28', null, str); 29 | assert.equal(tag.fields.statementNumber, '998'); 30 | assert.equal(tag.fields.sequenceNumber,'1'); 31 | }); 32 | 33 | it('should create tag NS (NonSwift)', () => { 34 | const str = 'XYZ'; 35 | const tag = tf.createTag('NS', null, str); 36 | assert.equal(tag.fields.nonSwift, 'XYZ'); 37 | }); 38 | 39 | it('should create tag 60 (OpeningBalance)', () => { 40 | const str = 'C160507EUR123,89'; 41 | const tag = tf.createTag('60', null, str); 42 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 43 | assert.equal(tag.fields.currency,'EUR'); 44 | assert.equal(tag.fields.amount, 123.89); 45 | }); 46 | 47 | it('should create tag 62 (ClosingBalance)', () => { 48 | const str = 'C160507EUR123,89'; 49 | const tag = tf.createTag('62', null, str); 50 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 51 | assert.equal(tag.fields.currency, 'EUR'); 52 | assert.equal(tag.fields.amount, 123.89); 53 | }); 54 | 55 | it('should create tag 64 (ClosingAvailableBalance)', () => { 56 | const str = 'C160507EUR123,89'; 57 | const tag = tf.createTag('64', null, str); 58 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 59 | assert.equal(tag.fields.currency, 'EUR'); 60 | assert.equal(tag.fields.amount, 123.89); 61 | }); 62 | 63 | it('should create tag 65 (ForwardAvailableBalance)', () => { 64 | const str = 'C160507EUR123,89'; 65 | const tag = tf.createTag('65', null, str); 66 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 67 | assert.equal(tag.fields.currency, 'EUR'); 68 | assert.equal(tag.fields.amount, 123.89); 69 | }); 70 | 71 | it('should create tag 61 (StatementLine)', () => { 72 | const str = '1605070507D123,89NTRFNONREF//B4E07XM00J000023'; 73 | const tag = tf.createTag('61', null, str); 74 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 75 | assert.equal(tag.fields.entryDate.toISOString().substr(0,10), '2016-05-07'); 76 | assert.equal(tag.fields.amount, -123.89); 77 | assert.equal(tag.fields.transactionType, 'NTRF'); 78 | assert.equal(tag.fields.reference, 'NONREF'); 79 | assert.equal(tag.fields.bankReference, 'B4E07XM00J000023'); 80 | assert.equal(tag.fields.isReversal, false); 81 | }); 82 | 83 | it('should create tag 61 / reversal and funds code', () => { 84 | const str = '1605070507RDR123,89NTRFNONREF//B4E07XM00J000023'; 85 | const tag = tf.createTag('61', null, str); 86 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 87 | assert.equal(tag.fields.entryDate.toISOString().substr(0,10), '2016-05-07'); 88 | assert.equal(tag.fields.amount, 123.89); // Reversed 89 | assert.equal(tag.fields.transactionType, 'NTRF'); 90 | assert.equal(tag.fields.reference, 'NONREF'); 91 | assert.equal(tag.fields.bankReference, 'B4E07XM00J000023'); 92 | assert.equal(tag.fields.isReversal, true); 93 | assert.equal(tag.fields.fundsCode, 'R'); 94 | }); 95 | 96 | it('should create tag 61 (with extraDetails)', () => { 97 | const str = '1605070507D123,89NTRFNONREF//B4E07XM00J000023\nSUPPLEMENTARY_DETAILS'; 98 | const tag = tf.createTag('61', null, str); 99 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2016-05-07'); 100 | assert.equal(tag.fields.entryDate.toISOString().substr(0,10), '2016-05-07'); 101 | assert.equal(tag.fields.amount, -123.89); 102 | assert.equal(tag.fields.transactionType, 'NTRF'); 103 | assert.equal(tag.fields.reference, 'NONREF'); 104 | assert.equal(tag.fields.bankReference, 'B4E07XM00J000023'); 105 | assert.equal(tag.fields.isReversal, false); 106 | assert.equal(tag.fields.extraDetails, 'SUPPLEMENTARY_DETAILS'); 107 | }); 108 | 109 | it('should create tag 61 (with extraDetails, but no bankRef)', () => { 110 | const str = '170406D000000001001,69N541NONREF\nNL72RABO0104510633'; 111 | const tag = tf.createTag('61', null, str); 112 | assert.equal(tag.fields.date.toISOString().substr(0,10), '2017-04-06'); 113 | assert.equal(tag.fields.isReversal, false); 114 | assert.equal(tag.fields.amount, -1001.69); 115 | assert.equal(tag.fields.transactionType, 'N541'); 116 | assert.equal(tag.fields.reference, 'NONREF'); 117 | assert.equal(tag.fields.extraDetails, 'NL72RABO0104510633'); 118 | }); 119 | 120 | it('should create tag 86 (TransactionDetails)', () => { 121 | const str = 'Some text here'; 122 | const tag = tf.createTag('86', null, str); 123 | assert.equal(tag.fields.transactionDetails, 'Some text here'); 124 | }); 125 | 126 | it('should create tag with a subId', () => { 127 | const str = '998/1'; 128 | const tag = tf.createTag('28', 'C', str); 129 | assert.equal(tag.fields.statementNumber, '998'); 130 | assert.equal(tag.fields.sequenceNumber, '1'); 131 | }); 132 | 133 | it('should throw unknown tag', () => { 134 | const str = 'Some data'; 135 | assert.throws( 136 | tf.createTag.bind(tf, 'XX', null, str), 137 | /Unknown tag/); 138 | }); 139 | 140 | it('should throw wrong content', () => { 141 | const str = 'Some data'; 142 | assert.throws( 143 | tf.createTag.bind(tf, '28', null, str), 144 | /Cannot parse/); 145 | }); 146 | }); 147 | describe('Tags', () => { 148 | 149 | it('Tag and TagBalance are abstact', () => { 150 | assert.throws( 151 | () => new tags.Tag, 152 | /Tag instances/); 153 | assert.throws( 154 | () => new tags.TagBalance('C160507EUR123,89'), 155 | /TagBalance instances/); 156 | }); 157 | 158 | }); 159 | }); 160 | -------------------------------------------------------------------------------- /test/test-with-NS.mt940x: -------------------------------------------------------------------------------- 1 | :20:17013109020 2 | :25:B4E08MS9D00A0009 3 | :28C:17001/1 4 | :60F:C170101PLN3503,60 5 | 6 | :61:170103DN369,00FCHGNONREF 7 | :86:>20Usługi księgowe - m-c grudzien 2016 rok.>31491050195310000 8 | 0477656534>32BOOKING GROUP 9 | 10 | :61:170104DN15,07FCHGNONREF 11 | :86:>20VB ELECTR. PŁATNOŚĆ KARTĄ 3.32 EUR 1 EUR= 12 | 4.5385 PLN GOOGLE *SVCSAPPS@google.com>31>32 13 | 14 | :61:170110DN123,00FCHGNONREF 15 | :86:>20usługa biurowa 2017/01>315910902053000000 16 | 016768736>32OFFICE GROUP 17 | UL. SPOKOJNA 3 18 | 19 | :62M:C170124PLN2996,53 20 | 21 | :20:17013109020 22 | :25:B4E08MS9D00A0009 23 | :28C:17001/2 24 | :60M:C170124PLN2996,53 25 | 26 | :61:170131DN25,00FCHGNONREF 27 | 28 | :NS:01My Street 17 29 | 02City and Region 30 | 03Invoice Nr. 12345 31 | 32 | :86:>20Opłata za prowadzenie rachunku od 1-01-2017 do 31-01-2017 33 | >31>32 34 | 35 | :62F:C170131PLN2971,53 36 | -------------------------------------------------------------------------------- /test/test1.mt940: -------------------------------------------------------------------------------- 1 | {1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4: 2 | :20:B4E08MS9D00A0009 3 | :25:123456789 4 | :28C:998/1 5 | :60F:C140507EUR0, 6 | :61:1405070507C500,NTRFNONREF//B4E07XM00J000023 7 | :86:HIER EEN MOOIE OMSCHRIJVING IN HOOFDLETTERS 8 | WANT DAT IS ZOALS DE NEDERLANDSE BANKEN COMMUNICEREN 9 | :62F:C140508EUR500, 10 | -} 11 | {1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4: 12 | :20:B4G30MS9D00A003D 13 | :25:123456789 14 | :28C:999/1 15 | :60F:C140729EUR3058,98 16 | :61:1407290729D2760,NTRFNONREF//B4G29PGCVO7Q06US 17 | /OCMT/EUR10,00/ 18 | :86:FACTUUR 201403110, 201403113 19 | REK: NL65INGB0123456789/NAAM: PICQER 20 | :61:1407290729C500NTRF29-07-2014 10:05//B4G29PGDCK1QFV3E 21 | :86:12160475 0050001631430920 ORDERID: 264267 MEDIA MARKT ONLINE NE 22 | REK: NL84INGB0234561789/NAAM: MMS ONLINE NEDERLAND B.V. 23 | :62F:C140730EUR798,98 24 | -} 25 | -------------------------------------------------------------------------------- /test/test2.mt940x: -------------------------------------------------------------------------------- 1 | :20:17013109020 2 | :25:B4E08MS9D00A0009 3 | :28C:17001/1 4 | :60F:C170101PLN3503,60 5 | 6 | :61:170103DN369,00FCHGNONREF 7 | :86:>20Usługi księgowe - m-c grudzien 2016 rok.>31491050195310000 8 | 0477656534>32BOOKING GROUP 9 | 10 | :61:170104DN15,07FCHGNONREF 11 | :86:>20VB ELECTR. PŁATNOŚĆ KARTĄ 3.32 EUR 1 EUR= 12 | 4.5385 PLN GOOGLE *SVCSAPPS@google.com>31>32 13 | 14 | :61:170110DN123,00FCHGNONREF 15 | :86:>20usługa biurowa 2017/01>315910902053000000 16 | 016768736>32OFFICE GROUP 17 | UL. SPOKOJNA 3 18 | 19 | :62M:C170124PLN2996,53 20 | 21 | :20:17013109020 22 | :25:B4E08MS9D00A0009 23 | :28C:17001/2 24 | :60M:C170124PLN2996,53 25 | 26 | :61:170131DN25,00FCHGNONREF 27 | :86:>20Opłata za prowadzenie rachunku od 1-01-2017 do 31-01-2017 28 | >31>32 29 | 30 | :62F:C170131PLN2971,53 31 | -------------------------------------------------------------------------------- /test/testX.mt940: -------------------------------------------------------------------------------- 1 | {1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4: 2 | :20:B4E08MS9D00A0009 3 | :25:123456789 4 | :28C:998/1 5 | :60F:C140507EUR0, 6 | :61:1405070507C500,NTRFNONREF//B4E07XM00J000023 7 | :86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) 8 | /ORDP/XXXXXXXXXXXXX XXXXXXXX BANKEN AB (PUBL) (FORMER: SXB A 9 | /REMI/XXXXXXXXXXX OUR REF: 03MT181012182288 10 | YOUR REF: 181012671 M CA O/XXXXDK22 11 | BIC:XXXXDK22 12 | :62F:C140508EUR500, 13 | -}{5:{MAC:ABCDEFG}} 14 | {1:F01KNABNL2HAXXX0000000000}{2:I940KNABNL2HXXXXN3020}{4: 15 | :20:B4G30MS9D00A003D 16 | :25:123456789 17 | :28C:999/1 18 | :60F:C140729EUR3058,98 19 | :61:1407290729D2760,NTRFNONREF//B4G29PGCVO7Q06US 20 | /OCMT/EUR10,00/ 21 | :86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) 22 | /ORDP/XX XXXXXX XXXXX XXXX N.A.25 XXXX XXXXX, CANARY WHARF 23 | /REMI/UBERWEISUNG OUR REF: 03MT181024144353 24 | YOUR REF: P6363103 240 1 M CA O/XXXXGB2L 25 | /ACC/INST/XXXXGB2L /6231400604 26 | BIC:XXXXGB2L 27 | :61:1407290729C500NTRF29-07-2014 10:05//B4G29PGDCK1QFV3E 28 | :86:12160475 0050001631430920 ORDERID: 264267 MEDIA MARKT ONLINE NE 29 | REK: NL84INGB0234561789/NAAM: MMS ONLINE NEDERLAND B.V. 30 | :62F:C140730EUR798,98 31 | -}{5:{MAC:12345678}{CHK:123456789ABC}} 32 | --------------------------------------------------------------------------------