├── .eslintrc.js
├── .github
└── workflows
│ └── app.yaml
├── .gitignore
├── .prettierrc
├── README.md
├── SECURITY.md
├── documentation
├── classes
│ └── ParserCommandDTO.html
├── coverage.html
├── dependencies.html
├── fonts
│ ├── ionicons.eot
│ ├── ionicons.svg
│ ├── ionicons.ttf
│ ├── ionicons.woff
│ ├── ionicons.woff2
│ ├── roboto-v15-latin-300.eot
│ ├── roboto-v15-latin-300.svg
│ ├── roboto-v15-latin-300.ttf
│ ├── roboto-v15-latin-300.woff
│ ├── roboto-v15-latin-300.woff2
│ ├── roboto-v15-latin-700.eot
│ ├── roboto-v15-latin-700.svg
│ ├── roboto-v15-latin-700.ttf
│ ├── roboto-v15-latin-700.woff
│ ├── roboto-v15-latin-700.woff2
│ ├── roboto-v15-latin-italic.eot
│ ├── roboto-v15-latin-italic.svg
│ ├── roboto-v15-latin-italic.ttf
│ ├── roboto-v15-latin-italic.woff
│ ├── roboto-v15-latin-italic.woff2
│ ├── roboto-v15-latin-regular.eot
│ ├── roboto-v15-latin-regular.svg
│ ├── roboto-v15-latin-regular.ttf
│ ├── roboto-v15-latin-regular.woff
│ └── roboto-v15-latin-regular.woff2
├── graph
│ └── dependencies.svg
├── images
│ ├── compodoc-vectorise-inverted.png
│ ├── compodoc-vectorise-inverted.svg
│ ├── compodoc-vectorise.png
│ ├── compodoc-vectorise.svg
│ ├── coverage-badge-documentation.svg
│ └── favicon.ico
├── index.html
├── injectables
│ ├── FileHelper.html
│ ├── ParserCommand.html
│ └── ParserService.html
├── interfaces
│ └── LogModel.html
├── js
│ ├── compodoc.js
│ ├── lazy-load-graphs.js
│ ├── libs
│ │ ├── EventDispatcher.js
│ │ ├── bootstrap-native.js
│ │ ├── clipboard.min.js
│ │ ├── custom-elements-es5-adapter.js
│ │ ├── custom-elements.min.js
│ │ ├── d3.v3.min.js
│ │ ├── deep-iterator.js
│ │ ├── es6-shim.min.js
│ │ ├── htmlparser.js
│ │ ├── innersvg.js
│ │ ├── lit-html.js
│ │ ├── prism.js
│ │ ├── promise.min.js
│ │ ├── svg-pan-zoom.min.js
│ │ ├── tablesort.min.js
│ │ ├── tablesort.number.min.js
│ │ ├── vis.min.js
│ │ └── zepto.min.js
│ ├── menu-wc.js
│ ├── menu-wc_es5.js
│ ├── menu.js
│ ├── routes.js
│ ├── search
│ │ ├── lunr.min.js
│ │ ├── search-lunr.js
│ │ ├── search.js
│ │ └── search_index.js
│ ├── sourceCode.js
│ ├── svg-pan-zoom.controls.js
│ ├── tabs.js
│ └── tree.js
├── miscellaneous
│ ├── enumerations.html
│ ├── functions.html
│ └── variables.html
├── modules.html
├── modules
│ ├── AppModule.html
│ ├── AppModule
│ │ └── dependencies.svg
│ ├── ParserModule.html
│ └── ParserModule
│ │ └── dependencies.svg
├── overview.html
├── properties.html
└── styles
│ ├── bootstrap-card.css
│ ├── bootstrap.min.css
│ ├── compodoc.css
│ ├── dark.css
│ ├── ionicons.min.css
│ ├── laravel.css
│ ├── material.css
│ ├── original.css
│ ├── postmark.css
│ ├── prism.css
│ ├── readthedocs.css
│ ├── reset.css
│ ├── stripe.css
│ ├── style.css
│ ├── tablesort.css
│ └── vagrant.css
├── full-documentation.md
├── input.example.log
├── jest.config.js
├── nest-cli.json
├── package-lock.json
├── package.json
├── scripts
└── runner.sh
├── src
├── app
│ └── app.module.ts
├── cli.ts
└── parser
│ ├── command
│ └── parser.command.ts
│ ├── common
│ ├── index.ts
│ └── utils.ts
│ ├── dtos
│ └── parser-command-dto.ts
│ ├── enum
│ ├── index.ts
│ └── log-level.enum.ts
│ ├── helper
│ ├── file-helper.ts
│ └── index.ts
│ ├── model
│ ├── index.ts
│ └── log.model.ts
│ ├── parser.module.ts
│ └── service
│ ├── parser.service.ts
│ └── test.log
├── test
├── integration-tests
│ ├── factories
│ │ ├── index.ts
│ │ └── parser-command.factory.ts
│ ├── fixtures
│ │ └── fixture-input.log
│ └── parser-command.spec.ts
└── unit-tests
│ ├── factories
│ ├── helper.factory.ts
│ ├── index.ts
│ ├── parser.factory.ts
│ └── utils.factory.ts
│ ├── filehelper.spec.ts
│ ├── fixtures
│ └── fixture-input.log
│ ├── parser.service.spec.ts
│ └── utils.spec.ts
├── tsconfig.build.json
├── tsconfig.compodoc.json
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir : __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/.github/workflows/app.yaml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | strategy:
15 | matrix:
16 | node-version: [12.x, 14.x, 15.x]
17 |
18 | steps:
19 | - uses: actions/checkout@v3
20 | - name: Use Node.js ${{ matrix.node-version }}
21 | uses: actions/setup-node@v3
22 | with:
23 | node-version: ${{ matrix.node-version }}
24 | - run: npm ci
25 | - run: npm run build --if-present
26 | - run: npm test
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | npm-debug.log*
7 | pnpm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 | lerna-debug.log*
11 |
12 | # OS
13 | .DS_Store
14 |
15 | # Tests
16 | /coverage
17 | /.nyc_output
18 |
19 | # IDEs and editors
20 | /.idea
21 | .project
22 | .classpath
23 | .c9/
24 | *.launch
25 | .settings/
26 | *.sublime-workspace
27 |
28 | # IDE - VSCode
29 | .vscode/*
30 | !.vscode/settings.json
31 | !.vscode/tasks.json
32 | !.vscode/launch.json
33 | !.vscode/extensions.json
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | # Log parser
3 |
4 | # Table of Contents
5 |
6 | - [Table of Contents](#table-of-contents)
7 |
8 | - [Overview](#overview)
9 |
10 | - [Provided Commands](#provided-commands)
11 |
12 | - [Code architecture](#code-architecture)
13 |
14 | - [source code](#source-code)
15 |
16 | - [Service build information](#service-build-information)
17 |
18 | - [Regular user](#regular-user)
19 |
20 | - [Documentation](#documentation)
21 |
22 | - [Example](#example)
23 |
24 | - [ToDo list](#todo-list)
25 |
26 | ## Overview
27 |
28 | Log parser takes a log input file and tries to parse it to extract useful information. It also respects [General Data Protection Regulation (GDPR)](https://gdpr-info.eu/)
29 |
30 | You can see take a look at the Full documentation [here](https://github.com/MoeidHeidari/log-parser/blob/main/full-documentation.md)
31 |
32 |
33 | ---
34 |
35 | #### Provided Commands
36 |
37 | ```bash
38 | cli
39 |
40 | parses a log file
41 |
42 | Options:
43 | -h, --help Show help [boolean]
44 | -l, --log-level log-level (ex: "error,[error,debug,warn,info]")
45 | [string] [default: "error"]
46 | -o, --output output log file (ex: "output.log")
47 | [string] [required] [default: "output.log"]
48 | -i, --input input log file (ex: "input.log") [string] [required]
49 | -v, --version Show version number [boolean]
50 | ```
51 |
52 | ---
53 |
54 | ## Code architecture
55 |
56 |
57 | ```bash
58 | src
59 | ├── app
60 | └── parser
61 | ├── command
62 | ├── common
63 | ├── dtos
64 | ├── enum
65 | ├── helper
66 | ├── model
67 | └── service
68 | ```
69 |
70 | ---
71 |
72 | ## source code
73 |
74 | ```bash
75 | git clone https://github.com/MoeidHeidari/log-parser.git
76 | cd log-parser
77 | ```
78 |
79 | ## Service build information
80 |
81 | ### Regular user
82 |
83 | ```bash
84 | npm install
85 | npm run build
86 | npm run test
87 | npm run lint
88 | npm start:{dev || debug || prod}
89 | ```
90 |
91 | ### using runner.sh
92 |
93 | ```bash
94 | bash scripts/runner.sh
95 | ...
96 | Done! 😍
97 | now you can use the application by following commmand
98 | node dist/cli.js -h
99 | ```
100 |
101 | test result
102 |
103 | ```bash
104 | PASS test/unit-tests/utils.spec.ts
105 | PASS test/unit-tests/filehelper.spec.ts
106 | PASS test/unit-tests/parser.service.spec.ts (5.093 s)
107 | PASS test/integration-tests/parser-command.spec.ts (5.418 s)
108 | Test Suites: 4 passed, 4 total
109 | Tests: 33 passed, 33 total
110 | Snapshots: 0 total
111 | Time: 5.732 s, estimated 6 s
112 | Ran all test suites.
113 | ```
114 |
115 | ## Documentation
116 |
117 | By running following comman you can generate the full code documentation (Compodoc) and get access to it through port `7000`
118 |
119 | ```bash
120 | npm run doc
121 | ```
122 |
123 | http://localhost:7000
124 |
125 | ## Example
126 |
127 | input.log
128 |
129 | ```textile
130 | 2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}
131 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
132 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}
133 | 2021-08-09T02:12:51.255Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is started"}
134 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request the user information","userId": 16}
135 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"User information is gathered","user":{"id":10,"name":"Alice"}}
136 | 2021-08-09T02:12:51.258Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request user orders list","userId":16}
137 | 2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}
138 | 2021-08-09T02:12:51.259Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user": {"id": 16, "name": "Michael"}}
139 | 2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}
140 | 2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}
141 | 2021-08-09T02:12:51.265Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is successfully finished"}
142 | ```
143 |
144 | Run Log parser
145 |
146 | ```bash
147 | npm run build
148 | ode dist/cli.js --input input.log --output log.json --log-level error,debug
149 | ```
150 |
151 | output.json
152 |
153 | ```json
154 | [
155 | {
156 | "timestamp": 1628475171254,
157 | "logLevel": "debug",
158 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e978",
159 | "err": "About to request the user information"
160 | },
161 | {
162 | "timestamp": 1628475171254,
163 | "logLevel": "debug",
164 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e978",
165 | "err": "About to request user orders list"
166 | },
167 | {
168 | "timestamp": 1628475171257,
169 | "logLevel": "debug",
170 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e821",
171 | "err": "About to request the user information"
172 | },
173 | {
174 | "timestamp": 1628475171257,
175 | "logLevel": "debug",
176 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e978",
177 | "err": "User information is gathered"
178 | },
179 | {
180 | "timestamp": 1628475171258,
181 | "logLevel": "debug",
182 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e821",
183 | "err": "About to request user orders list"
184 | },
185 | {
186 | "timestamp": 1628475171259,
187 | "logLevel": "error",
188 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e978",
189 | "err": "Cannot find user orders list"
190 | },
191 | {
192 | "timestamp": 1628475171259,
193 | "logLevel": "debug",
194 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e821",
195 | "err": "User information is retrieved"
196 | },
197 | {
198 | "timestamp": 1628475171262,
199 | "logLevel": "debug",
200 | "transactionId": "9abc55b2-807b-4361-9dbe-aa88b1b2e821",
201 | "err": "User information is retrieved"
202 | }
203 | ]
204 | ```
205 |
206 | ## ToDo list
207 |
208 | - [ ] connect it to logstash
209 | - [ ] implement elastic search
210 |
211 | ##
212 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/documentation/coverage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | - Documentation coverage
55 |
56 |
57 |
58 |

59 |
60 |
61 |
169 |
170 |
171 |
172 |
175 |
176 |
177 |
178 |
results matching ""
179 |
180 |
181 |
182 |
No results matching ""
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
198 |
199 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
--------------------------------------------------------------------------------
/documentation/dependencies.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | - Dependencies
51 |
52 |
53 | -
54 | @compodoc/compodoc : ^1.1.19
55 | -
56 | @nestjs/common : ^8.0.0
57 | -
58 | @nestjs/core : ^8.0.0
59 | -
60 | @nestjs/platform-express : ^8.0.0
61 | -
62 | class-transformer : ^0.5.1
63 | -
64 | class-validator : ^0.13.2
65 | -
66 | @types/faker : ^5.1.4
67 | -
68 | nest-winston : ^1.6.2
69 | -
70 | nestjs-command : ^3.1.1
71 | -
72 | reflect-metadata : ^0.1.13
73 | -
74 | rimraf : ^3.0.2
75 | -
76 | rxjs : ^7.2.0
77 | -
78 | faker : ^5.1.0
79 | -
80 | winston : ^3.7.2
81 | -
82 | yargs : ^17.5.1
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
results matching ""
94 |
95 |
96 |
97 |
No results matching ""
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
113 |
114 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/documentation/fonts/ionicons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/ionicons.eot
--------------------------------------------------------------------------------
/documentation/fonts/ionicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/ionicons.ttf
--------------------------------------------------------------------------------
/documentation/fonts/ionicons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/ionicons.woff
--------------------------------------------------------------------------------
/documentation/fonts/ionicons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/ionicons.woff2
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-300.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-300.eot
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-300.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-300.ttf
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-300.woff
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-300.woff2
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-700.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-700.eot
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-700.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-700.ttf
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-700.woff
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-700.woff2
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-italic.eot
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-italic.ttf
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-italic.woff
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-italic.woff2
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-regular.eot
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-regular.ttf
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-regular.woff
--------------------------------------------------------------------------------
/documentation/fonts/roboto-v15-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/fonts/roboto-v15-latin-regular.woff2
--------------------------------------------------------------------------------
/documentation/graph/dependencies.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
73 |
--------------------------------------------------------------------------------
/documentation/images/compodoc-vectorise-inverted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/images/compodoc-vectorise-inverted.png
--------------------------------------------------------------------------------
/documentation/images/compodoc-vectorise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/images/compodoc-vectorise.png
--------------------------------------------------------------------------------
/documentation/images/coverage-badge-documentation.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/documentation/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MoeidHeidari/log-parser/3c08b96617974640690a12001437aa475b9a4e02/documentation/images/favicon.ico
--------------------------------------------------------------------------------
/documentation/js/compodoc.js:
--------------------------------------------------------------------------------
1 | var compodoc = {
2 | EVENTS: {
3 | READY: 'compodoc.ready',
4 | SEARCH_READY: 'compodoc.search.ready'
5 | }
6 | };
7 |
8 | Object.assign( compodoc, EventDispatcher.prototype );
9 |
10 | document.addEventListener('DOMContentLoaded', function() {
11 | compodoc.dispatchEvent({
12 | type: compodoc.EVENTS.READY
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/documentation/js/lazy-load-graphs.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function() {
2 | var lazyGraphs = [].slice.call(document.querySelectorAll('[lazy]'));
3 | var active = false;
4 |
5 | var lazyLoad = function() {
6 | if (active === false) {
7 | active = true;
8 |
9 | setTimeout(function() {
10 | lazyGraphs.forEach(function(lazyGraph) {
11 | if (
12 | lazyGraph.getBoundingClientRect().top <= window.innerHeight &&
13 | lazyGraph.getBoundingClientRect().bottom >= 0 &&
14 | getComputedStyle(lazyGraph).display !== 'none'
15 | ) {
16 | lazyGraph.data = lazyGraph.getAttribute('lazy');
17 | lazyGraph.removeAttribute('lazy');
18 |
19 | lazyGraphs = lazyGraphs.filter(function(image) { return image !== lazyGraph});
20 |
21 | if (lazyGraphs.length === 0) {
22 | document.removeEventListener('scroll', lazyLoad);
23 | window.removeEventListener('resize', lazyLoad);
24 | window.removeEventListener('orientationchange', lazyLoad);
25 | }
26 | }
27 | });
28 |
29 | active = false;
30 | }, 200);
31 | }
32 | };
33 |
34 | // initial load
35 | lazyLoad();
36 |
37 | var container = document.querySelector('.container-fluid.modules');
38 | if (container) {
39 | container.addEventListener('scroll', lazyLoad);
40 | window.addEventListener('resize', lazyLoad);
41 | window.addEventListener('orientationchange', lazyLoad);
42 | }
43 |
44 | });
45 |
--------------------------------------------------------------------------------
/documentation/js/libs/EventDispatcher.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | var EventDispatcher=function(){};Object.assign(EventDispatcher.prototype,{addEventListener:function(i,t){void 0===this._listeners&&(this._listeners={});var e=this._listeners;void 0===e[i]&&(e[i]=[]),-1===e[i].indexOf(t)&&e[i].push(t)},hasEventListener:function(i,t){if(void 0===this._listeners)return!1;var e=this._listeners;return void 0!==e[i]&&-1!==e[i].indexOf(t)},removeEventListener:function(i,t){if(void 0!==this._listeners){var e=this._listeners[i];if(void 0!==e){var s=e.indexOf(t);-1!==s&&e.splice(s,1)}}},dispatchEvent:function(i){if(void 0!==this._listeners){var t=this._listeners[i.type];if(void 0!==t){i.target=this;var e=[],s=0,n=t.length;for(s=0;s1?t[t.length-1]:void 0:t[0]},this.getActiveContent=function(){var t=this.getActiveTab().getElementsByTagName("A")[0].getAttribute("href").replace("#","");return t&&document.getElementById("c-"+t)},this.tab.addEventListener("click",this.handle,!1)},d=document.querySelectorAll("[data-toggle='tab'], [data-toggle='pill']"),u=0,h=d.length;u",">"));else if(1==i){if(r.push("<",e.tagName),e.hasAttributes())for(var n=e.attributes,s=0,o=n.length;s");for(var h=e.childNodes,s=0,o=h.length;s")}else r.push("/>")}else{if(8!=i)throw"Error serializing XML. Unhandled node of type: "+i;r.push("\x3c!--",e.nodeValue,"--\x3e")}};Object.defineProperty(e.prototype,"innerHTML",{get:function(){for(var e=[],r=this.firstChild;r;)t(r,e),r=r.nextSibling;return e.join("")},set:function(e){for(;this.firstChild;)this.removeChild(this.firstChild);try{var t=new DOMParser;t.async=!1,sXML="";for(var r=t.parseFromString(sXML,"text/xml").documentElement.firstChild;r;)this.appendChild(this.ownerDocument.importNode(r,!0)),r=r.nextSibling}catch(e){throw new Error("Error parsing XML string")}}})}}((0,eval)("this").SVGElement);
--------------------------------------------------------------------------------
/documentation/js/libs/promise.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 (c) Pierre Duquesne
3 | * Licensed under the New BSD License.
4 | * https://github.com/stackp/promisejs
5 | */
6 | (function(a){function b(){this._callbacks=[];}b.prototype.then=function(a,c){var d;if(this._isdone)d=a.apply(c,this.result);else{d=new b();this._callbacks.push(function(){var b=a.apply(c,arguments);if(b&&typeof b.then==='function')b.then(d.done,d);});}return d;};b.prototype.done=function(){this.result=arguments;this._isdone=true;for(var a=0;a=300)&&j.status!==304);h.done(a,j.responseText,j);}};j.send(k);return h;}function h(a){return function(b,c,d){return g(a,b,c,d);};}var i={Promise:b,join:c,chain:d,ajax:g,get:h('GET'),post:h('POST'),put:h('PUT'),del:h('DELETE'),ENOXHR:1,ETIMEOUT:2,ajaxTimeout:0};if(typeof define==='function'&&define.amd)define(function(){return i;});else a.promise=i;})(this);
--------------------------------------------------------------------------------
/documentation/js/libs/tablesort.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * tablesort v5.1.0 (2018-09-14)
3 | * http://tristen.ca/tablesort/demo/
4 | * Copyright (c) 2018 ; Licensed MIT
5 | */
6 | !function(){function a(b,c){if(!(this instanceof a))return new a(b,c);if(!b||"TABLE"!==b.tagName)throw new Error("Element must be a table");this.init(b,c||{})}var b=[],c=function(a){var b;return window.CustomEvent&&"function"==typeof window.CustomEvent?b=new CustomEvent(a):(b=document.createEvent("CustomEvent"),b.initCustomEvent(a,!1,!1,void 0)),b},d=function(a){return a.getAttribute("data-sort")||a.textContent||a.innerText||""},e=function(a,b){return a=a.trim().toLowerCase(),b=b.trim().toLowerCase(),a===b?0:a0)if(a.tHead&&a.tHead.rows.length>0){for(e=0;e0&&l.push(k),m++;if(!l)return}for(m=0;m
16 |
82 |
83 |
84 |
90 |
95 |
96 |
97 |
103 |
108 |
109 |
110 |
116 |
121 |
122 |
123 |
129 |
140 |
141 |
142 | Documentation coverage
143 |
144 |
145 |
146 | Documentation generated using
147 |
148 |
149 |
150 |
151 |
152 | `);
153 | this.innerHTML = tp.strings;
154 | }
155 | });
--------------------------------------------------------------------------------
/documentation/js/search/search-lunr.js:
--------------------------------------------------------------------------------
1 | (function(compodoc) {
2 |
3 | function LunrSearchEngine() {
4 | this.index = undefined;
5 | this.store = {};
6 | this.name = 'LunrSearchEngine';
7 | }
8 |
9 | LunrSearchEngine.prototype.init = function() {
10 | var that = this,
11 | d = new promise.Promise();
12 |
13 | that.index = lunr.Index.load(COMPODOC_SEARCH_INDEX.index);
14 | that.store = COMPODOC_SEARCH_INDEX.store;
15 | d.done();
16 |
17 | return d;
18 | };
19 |
20 | LunrSearchEngine.prototype.search = function(q, offset, length) {
21 | var that = this,
22 | results = [],
23 | d = new promise.Promise();
24 |
25 | if (this.index) {
26 | results = $.map(this.index.search('*' + q + '*'), function(result) {
27 | var doc = that.store[result.ref];
28 |
29 | return {
30 | title: doc.title,
31 | url: doc.url,
32 | body: doc.summary || doc.body
33 | };
34 | });
35 | }
36 |
37 | d.done({
38 | query: q,
39 | results: length === 0 ? results : results.slice(0, length),
40 | count: results.length
41 | });
42 |
43 | return d;
44 | };
45 |
46 | compodoc.addEventListener(compodoc.EVENTS.READY, function(event) {
47 | var engine = new LunrSearchEngine(),
48 | initialized = false;
49 |
50 | function query(q, offset, length) {
51 | if (!initialized) throw new Error('Search has not been initialized');
52 | return engine.search(q, offset, length);
53 | }
54 |
55 | compodoc.search = {
56 | query: query
57 | };
58 |
59 | engine.init()
60 | .then(function() {
61 | initialized = true;
62 | compodoc.dispatchEvent({
63 | type: compodoc.EVENTS.SEARCH_READY
64 | });
65 | });
66 | });
67 | })(compodoc);
68 |
--------------------------------------------------------------------------------
/documentation/js/sourceCode.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function() {
2 | var $tabSource = document.querySelector('#source-tab'),
3 | $tabInfo = document.querySelector('#info-tab'),
4 | $tabReadme = document.querySelector('#readme-tab'),
5 | $tabTemplate = document.querySelector('#templateData-tab'),
6 | $tabTree = document.querySelector('#tree-tab'),
7 | $tabExample = document.querySelector('#example-tab'),
8 | $prismPre = document.querySelector('pre.compodoc-sourcecode');
9 | if ($tabSource && $prismPre) {
10 | $prismCode = $prismPre.querySelector('code'),
11 | $content = document.querySelector('.content'),
12 | prismLinks = document.querySelectorAll('.link-to-prism')
13 |
14 | for (var i = 0; i < prismLinks.length; i++) {
15 | prismLinks[i].addEventListener('click', linkToPrism, false);
16 | }
17 |
18 | function linkToPrism(event) {
19 | var targetLine = event.target.getAttribute('data-line');
20 | event.preventDefault();
21 |
22 | $prismPre.setAttribute('data-line', targetLine);
23 | Prism.highlightElement($prismCode, function() {});
24 |
25 | $tabSource.click();
26 |
27 | setTimeout(function() {
28 | var $prismHighlightLine = document.querySelector('.line-highlight'),
29 | top = parseInt(getComputedStyle($prismHighlightLine)['top']);
30 | $content.scrollTop = top;
31 | }, 500);
32 | };
33 |
34 | window.onhashchange = function(event) {
35 | switch (window.location.hash) {
36 | case '':
37 | case '#info':
38 | $tabInfo.click();
39 | break;
40 | case '#readme':
41 | $tabReadme.click();
42 | break;
43 | case '#source':
44 | $tabSource.click();
45 | break;
46 | case '#template':
47 | $tabTemplate.click();
48 | break;
49 | case '#dom-tree':
50 | $tabTree.click();
51 | break;
52 | case '#example':
53 | $tabExample.click();
54 | break;
55 | }
56 | }
57 | }
58 | });
59 |
--------------------------------------------------------------------------------
/documentation/js/svg-pan-zoom.controls.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function() {
2 | if (document.getElementById('module-graph-svg')) {
3 | panZoom = svgPanZoom(document.getElementById('module-graph-svg').querySelector('svg'), {
4 | zoomEnabled: true,
5 | minZoom: 1,
6 | maxZoom: 5
7 | });
8 |
9 | document.getElementById('zoom-in').addEventListener('click', function(ev) {
10 | ev.preventDefault();
11 | panZoom.zoomIn();
12 | });
13 |
14 | document.getElementById('zoom-out').addEventListener('click', function(ev) {
15 | ev.preventDefault();
16 | panZoom.zoomOut();
17 | });
18 |
19 | document.getElementById('reset').addEventListener('click', function(ev) {
20 | ev.preventDefault();
21 | panZoom.resetZoom();
22 | panZoom.resetPan();
23 | });
24 |
25 | var overviewFullscreen = false,
26 | originalOverviewHeight;
27 |
28 | document.getElementById('fullscreen').addEventListener('click', function(ev) {
29 | if (overviewFullscreen) {
30 | document.getElementById('module-graph-svg').style.height = originalOverviewHeight;
31 | overviewFullscreen = false;
32 | if (ev.target) {
33 | ev.target.classList.remove('ion-md-close');
34 | ev.target.classList.add('ion-ios-resize');
35 | }
36 | } else {
37 | originalOverviewHeight = document.getElementById('module-graph-svg').style.height;
38 | document.getElementById('module-graph-svg').style.height = '85vh';
39 | overviewFullscreen = true;
40 | if (ev.target) {
41 | ev.target.classList.remove('ion-ios-resize');
42 | ev.target.classList.add('ion-md-close');
43 | }
44 | }
45 | document.getElementById('module-graph-svg').querySelector('svg').style.height = document.getElementById('module-graph-svg').clientHeight;
46 | setTimeout(function() {
47 | panZoom.resize();
48 | panZoom.fit();
49 | panZoom.center();
50 | }, 0)
51 | });
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/documentation/js/tabs.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function() {
2 | var tabs = document.getElementsByClassName('nav-tabs'),
3 | updateAddress = function(e) {
4 | if(history.pushState && e.target.dataset.link) {
5 | history.pushState(null, null, '#' + e.target.dataset.link);
6 | }
7 | };
8 | if (tabs.length > 0) {
9 | tabs = tabs[0].querySelectorAll('li');
10 | for (var i = 0; i < tabs.length; i++) {
11 | tabs[i].addEventListener('click', updateAddress);
12 | var linkTag = tabs[i].querySelector('a');
13 | if (location.hash !== '') {
14 | var currentHash = location.hash.substr(1);
15 | if (currentHash === linkTag.dataset.link) {
16 | linkTag.click();
17 | }
18 | }
19 | }
20 | }
21 | });
22 |
--------------------------------------------------------------------------------
/documentation/js/tree.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', function() {
2 | var tabs = document.getElementsByClassName('nav-tabs')[0],
3 | tabsCollection = tabs.getElementsByTagName('A'),
4 | treeTab;
5 | var len = tabsCollection.length;
6 | for(var i = 0; i < len; i++) {
7 | if (tabsCollection[i].getAttribute('id') === 'tree-tab') {
8 | treeTab = tabsCollection[i];
9 | }
10 | }
11 |
12 | // short-circuit if no tree tab
13 | if (!treeTab) return;
14 |
15 | var handler = new Tautologistics.NodeHtmlParser.HtmlBuilder(function(error, dom) {
16 | if (error) {
17 | console.log('handler ko');
18 | }
19 | }),
20 | parser = new Tautologistics.NodeHtmlParser.Parser(handler),
21 | currentLocation = window.location;
22 | parser.parseComplete(COMPONENT_TEMPLATE);
23 |
24 | var newNodes = [],
25 | newEdges = [],
26 | parsedHtml = handler.dom[0],
27 | nodeCount = 0,
28 | nodeLevel = 0;
29 |
30 | newNodes.push({
31 | _id: 0,
32 | label: parsedHtml.name,
33 | type: parsedHtml.type
34 | })
35 | //Add id for nodes
36 | var traverseIds = function(o) {
37 | for (i in o) {
38 | if (!!o[i] && typeof(o[i]) == "object") {
39 | if (!o[i].length && o[i].type === 'tag') {
40 | nodeCount += 1;
41 | o[i]._id = nodeCount;
42 | }
43 | traverseIds(o[i]);
44 | }
45 | }
46 | }
47 | parsedHtml._id = 0;
48 | traverseIds(parsedHtml);
49 |
50 |
51 | var DeepIterator = deepIterator.default,
52 | it = DeepIterator(parsedHtml);
53 | for (let {
54 | value,
55 | parent,
56 | parentNode,
57 | key,
58 | type
59 | } of it) {
60 | if (type === 'NonIterableObject' && typeof key !== 'undefined' && value.type === 'tag') {
61 | var newNode = {
62 | id: value._id,
63 | label: value.name,
64 | type: value.type
65 | };
66 | for(var i = 0; i < COMPONENTS.length; i++) {
67 | if (COMPONENTS[i].selector === value.name) {
68 | newNode.font = {
69 | multi: 'html'
70 | };
71 | newNode.label = '' + newNode.label + '';
72 | newNode.color = '#FB7E81';
73 | newNode.name = COMPONENTS[i].name;
74 | }
75 | }
76 | for(var i = 0; i < DIRECTIVES.length; i++) {
77 | if (value.attributes) {
78 | for(attr in value.attributes) {
79 | if (DIRECTIVES[i].selector.indexOf(attr) !== -1) {
80 | newNode.font = {
81 | multi: 'html'
82 | };
83 | newNode.label = '' + newNode.label + '';
84 | newNode.color = '#FF9800';
85 | newNode.name = DIRECTIVES[i].name;
86 | }
87 | }
88 | }
89 | }
90 | newNodes.push(newNode);
91 | newEdges.push({
92 | from: parentNode._parent._id,
93 | to: value._id,
94 | arrows: 'to'
95 | });
96 | }
97 | }
98 |
99 | newNodes.shift();
100 |
101 | var container = document.getElementById('tree-container'),
102 | data = {
103 | nodes: newNodes,
104 | edges: newEdges
105 | },
106 | options = {
107 | layout: {
108 | hierarchical: {
109 | sortMethod: 'directed',
110 | enabled: true
111 | }
112 | },
113 | nodes: {
114 | shape: 'ellipse',
115 | fixed: true
116 | }
117 | },
118 |
119 | handleClickNode = function(params) {
120 | var clickeNodeId;
121 | if (params.nodes.length > 0) {
122 | clickeNodeId = params.nodes[0];
123 | for(var i = 0; i < newNodes.length; i++) {
124 | if (newNodes[i].id === clickeNodeId) {
125 | for(var j = 0; j < COMPONENTS.length; j++) {
126 | if (COMPONENTS[j].name === newNodes[i].name) {
127 | document.location.href = currentLocation.origin + currentLocation.pathname.replace(ACTUAL_COMPONENT.name, newNodes[i].name);
128 | }
129 | }
130 | }
131 | }
132 | }
133 | },
134 |
135 | loadTree = function () {
136 | setTimeout(function() {
137 | container.style.height = document.getElementsByClassName('content')[0].offsetHeight - 140 + 'px';
138 | var network = new vis.Network(container, data, options);
139 | network.on('click', handleClickNode);
140 | }, 200); // Fade is 0.150
141 | };
142 |
143 | loadTree();
144 | treeTab.addEventListener('click', function() {
145 | loadTree();
146 | });
147 | });
148 |
--------------------------------------------------------------------------------
/documentation/miscellaneous/enumerations.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | - Miscellaneous
54 | - Enumerations
55 |
56 |
57 |
58 | Index
59 |
60 |
61 |
62 |
63 |
68 | |
69 |
70 |
71 |
72 |
73 |
74 |
src/parser/enum/log-level.enum.ts
75 |
76 |
77 |
78 |
79 |
80 |
81 | LogLevel
82 | |
83 |
84 |
85 |
86 | An enum that represents the log levels the parser understands
87 |
88 | |
89 |
90 |
91 |
92 | ERROR
93 | |
94 |
95 |
96 |
97 | Value : error
98 | |
99 |
100 |
101 |
102 | INFO
103 | |
104 |
105 |
106 |
107 | Value : info
108 | |
109 |
110 |
111 |
112 | WARN
113 | |
114 |
115 |
116 |
117 | Value : warn
118 | |
119 |
120 |
121 |
122 | DEBUG
123 | |
124 |
125 |
126 |
127 | Value : debug
128 | |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
results matching ""
139 |
140 |
141 |
142 |
No results matching ""
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
158 |
159 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
--------------------------------------------------------------------------------
/documentation/miscellaneous/functions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | - Miscellaneous
54 | - Functions
55 |
56 |
57 |
58 | Index
59 |
60 |
61 |
62 |
63 |
71 | |
72 |
73 |
74 |
75 |
76 |
77 |
src/cli.ts
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | bootstrap
86 |
87 |
88 | |
89 |
90 |
91 |
92 | bootstrap()
93 | |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Main application entry point
102 |
103 |
104 | |
105 |
106 |
107 |
108 | src/parser/common/utils.ts
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | validateDTO
117 |
118 |
119 | |
120 |
121 |
122 |
123 | validateDTO(dto: any)
124 | |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | validates dto and returns bad request if it is wrong
133 |
134 |
135 |
136 | Parameters :
137 |
138 |
139 |
140 |
141 | Name |
142 | Type |
143 | Optional |
144 | Description |
145 |
146 |
147 |
148 |
149 | dto |
150 |
151 | any
152 | |
153 |
154 |
155 | No
156 | |
157 |
158 |
159 |
160 | dto
161 |
162 | |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | Returns : Promise<any>
171 |
172 |
173 |
174 |
175 |
176 | |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
results matching ""
186 |
187 |
188 |
189 |
No results matching ""
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
205 |
206 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
--------------------------------------------------------------------------------
/documentation/miscellaneous/variables.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | - Miscellaneous
54 | - Variables
55 |
56 |
57 |
58 | Index
59 |
60 |
61 |
62 |
63 |
68 | |
69 |
70 |
71 |
72 |
73 |
74 |
src/parser/dtos/parser-command-dto.ts
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | allowedProperties
83 |
84 |
85 | |
86 |
87 |
88 |
89 | Type : []
90 |
91 | |
92 |
93 |
94 |
95 | Default value : ['input', 'output', 'logLevel']
96 | |
97 |
98 |
99 |
100 |
101 | list of allowed properties
102 |
103 | |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
results matching ""
115 |
116 |
117 |
118 |
No results matching ""
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
134 |
135 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/documentation/modules.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | - Modules
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 |
52 |
53 |
56 |
57 |
58 |
59 |
60 |
61 |
64 |
65 |
66 |
69 |
70 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
results matching ""
99 |
100 |
101 |
102 |
No results matching ""
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
118 |
119 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/documentation/modules/AppModule.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | - Modules
39 | - AppModule
40 |
41 |
42 |
43 |
44 |
45 |
47 |
49 |
50 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | -
98 | Info
99 |
100 | -
101 | Source
102 |
103 |
104 |
105 |
106 |
107 |
108 |
File
110 |
111 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
Imports
124 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
import { Module } from '@nestjs/common';
139 | import { CommandModule } from 'nestjs-command';
140 | import { ParserModule } from '../parser/parser.module';
141 |
142 |
143 |
144 | @Module({
145 | imports: [CommandModule,ParserModule,],
146 | providers: []
147 | })
148 | export class AppModule {}
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
results matching ""
171 |
172 |
173 |
174 |
No results matching ""
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
190 |
191 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/documentation/modules/AppModule/dependencies.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
41 |
--------------------------------------------------------------------------------
/documentation/modules/ParserModule/dependencies.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
53 |
--------------------------------------------------------------------------------
/documentation/properties.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | parser documentation
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | - Properties
52 |
53 |
54 | -
55 | Version : 0.0.1
56 | -
57 | Description :
58 | -
59 | License : UNLICENSED
60 | -
61 | Author :
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
results matching ""
71 |
72 |
73 |
74 |
No results matching ""
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
90 |
91 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/documentation/styles/bootstrap-card.css:
--------------------------------------------------------------------------------
1 | .card {
2 | position: relative;
3 | display: block;
4 | margin-bottom: 20px;
5 | background-color: #fff;
6 | border: 1px solid #ddd;
7 | border-radius: 4px;
8 | }
9 |
10 | .card-block {
11 | padding: 15px;
12 | }
13 | .card-block:before, .card-block:after {
14 | content: " ";
15 | display: table;
16 | }
17 | .card-block:after {
18 | clear: both;
19 | }
20 |
21 | .card-title {
22 | margin: 5px;
23 | margin-bottom: 2px;
24 | text-align: center;
25 | }
26 |
27 | .card-subtitle {
28 | margin-top: -10px;
29 | margin-bottom: 0;
30 | }
31 |
32 | .card-text:last-child {
33 | margin-bottom: 0;
34 | margin-top: 10px;
35 | }
36 |
37 | .card-link:hover {
38 | text-decoration: none;
39 | }
40 | .card-link + .card-link {
41 | margin-left: 15px;
42 | }
43 |
44 | .card > .list-group:first-child .list-group-item:first-child {
45 | border-top-right-radius: 4px;
46 | border-top-left-radius: 4px;
47 | }
48 | .card > .list-group:last-child .list-group-item:last-child {
49 | border-bottom-right-radius: 4px;
50 | border-bottom-left-radius: 4px;
51 | }
52 |
53 | .card-header {
54 | padding: 10px 15px;
55 | background-color: #f5f5f5;
56 | border-bottom: 1px solid #ddd;
57 | }
58 | .card-header:before, .card-header:after {
59 | content: " ";
60 | display: table;
61 | }
62 | .card-header:after {
63 | clear: both;
64 | }
65 | .card-header:first-child {
66 | border-radius: 4px 4px 0 0;
67 | }
68 |
69 | .card-footer {
70 | padding: 10px 15px;
71 | background-color: #f5f5f5;
72 | border-top: 1px solid #ddd;
73 | }
74 | .card-footer:before, .card-footer:after {
75 | content: " ";
76 | display: table;
77 | }
78 | .card-footer:after {
79 | clear: both;
80 | }
81 | .card-footer:last-child {
82 | border-radius: 0 0 4px 4px;
83 | }
84 |
85 | .card-header-tabs {
86 | margin-right: -5px;
87 | margin-bottom: -10px;
88 | margin-left: -5px;
89 | border-bottom: 0;
90 | }
91 |
92 | .card-header-pills {
93 | margin-right: -5px;
94 | margin-left: -5px;
95 | }
96 |
97 | .card-primary {
98 | background-color: #337ab7;
99 | border-color: #337ab7;
100 | }
101 | .card-primary .card-header,
102 | .card-primary .card-footer {
103 | background-color: transparent;
104 | }
105 |
106 | .card-success {
107 | background-color: #5cb85c;
108 | border-color: #5cb85c;
109 | }
110 | .card-success .card-header,
111 | .card-success .card-footer {
112 | background-color: transparent;
113 | }
114 |
115 | .card-info {
116 | background-color: #5bc0de;
117 | border-color: #5bc0de;
118 | }
119 | .card-info .card-header,
120 | .card-info .card-footer {
121 | background-color: transparent;
122 | }
123 |
124 | .card-warning {
125 | background-color: #f0ad4e;
126 | border-color: #f0ad4e;
127 | }
128 | .card-warning .card-header,
129 | .card-warning .card-footer {
130 | background-color: transparent;
131 | }
132 |
133 | .card-danger {
134 | background-color: #d9534f;
135 | border-color: #d9534f;
136 | }
137 | .card-danger .card-header,
138 | .card-danger .card-footer {
139 | background-color: transparent;
140 | }
141 |
142 | .card-outline-primary {
143 | background-color: transparent;
144 | border-color: #337ab7;
145 | }
146 |
147 | .card-outline-secondary {
148 | background-color: transparent;
149 | border-color: #ccc;
150 | }
151 |
152 | .card-outline-info {
153 | background-color: transparent;
154 | border-color: #5bc0de;
155 | }
156 |
157 | .card-outline-success {
158 | background-color: transparent;
159 | border-color: #5cb85c;
160 | }
161 |
162 | .card-outline-warning {
163 | background-color: transparent;
164 | border-color: #f0ad4e;
165 | }
166 |
167 | .card-outline-danger {
168 | background-color: transparent;
169 | border-color: #d9534f;
170 | }
171 |
172 | .card-inverse .card-header,
173 | .card-inverse .card-footer {
174 | border-color: rgba(255, 255, 255, 0.2);
175 | }
176 | .card-inverse .card-header,
177 | .card-inverse .card-footer,
178 | .card-inverse .card-title,
179 | .card-inverse .card-blockquote {
180 | color: #fff;
181 | }
182 | .card-inverse .card-link,
183 | .card-inverse .card-text,
184 | .card-inverse .card-subtitle,
185 | .card-inverse .card-blockquote .blockquote-footer {
186 | color: rgba(255, 255, 255, 0.65);
187 | }
188 | .card-inverse .card-link:hover, .card-inverse .card-link:focus {
189 | color: #fff;
190 | }
191 |
192 | .card-blockquote {
193 | padding: 0;
194 | margin-bottom: 0;
195 | border-left: 0;
196 | }
197 |
198 | .card-img {
199 | border-radius: .25em;
200 | }
201 |
202 | .card-img-overlay {
203 | position: absolute;
204 | top: 0;
205 | right: 0;
206 | bottom: 0;
207 | left: 0;
208 | padding: 15px;
209 | }
210 |
211 | .card-img-top {
212 | border-top-right-radius: 4px;
213 | border-top-left-radius: 4px;
214 | }
215 |
216 | .card-img-bottom {
217 | border-bottom-right-radius: 4px;
218 | border-bottom-left-radius: 4px;
219 | }
220 |
--------------------------------------------------------------------------------
/documentation/styles/dark.css:
--------------------------------------------------------------------------------
1 | body.dark {
2 | background: #212121;
3 | color: #fafafa;
4 | }
5 |
6 | .dark code {
7 | color: #e09393;
8 | }
9 |
10 | .dark a,
11 | .dark .menu ul.list li a.active {
12 | color: #7fc9ff;
13 | }
14 |
15 | .dark .menu {
16 | background: #212121;
17 | border-right: 1px solid #444;
18 | }
19 |
20 | .dark .menu ul.list li a {
21 | color: #fafafa;
22 | }
23 |
24 | .dark .menu ul.list li.divider {
25 | background: #444;
26 | }
27 |
28 | .dark .xs-menu ul.list li:nth-child(2) {
29 | margin: 0;
30 | background: none;
31 | }
32 |
33 | .dark .menu ul.list li:nth-child(2) {
34 | margin: 0;
35 | background: none;
36 | }
37 |
38 | .dark #book-search-input {
39 | background: #212121;
40 | border-top: 1px solid #444;
41 | border-bottom: 1px solid #444;
42 | color: #fafafa;
43 | }
44 |
45 | .dark .table.metadata > tbody > tr:hover {
46 | color: #555;
47 | }
48 |
49 | .dark .table-bordered {
50 | border: 1px solid #444;
51 | }
52 |
53 | .dark .table-bordered > tbody > tr > td,
54 | .dark .table-bordered > tbody > tr > th,
55 | .dark .table-bordered > tfoot > tr > td,
56 | .dark .table-bordered > tfoot > tr > th,
57 | .dark .table-bordered > thead > tr > td,
58 | .dark .table-bordered > thead > tr > th {
59 | border: 1px solid #444;
60 | }
61 |
62 | .dark .coverage a,
63 | .dark .coverage-count {
64 | color: #fafafa;
65 | }
66 |
67 | .dark .coverage-header {
68 | color: black;
69 | }
70 |
71 | .dark .routes svg text,
72 | .dark .routes svg a {
73 | fill: white;
74 | }
75 | .dark .routes svg rect {
76 | fill: #212121 !important;
77 | }
78 |
79 | .dark .navbar-default,
80 | .dark .btn-default {
81 | background-color: black;
82 | border-color: #444;
83 | color: #fafafa;
84 | }
85 |
86 | .dark .navbar-default .navbar-brand {
87 | color: #fafafa;
88 | }
89 |
90 | .dark .overview .card,
91 | .dark .modules .card {
92 | background: #171717;
93 | color: #fafafa;
94 | border: 1px solid #444;
95 | }
96 | .dark .overview .card a {
97 | color: #fafafa;
98 | }
99 |
100 | .dark .modules .card-header {
101 | background: none;
102 | border-bottom: 1px solid #444;
103 | }
104 |
105 | .dark .module .list-group-item {
106 | background: none;
107 | border: 1px solid #444;
108 | }
109 |
110 | .dark .container-fluid.module h3 a {
111 | color: #337ab7;
112 | }
113 |
114 | .dark table.params thead {
115 | background: #484848;
116 | color: #fafafa;
117 | }
118 |
--------------------------------------------------------------------------------
/documentation/styles/laravel.css:
--------------------------------------------------------------------------------
1 | .nav-tabs > li > a {
2 | text-decoration: none;
3 | }
4 |
5 | .navbar-default .navbar-brand {
6 | color: #f4645f;
7 | text-decoration: none;
8 | font-size: 16px;
9 | }
10 |
11 | .menu ul.list li a[data-type='chapter-link'],
12 | .menu ul.list li.chapter .simple {
13 | color: #525252;
14 | border-bottom: 1px dashed rgba(0, 0, 0, 0.1);
15 | }
16 |
17 | .content h1,
18 | .content h2,
19 | .content h3,
20 | .content h4,
21 | .content h5 {
22 | color: #292e31;
23 | font-weight: normal;
24 | }
25 |
26 | .content {
27 | color: #4c555a;
28 | }
29 |
30 | a {
31 | color: #f4645f;
32 | text-decoration: underline;
33 | }
34 | a:hover {
35 | color: #f1362f;
36 | }
37 |
38 | .menu ul.list li:nth-child(2) {
39 | margin-top: 0;
40 | }
41 |
42 | .menu ul.list li.title a {
43 | color: #f4645f;
44 | text-decoration: none;
45 | font-size: 16px;
46 | }
47 |
48 | .menu ul.list li a {
49 | color: #f4645f;
50 | text-decoration: none;
51 | }
52 | .menu ul.list li a.active {
53 | color: #f4645f;
54 | font-weight: bold;
55 | }
56 |
57 | code {
58 | box-sizing: border-box;
59 | display: inline-block;
60 | padding: 0 5px;
61 | background: #f0f2f1;
62 | border-radius: 3px;
63 | color: #b93d6a;
64 | font-size: 13px;
65 | line-height: 20px;
66 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125);
67 | }
68 |
69 | pre {
70 | margin: 0;
71 | padding: 12px 12px;
72 | background: rgba(238, 238, 238, 0.35);
73 | border-radius: 3px;
74 | font-size: 13px;
75 | line-height: 1.5em;
76 | font-weight: 500;
77 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125);
78 | }
79 |
80 | .dark body {
81 | color: #fafafa;
82 | }
83 | .dark .content h1,
84 | .dark .content h2,
85 | .dark .content h3,
86 | .dark .content h4,
87 | .dark .content h5 {
88 | color: #fafafa;
89 | }
90 |
91 | .dark code {
92 | background: none;
93 | }
94 |
95 | .dark .content {
96 | color: #fafafa;
97 | }
98 |
99 | .dark .menu ul.list li a[data-type='chapter-link'],
100 | .dark .menu ul.list li.chapter .simple {
101 | color: #fafafa;
102 | }
103 |
104 | .dark .menu ul.list li.title a {
105 | color: #fafafa;
106 | }
107 |
108 | .dark .menu ul.list li a {
109 | color: #fafafa;
110 | }
111 | .dark .menu ul.list li a.active {
112 | color: #7fc9ff;
113 | }
114 |
--------------------------------------------------------------------------------
/documentation/styles/material.css:
--------------------------------------------------------------------------------
1 | .menu {
2 | background: none;
3 | }
4 |
5 | a:hover {
6 | text-decoration: none;
7 | }
8 |
9 | /** LINK **/
10 |
11 | .menu ul.list li a {
12 | text-decoration: none;
13 | }
14 |
15 | .menu ul.list li a:hover,
16 | .menu ul.list li.chapter .simple:hover {
17 | background-color: #f8f9fa;
18 | text-decoration: none;
19 | }
20 |
21 | #book-search-input {
22 | margin-bottom: 0;
23 | }
24 |
25 | .menu ul.list li.divider {
26 | margin-top: 0;
27 | background: #e9ecef;
28 | }
29 |
30 | .menu .title:hover {
31 | background-color: #f8f9fa;
32 | }
33 |
34 | /** CARD **/
35 |
36 | .card {
37 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
38 | 0 1px 5px 0 rgba(0, 0, 0, 0.12);
39 | border-radius: 0.125rem;
40 | border: 0;
41 | margin-top: 1px;
42 | }
43 |
44 | .card-header {
45 | background: none;
46 | }
47 |
48 | /** BUTTON **/
49 |
50 | .btn {
51 | border-radius: 0.125rem;
52 | }
53 |
54 | /** NAV BAR **/
55 |
56 | .nav {
57 | border: 0;
58 | }
59 | .nav-tabs > li > a {
60 | border: 0;
61 | border-bottom: 0.214rem solid transparent;
62 | color: rgba(0, 0, 0, 0.54);
63 | margin-right: 0;
64 | }
65 | .nav-tabs > li.active > a,
66 | .nav-tabs > li.active > a:focus,
67 | .nav-tabs > li.active > a:hover {
68 | color: rgba(0, 0, 0, 0.87);
69 | border-top: 0;
70 | border-left: 0;
71 | border-right: 0;
72 | border-bottom: 0.214rem solid transparent;
73 | border-color: #008cff;
74 | font-weight: bold;
75 | }
76 | .nav > li > a:focus,
77 | .nav > li > a:hover {
78 | background: none;
79 | }
80 |
81 | /** LIST **/
82 |
83 | .list-group-item:first-child {
84 | border-top-left-radius: 0.125rem;
85 | border-top-right-radius: 0.125rem;
86 | }
87 | .list-group-item:last-child {
88 | border-bottom-left-radius: 0.125rem;
89 | border-bottom-right-radius: 0.125rem;
90 | }
91 |
92 | /** MISC **/
93 |
94 | .modifier {
95 | border-radius: 0.125rem;
96 | }
97 |
98 | pre[class*='language-'] {
99 | border-radius: 0.125rem;
100 | }
101 |
102 | /** TABLE **/
103 |
104 | .table-hover > tbody > tr:hover {
105 | background: rgba(0, 0, 0, 0.075);
106 | }
107 |
108 | table.params thead {
109 | background: none;
110 | }
111 | table.params thead td {
112 | color: rgba(0, 0, 0, 0.54);
113 | font-weight: bold;
114 | }
115 |
116 | .dark .menu .title:hover {
117 | background-color: #2d2d2d;
118 | }
119 | .dark .menu ul.list li a:hover,
120 | .dark .menu ul.list li.chapter .simple:hover {
121 | background-color: #2d2d2d;
122 | }
123 | .dark .nav-tabs > li:not(.active) > a {
124 | color: #fafafa;
125 | }
126 | .dark table.params thead {
127 | background: #484848;
128 | }
129 | .dark table.params thead td {
130 | color: #fafafa;
131 | }
132 |
--------------------------------------------------------------------------------
/documentation/styles/original.css:
--------------------------------------------------------------------------------
1 | .navbar-default .navbar-brand,
2 | .menu ul.list li.title {
3 | font-weight: bold;
4 | color: #3c3c3c;
5 | padding-bottom: 5px;
6 | }
7 |
8 | .menu ul.list li a[data-type='chapter-link'],
9 | .menu ul.list li.chapter .simple {
10 | font-weight: bold;
11 | font-size: 14px;
12 | }
13 |
14 | .menu ul.list li a[href='./routes.html'] {
15 | border-bottom: none;
16 | }
17 |
18 | .menu ul.list > li:nth-child(2) {
19 | display: none;
20 | }
21 |
22 | .menu ul.list li.chapter ul.links {
23 | background: #fff;
24 | padding-left: 0;
25 | }
26 |
27 | .menu ul.list li.chapter ul.links li {
28 | border-bottom: 1px solid #ddd;
29 | padding-left: 20px;
30 | }
31 |
32 | .menu ul.list li.chapter ul.links li:last-child {
33 | border-bottom: none;
34 | }
35 |
36 | .menu ul.list li a.active {
37 | color: #337ab7;
38 | font-weight: bold;
39 | }
40 |
41 | #book-search-input {
42 | margin-bottom: 0;
43 | border-bottom: none;
44 | }
45 | .menu ul.list li.divider {
46 | margin: 0;
47 | }
48 |
49 | .dark .menu ul.list li.chapter ul.links {
50 | background: none;
51 | }
52 |
--------------------------------------------------------------------------------
/documentation/styles/postmark.css:
--------------------------------------------------------------------------------
1 | .navbar-default {
2 | background: #ffde00;
3 | border: none;
4 | }
5 |
6 | .navbar-default .navbar-brand {
7 | color: #333;
8 | font-weight: bold;
9 | }
10 |
11 | .menu {
12 | background: #333;
13 | color: #fcfcfc;
14 | }
15 |
16 | .menu ul.list li a {
17 | color: #333;
18 | }
19 |
20 | .menu ul.list li.title {
21 | background: #ffde00;
22 | color: #333;
23 | padding-bottom: 5px;
24 | }
25 |
26 | .menu ul.list li:nth-child(2) {
27 | margin-top: 0;
28 | }
29 |
30 | .menu ul.list li.chapter a,
31 | .menu ul.list li.chapter .simple {
32 | color: white;
33 | text-decoration: none;
34 | }
35 |
36 | .menu ul.list li.chapter ul.links a {
37 | color: #949494;
38 | text-transform: none;
39 | padding-left: 35px;
40 | }
41 |
42 | .menu ul.list li.chapter ul.links a:hover,
43 | .menu ul.list li.chapter ul.links a.active {
44 | color: #ffde00;
45 | }
46 |
47 | .menu ul.list li.chapter ul.links {
48 | padding-left: 0;
49 | }
50 |
51 | .menu ul.list li.divider {
52 | background: rgba(255, 255, 255, 0.07);
53 | }
54 |
55 | #book-search-input input,
56 | #book-search-input input:focus,
57 | #book-search-input input:hover {
58 | color: #949494;
59 | }
60 |
61 | .copyright {
62 | color: #b3b3b3;
63 | background: #272525;
64 | }
65 |
66 | .content {
67 | background: #fcfcfc;
68 | }
69 |
70 | .content a {
71 | color: #007dcc;
72 | }
73 |
74 | .content a:visited {
75 | color: #0165a5;
76 | }
77 |
78 | .menu ul.list li:nth-last-child(2) {
79 | background: none;
80 | }
81 |
82 | .list-group-item:first-child,
83 | .list-group-item:last-child {
84 | border-radius: 0;
85 | }
86 |
87 | .menu ul.list li.title a {
88 | text-decoration: none;
89 | font-weight: bold;
90 | }
91 |
92 | .menu ul.list li.title a:hover {
93 | background: rgba(255, 255, 255, 0.1);
94 | }
95 |
96 | .breadcrumb > li + li:before {
97 | content: '»\00a0';
98 | }
99 |
100 | .breadcrumb {
101 | padding-bottom: 15px;
102 | border-bottom: 1px solid #e1e4e5;
103 | }
104 |
105 | code {
106 | white-space: nowrap;
107 | max-width: 100%;
108 | background: #f5f5f5;
109 | padding: 2px 5px;
110 | color: #666666;
111 | overflow-x: auto;
112 | border-radius: 0;
113 | }
114 |
115 | pre {
116 | white-space: pre;
117 | margin: 0;
118 | padding: 12px 12px;
119 | font-size: 12px;
120 | line-height: 1.5;
121 | display: block;
122 | overflow: auto;
123 | color: #404040;
124 | background: #f3f3f3;
125 | }
126 |
127 | pre code.hljs {
128 | border: none;
129 | background: inherit;
130 | }
131 |
132 | /*
133 | Atom One Light by Daniel Gamage
134 | Original One Light Syntax theme from https://github.com/atom/one-light-syntax
135 | base: #fafafa
136 | mono-1: #383a42
137 | mono-2: #686b77
138 | mono-3: #a0a1a7
139 | hue-1: #0184bb
140 | hue-2: #4078f2
141 | hue-3: #a626a4
142 | hue-4: #50a14f
143 | hue-5: #e45649
144 | hue-5-2: #c91243
145 | hue-6: #986801
146 | hue-6-2: #c18401
147 | */
148 |
149 | .hljs {
150 | display: block;
151 | overflow-x: auto;
152 | padding: 0.5em;
153 | color: #383a42;
154 | background: #fafafa;
155 | }
156 |
157 | .hljs-comment,
158 | .hljs-quote {
159 | color: #a0a1a7;
160 | font-style: italic;
161 | }
162 |
163 | .hljs-doctag,
164 | .hljs-keyword,
165 | .hljs-formula {
166 | color: #a626a4;
167 | }
168 |
169 | .hljs-section,
170 | .hljs-name,
171 | .hljs-selector-tag,
172 | .hljs-deletion,
173 | .hljs-subst {
174 | color: #e45649;
175 | }
176 |
177 | .hljs-literal {
178 | color: #0184bb;
179 | }
180 |
181 | .hljs-string,
182 | .hljs-regexp,
183 | .hljs-addition,
184 | .hljs-attribute,
185 | .hljs-meta-string {
186 | color: #50a14f;
187 | }
188 |
189 | .hljs-built_in,
190 | .hljs-class .hljs-title {
191 | color: #c18401;
192 | }
193 |
194 | .hljs-attr,
195 | .hljs-variable,
196 | .hljs-template-variable,
197 | .hljs-type,
198 | .hljs-selector-class,
199 | .hljs-selector-attr,
200 | .hljs-selector-pseudo,
201 | .hljs-number {
202 | color: #986801;
203 | }
204 |
205 | .hljs-symbol,
206 | .hljs-bullet,
207 | .hljs-link,
208 | .hljs-meta,
209 | .hljs-selector-id,
210 | .hljs-title {
211 | color: #4078f2;
212 | }
213 |
214 | .hljs-emphasis {
215 | font-style: italic;
216 | }
217 |
218 | .hljs-strong {
219 | font-weight: bold;
220 | }
221 |
222 | .hljs-link {
223 | text-decoration: underline;
224 | }
225 |
226 | .dark .content {
227 | background: none;
228 | }
229 | .dark code {
230 | background: none;
231 | color: #e09393;
232 | }
233 | .dark .menu ul.list li.chapter a.active {
234 | color: #ffde00;
235 | }
236 | .dark .menu {
237 | background: #272525;
238 | }
239 |
--------------------------------------------------------------------------------
/documentation/styles/prism.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.24.0
2 | https://prismjs.com/download.html?#themes=prism-okaidia&languages=markup+css+clike+javascript+apacheconf+aspnet+bash+c+csharp+cpp+coffeescript+dart+docker+elm+git+go+graphql+handlebars+haskell+http+ignore+java+json+kotlin+less+markdown+markup-templating+nginx+php+powershell+ruby+rust+sass+scss+sql+swift+typescript+wasm+yaml&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard */
3 | /**
4 | * okaidia theme for JavaScript, CSS and HTML
5 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/
6 | * @author ocodia
7 | */
8 |
9 | code[class*='language-'],
10 | pre[class*='language-'] {
11 | color: #f8f8f2;
12 | background: none;
13 | text-shadow: 0 1px rgba(0, 0, 0, 0.3);
14 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
15 | font-size: 1em;
16 | text-align: left;
17 | white-space: pre;
18 | word-spacing: normal;
19 | word-break: normal;
20 | word-wrap: normal;
21 | line-height: 1.5;
22 |
23 | -moz-tab-size: 4;
24 | -o-tab-size: 4;
25 | tab-size: 4;
26 |
27 | -webkit-hyphens: none;
28 | -moz-hyphens: none;
29 | -ms-hyphens: none;
30 | hyphens: none;
31 | }
32 |
33 | /* Code blocks */
34 | pre[class*='language-'] {
35 | padding: 1em;
36 | margin: 0.5em 0;
37 | overflow: auto;
38 | border-radius: 0.3em;
39 | }
40 |
41 | :not(pre) > code[class*='language-'],
42 | pre[class*='language-'] {
43 | background: #272822;
44 | }
45 |
46 | /* Inline code */
47 | :not(pre) > code[class*='language-'] {
48 | padding: 0.1em;
49 | border-radius: 0.3em;
50 | white-space: normal;
51 | }
52 |
53 | .token.comment,
54 | .token.prolog,
55 | .token.doctype,
56 | .token.cdata {
57 | color: #8292a2;
58 | }
59 |
60 | .token.punctuation {
61 | color: #f8f8f2;
62 | }
63 |
64 | .token.namespace {
65 | opacity: 0.7;
66 | }
67 |
68 | .token.property,
69 | .token.tag,
70 | .token.constant,
71 | .token.symbol,
72 | .token.deleted {
73 | color: #f92672;
74 | }
75 |
76 | .token.boolean,
77 | .token.number {
78 | color: #ae81ff;
79 | }
80 |
81 | .token.selector,
82 | .token.attr-name,
83 | .token.string,
84 | .token.char,
85 | .token.builtin,
86 | .token.inserted {
87 | color: #a6e22e;
88 | }
89 |
90 | .token.operator,
91 | .token.entity,
92 | .token.url,
93 | .language-css .token.string,
94 | .style .token.string,
95 | .token.variable {
96 | color: #f8f8f2;
97 | }
98 |
99 | .token.atrule,
100 | .token.attr-value,
101 | .token.function,
102 | .token.class-name {
103 | color: #e6db74;
104 | }
105 |
106 | .token.keyword {
107 | color: #66d9ef;
108 | }
109 |
110 | .token.regex,
111 | .token.important {
112 | color: #fd971f;
113 | }
114 |
115 | .token.important,
116 | .token.bold {
117 | font-weight: bold;
118 | }
119 | .token.italic {
120 | font-style: italic;
121 | }
122 |
123 | .token.entity {
124 | cursor: help;
125 | }
126 |
127 | pre[data-line] {
128 | position: relative;
129 | padding: 1em 0 1em 3em;
130 | }
131 |
132 | .line-highlight {
133 | position: absolute;
134 | left: 0;
135 | right: 0;
136 | padding: inherit 0;
137 | margin-top: 1em; /* Same as .prism’s padding-top */
138 |
139 | background: hsla(24, 20%, 50%, 0.08);
140 | background: linear-gradient(to right, hsla(24, 20%, 50%, 0.1) 70%, hsla(24, 20%, 50%, 0));
141 |
142 | pointer-events: none;
143 |
144 | line-height: inherit;
145 | white-space: pre;
146 | }
147 |
148 | @media print {
149 | .line-highlight {
150 | /*
151 | * This will prevent browsers from replacing the background color with white.
152 | * It's necessary because the element is layered on top of the displayed code.
153 | */
154 | -webkit-print-color-adjust: exact;
155 | color-adjust: exact;
156 | }
157 | }
158 |
159 | .line-highlight:before,
160 | .line-highlight[data-end]:after {
161 | content: attr(data-start);
162 | position: absolute;
163 | top: 0.4em;
164 | left: 0.6em;
165 | min-width: 1em;
166 | padding: 0 0.5em;
167 | background-color: hsla(24, 20%, 50%, 0.4);
168 | color: hsl(24, 20%, 95%);
169 | font: bold 65%/1.5 sans-serif;
170 | text-align: center;
171 | vertical-align: 0.3em;
172 | border-radius: 999px;
173 | text-shadow: none;
174 | box-shadow: 0 1px white;
175 | }
176 |
177 | .line-highlight[data-end]:after {
178 | content: attr(data-end);
179 | top: auto;
180 | bottom: 0.4em;
181 | }
182 |
183 | .line-numbers .line-highlight:before,
184 | .line-numbers .line-highlight:after {
185 | content: none;
186 | }
187 |
188 | pre[id].linkable-line-numbers span.line-numbers-rows {
189 | pointer-events: all;
190 | }
191 | pre[id].linkable-line-numbers span.line-numbers-rows > span:before {
192 | cursor: pointer;
193 | }
194 | pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before {
195 | background-color: rgba(128, 128, 128, 0.2);
196 | }
197 |
198 | pre[class*='language-'].line-numbers {
199 | position: relative;
200 | padding-left: 3.8em;
201 | counter-reset: linenumber;
202 | }
203 |
204 | pre[class*='language-'].line-numbers > code {
205 | position: relative;
206 | white-space: inherit;
207 | }
208 |
209 | .line-numbers .line-numbers-rows {
210 | position: absolute;
211 | pointer-events: none;
212 | top: 0;
213 | font-size: 100%;
214 | left: -3.8em;
215 | width: 3em; /* works for line-numbers below 1000 lines */
216 | letter-spacing: -1px;
217 | border-right: 1px solid #999;
218 |
219 | -webkit-user-select: none;
220 | -moz-user-select: none;
221 | -ms-user-select: none;
222 | user-select: none;
223 | }
224 |
225 | .line-numbers-rows > span {
226 | display: block;
227 | counter-increment: linenumber;
228 | }
229 |
230 | .line-numbers-rows > span:before {
231 | content: counter(linenumber);
232 | color: #999;
233 | display: block;
234 | padding-right: 0.8em;
235 | text-align: right;
236 | }
237 |
238 | div.code-toolbar {
239 | position: relative;
240 | }
241 |
242 | div.code-toolbar > .toolbar {
243 | position: absolute;
244 | top: 0.3em;
245 | right: 0.2em;
246 | transition: opacity 0.3s ease-in-out;
247 | opacity: 0;
248 | }
249 |
250 | div.code-toolbar:hover > .toolbar {
251 | opacity: 1;
252 | }
253 |
254 | /* Separate line b/c rules are thrown out if selector is invalid.
255 | IE11 and old Edge versions don't support :focus-within. */
256 | div.code-toolbar:focus-within > .toolbar {
257 | opacity: 1;
258 | }
259 |
260 | div.code-toolbar > .toolbar .toolbar-item {
261 | display: inline-block;
262 | }
263 |
264 | div.code-toolbar > .toolbar a {
265 | cursor: pointer;
266 | }
267 |
268 | div.code-toolbar > .toolbar button {
269 | background: none;
270 | border: 0;
271 | color: inherit;
272 | font: inherit;
273 | line-height: normal;
274 | overflow: visible;
275 | padding: 0;
276 | -webkit-user-select: none; /* for button */
277 | -moz-user-select: none;
278 | -ms-user-select: none;
279 | }
280 |
281 | div.code-toolbar > .toolbar a,
282 | div.code-toolbar > .toolbar button,
283 | div.code-toolbar > .toolbar span {
284 | color: #bbb;
285 | font-size: 0.8em;
286 | padding: 0 0.5em;
287 | background: #f5f2f0;
288 | background: rgba(224, 224, 224, 0.2);
289 | box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2);
290 | border-radius: 0.5em;
291 | }
292 |
293 | div.code-toolbar > .toolbar a:hover,
294 | div.code-toolbar > .toolbar a:focus,
295 | div.code-toolbar > .toolbar button:hover,
296 | div.code-toolbar > .toolbar button:focus,
297 | div.code-toolbar > .toolbar span:hover,
298 | div.code-toolbar > .toolbar span:focus {
299 | color: inherit;
300 | text-decoration: none;
301 | }
302 |
--------------------------------------------------------------------------------
/documentation/styles/readthedocs.css:
--------------------------------------------------------------------------------
1 | .navbar-default {
2 | background: #2980b9;
3 | border: none;
4 | }
5 |
6 | .navbar-default .navbar-brand {
7 | color: #fcfcfc;
8 | }
9 |
10 | .menu {
11 | background: #343131;
12 | color: #fcfcfc;
13 | }
14 |
15 | .menu ul.list li a {
16 | color: #fcfcfc;
17 | }
18 |
19 | .menu ul.list li.title {
20 | background: #2980b9;
21 | padding-bottom: 5px;
22 | }
23 |
24 | .menu ul.list li:nth-child(2) {
25 | margin-top: 0;
26 | }
27 |
28 | .menu ul.list li.chapter a,
29 | .menu ul.list li.chapter .simple {
30 | color: #555;
31 | text-transform: uppercase;
32 | text-decoration: none;
33 | }
34 |
35 | .menu ul.list li.chapter ul.links a {
36 | color: #b3b3b3;
37 | text-transform: none;
38 | padding-left: 35px;
39 | }
40 |
41 | .menu ul.list li.chapter ul.links a:hover {
42 | background: #4e4a4a;
43 | }
44 |
45 | .menu ul.list li.chapter a.active,
46 | .menu ul.list li.chapter ul.links a.active {
47 | color: #0099e5;
48 | }
49 |
50 | .menu ul.list li.chapter ul.links {
51 | padding-left: 0;
52 | }
53 |
54 | .menu ul.list li.divider {
55 | background: rgba(255, 255, 255, 0.07);
56 | }
57 |
58 | #book-search-input input,
59 | #book-search-input input:focus,
60 | #book-search-input input:hover {
61 | color: #949494;
62 | }
63 |
64 | .copyright {
65 | color: #b3b3b3;
66 | background: #272525;
67 | }
68 |
69 | .content {
70 | background: #fcfcfc;
71 | }
72 |
73 | .content a {
74 | color: #2980b9;
75 | }
76 |
77 | .content a:hover {
78 | color: #3091d1;
79 | }
80 |
81 | .content a:visited {
82 | color: #9b59b6;
83 | }
84 |
85 | .menu ul.list li:nth-last-child(2) {
86 | background: none;
87 | }
88 |
89 | code {
90 | white-space: nowrap;
91 | max-width: 100%;
92 | background: #fff;
93 | padding: 2px 5px;
94 | color: #e74c3c;
95 | overflow-x: auto;
96 | border-radius: 0;
97 | }
98 |
99 | pre {
100 | white-space: pre;
101 | margin: 0;
102 | padding: 12px 12px;
103 | font-size: 12px;
104 | line-height: 1.5;
105 | display: block;
106 | overflow: auto;
107 | color: #404040;
108 | background: rgba(238, 238, 238, 0.35);
109 | }
110 |
111 | .dark .content {
112 | background: none;
113 | }
114 | .dark code {
115 | background: none;
116 | color: #e09393;
117 | }
118 |
--------------------------------------------------------------------------------
/documentation/styles/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html,
7 | body,
8 | div,
9 | span,
10 | applet,
11 | object,
12 | iframe,
13 | h1,
14 | h2,
15 | h3,
16 | h4,
17 | h5,
18 | h6,
19 | p,
20 | blockquote,
21 | pre,
22 | a,
23 | abbr,
24 | acronym,
25 | address,
26 | big,
27 | cite,
28 | code,
29 | del,
30 | dfn,
31 | em,
32 | img,
33 | ins,
34 | kbd,
35 | q,
36 | s,
37 | samp,
38 | small,
39 | strike,
40 | strong,
41 | sub,
42 | sup,
43 | tt,
44 | var,
45 | b,
46 | u,
47 | i,
48 | center,
49 | dl,
50 | dt,
51 | dd,
52 | ol,
53 | ul,
54 | li,
55 | fieldset,
56 | form,
57 | label,
58 | legend,
59 | table,
60 | caption,
61 | tbody,
62 | tfoot,
63 | thead,
64 | tr,
65 | th,
66 | td,
67 | article,
68 | aside,
69 | canvas,
70 | details,
71 | embed,
72 | figure,
73 | figcaption,
74 | footer,
75 | header,
76 | hgroup,
77 | menu,
78 | nav,
79 | output,
80 | ruby,
81 | section,
82 | summary,
83 | time,
84 | mark,
85 | audio,
86 | video {
87 | margin: 0;
88 | padding: 0;
89 | border: 0;
90 | font: inherit;
91 | font-size: 100%;
92 | vertical-align: baseline;
93 | }
94 | /* HTML5 display-role reset for older browsers */
95 | article,
96 | aside,
97 | details,
98 | figcaption,
99 | figure,
100 | footer,
101 | header,
102 | hgroup,
103 | menu,
104 | nav,
105 | section {
106 | display: block;
107 | }
108 | body {
109 | line-height: 1;
110 | }
111 | ol,
112 | ul {
113 | list-style: none;
114 | }
115 | blockquote,
116 | q {
117 | quotes: none;
118 | }
119 | blockquote:before,
120 | blockquote:after,
121 | q:before,
122 | q:after {
123 | content: '';
124 | content: none;
125 | }
126 | table {
127 | border-collapse: collapse;
128 | border-spacing: 0;
129 | }
130 |
--------------------------------------------------------------------------------
/documentation/styles/stripe.css:
--------------------------------------------------------------------------------
1 | .navbar-default .navbar-brand {
2 | color: #0099e5;
3 | }
4 |
5 | .menu ul.list li a[data-type='chapter-link'],
6 | .menu ul.list li.chapter .simple {
7 | color: #939da3;
8 | text-transform: uppercase;
9 | }
10 |
11 | .content h1,
12 | .content h2,
13 | .content h3,
14 | .content h4,
15 | .content h5 {
16 | color: #292e31;
17 | font-weight: normal;
18 | }
19 |
20 | .content {
21 | color: #4c555a;
22 | }
23 |
24 | .menu ul.list li.title {
25 | padding: 5px 0;
26 | }
27 |
28 | a {
29 | color: #0099e5;
30 | text-decoration: none;
31 | }
32 | a:hover {
33 | color: #292e31;
34 | text-decoration: none;
35 | }
36 |
37 | .menu ul.list li:nth-child(2) {
38 | margin-top: 0;
39 | }
40 |
41 | .menu ul.list li.title a,
42 | .navbar a {
43 | color: #0099e5;
44 | text-decoration: none;
45 | font-size: 16px;
46 | }
47 |
48 | .menu ul.list li a.active {
49 | color: #0099e5;
50 | }
51 |
52 | code {
53 | box-sizing: border-box;
54 | display: inline-block;
55 | padding: 0 5px;
56 | background: #fafcfc;
57 | border-radius: 4px;
58 | color: #b93d6a;
59 | font-size: 13px;
60 | line-height: 20px;
61 | }
62 |
63 | pre {
64 | margin: 0;
65 | padding: 12px 12px;
66 | background: #272b2d;
67 | border-radius: 5px;
68 | font-size: 13px;
69 | line-height: 1.5em;
70 | font-weight: 500;
71 | }
72 |
73 | .dark body {
74 | color: #fafafa;
75 | }
76 | .dark .content h1,
77 | .dark .content h2,
78 | .dark .content h3,
79 | .dark .content h4,
80 | .dark .content h5 {
81 | color: #fafafa;
82 | }
83 |
84 | .dark code {
85 | background: none;
86 | }
87 |
88 | .dark .content {
89 | color: #fafafa;
90 | }
91 |
92 | .dark .menu ul.list li a[data-type='chapter-link'],
93 | .dark .menu ul.list li.chapter .simple {
94 | color: #fafafa;
95 | }
96 |
97 | .dark .menu ul.list li.title a {
98 | color: #fafafa;
99 | }
100 |
101 | .dark .menu ul.list li a {
102 | color: #fafafa;
103 | }
104 | .dark .menu ul.list li a.active {
105 | color: #7fc9ff;
106 | }
107 |
--------------------------------------------------------------------------------
/documentation/styles/style.css:
--------------------------------------------------------------------------------
1 | @import "./reset.css";
2 | @import "./bootstrap.min.css";
3 | @import "./bootstrap-card.css";
4 | @import "./prism.css";
5 | @import "./ionicons.min.css";
6 | @import "./compodoc.css";
7 | @import "./tablesort.css";
8 |
--------------------------------------------------------------------------------
/documentation/styles/tablesort.css:
--------------------------------------------------------------------------------
1 | th[role=columnheader]:not(.no-sort) {
2 | cursor: pointer;
3 | }
4 |
5 | th[role=columnheader]:not(.no-sort):after {
6 | content: '';
7 | float: right;
8 | margin-top: 7px;
9 | border-width: 0 4px 4px;
10 | border-style: solid;
11 | border-color: #404040 transparent;
12 | visibility: visible;
13 | opacity: 1;
14 | -ms-user-select: none;
15 | -webkit-user-select: none;
16 | -moz-user-select: none;
17 | user-select: none;
18 | }
19 |
20 | th[aria-sort=ascending]:not(.no-sort):after {
21 | border-bottom: none;
22 | border-width: 4px 4px 0;
23 | }
24 |
25 | th[aria-sort]:not(.no-sort):after {
26 | visibility: visible;
27 | opacity: 0.4;
28 | }
29 |
30 | th[role=columnheader]:not(.no-sort):hover:after {
31 | visibility: visible;
32 | opacity: 1;
33 | }
34 |
--------------------------------------------------------------------------------
/documentation/styles/vagrant.css:
--------------------------------------------------------------------------------
1 | .navbar-default .navbar-brand {
2 | background: white;
3 | color: #8d9ba8;
4 | }
5 |
6 | .menu .list {
7 | background: #0c5593;
8 | }
9 |
10 | .menu .chapter {
11 | padding: 0 20px;
12 | }
13 |
14 | .menu ul.list li a[data-type='chapter-link'],
15 | .menu ul.list li.chapter .simple {
16 | color: white;
17 | text-transform: uppercase;
18 | border-bottom: 1px solid rgba(255, 255, 255, 0.4);
19 | }
20 |
21 | .content h1,
22 | .content h2,
23 | .content h3,
24 | .content h4,
25 | .content h5 {
26 | color: #292e31;
27 | font-weight: normal;
28 | }
29 |
30 | .content {
31 | color: #4c555a;
32 | }
33 |
34 | a {
35 | color: #0094bf;
36 | text-decoration: underline;
37 | }
38 | a:hover {
39 | color: #f1362f;
40 | }
41 |
42 | .menu ul.list li.title {
43 | background: white;
44 | padding-bottom: 5px;
45 | }
46 |
47 | .menu ul.list li:nth-child(2) {
48 | margin-top: 0;
49 | }
50 |
51 | .menu ul.list li:nth-last-child(2) {
52 | background: none;
53 | }
54 |
55 | .menu ul.list li.title a {
56 | padding: 10px 15px;
57 | }
58 |
59 | .menu ul.list li.title a,
60 | .navbar a {
61 | color: #8d9ba8;
62 | text-decoration: none;
63 | font-size: 16px;
64 | font-weight: 300;
65 | }
66 |
67 | .menu ul.list li a {
68 | color: white;
69 | padding: 10px;
70 | font-weight: 300;
71 | text-decoration: none;
72 | }
73 | .menu ul.list li a.active {
74 | color: white;
75 | font-weight: bold;
76 | }
77 |
78 | .copyright {
79 | color: white;
80 | background: #000;
81 | }
82 |
83 | code {
84 | box-sizing: border-box;
85 | display: inline-block;
86 | padding: 0 5px;
87 | background: rgba(0, 148, 191, 0.1);
88 | border-radius: 3px;
89 | color: #0094bf;
90 | font-size: 13px;
91 | line-height: 20px;
92 | }
93 |
94 | pre {
95 | margin: 0;
96 | padding: 12px 12px;
97 | background: rgba(238, 238, 238, 0.35);
98 | border-radius: 3px;
99 | font-size: 13px;
100 | line-height: 1.5em;
101 | font-weight: 500;
102 | }
103 |
104 | .dark body {
105 | color: #fafafa;
106 | }
107 | .dark .content h1,
108 | .dark .content h2,
109 | .dark .content h3,
110 | .dark .content h4,
111 | .dark .content h5 {
112 | color: #fafafa;
113 | }
114 |
115 | .dark code {
116 | background: none;
117 | }
118 |
119 | .dark .content {
120 | color: #fafafa;
121 | }
122 |
123 | .dark .menu ul.list li.title a,
124 | .dark .navbar a {
125 | color: #8d9ba8;
126 | }
127 |
128 | .dark .menu ul.list li a {
129 | color: #fafafa;
130 | }
131 |
--------------------------------------------------------------------------------
/input.example.log:
--------------------------------------------------------------------------------
1 | 2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}
2 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
3 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}
4 | 2021-08-09T02:12:51.255Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is started"}
5 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request the user information","userId": 16}
6 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"User information is gathered","user":{"id":10,"name":"Alice"}}
7 | 2021-08-09T02:12:51.258Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request user orders list","userId":16}
8 | 2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}
9 | 2021-08-09T02:12:51.259Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user": {"id": 16, "name": "Michael"}}
10 | 2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}
11 | 2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}
12 | 2021-08-09T02:12:51.265Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is successfully finished"}
13 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node',
4 | roots: ['./'],
5 | transform: { '\\.ts$': ['ts-jest'] },
6 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec|e2e-spec))\\.tsx?$',
7 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
8 | globals: {
9 | 'ts-jest': {
10 | tsconfig: {
11 | // allow js in typescript
12 | allowJs: true,
13 | },
14 | },
15 | },
16 | coverageProvider: 'v8',
17 | collectCoverageFrom: [
18 | 'src/**/*.ts',
19 | '!src/main.ts',
20 | '!src/**/*.config.ts',
21 | '!src/application/controllers/*',
22 | '!src/application/interceptors/*',
23 | '!src/domain/entities/**',
24 | '!src/domain/interfaces/*',
25 | '!src/domain/modules/*',
26 | '!src/infrastructure/**',
27 | ],
28 | coverageThreshold: {
29 | global: {
30 | lines: 70,
31 | statements: 70,
32 | },
33 | },
34 | };
35 |
36 |
--------------------------------------------------------------------------------
/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src"
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parser",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json",
22 | "doc": "./node_modules/.bin/compodoc -p tsconfig.compodoc.json -w -s -r 7000 --theme 'Stripe'"
23 | },
24 | "dependencies": {
25 | "@compodoc/compodoc": "^1.1.19",
26 | "@nestjs/common": "^8.0.0",
27 | "@nestjs/core": "^8.0.0",
28 | "@nestjs/platform-express": "^8.0.0",
29 | "class-transformer": "^0.5.1",
30 | "class-validator": "^0.13.2",
31 | "@types/faker": "^5.1.4",
32 | "nest-winston": "^1.6.2",
33 | "nestjs-command": "^3.1.1",
34 | "reflect-metadata": "^0.1.13",
35 | "rimraf": "^3.0.2",
36 | "rxjs": "^7.2.0",
37 | "faker": "^5.1.0",
38 | "winston": "^3.7.2",
39 | "yargs": "^17.5.1"
40 | },
41 | "devDependencies": {
42 | "@nestjs/cli": "^8.0.0",
43 | "@nestjs/schematics": "^8.0.0",
44 | "@nestjs/testing": "^8.0.0",
45 | "@types/express": "^4.17.13",
46 | "@types/jest": "27.5.0",
47 | "@types/node": "^16.0.0",
48 | "@types/supertest": "^2.0.11",
49 | "@types/yargs": "^17.0.10",
50 | "@typescript-eslint/eslint-plugin": "^5.0.0",
51 | "@typescript-eslint/parser": "^5.0.0",
52 | "eslint": "^8.0.1",
53 | "eslint-config-prettier": "^8.3.0",
54 | "eslint-plugin-prettier": "^4.0.0",
55 | "jest": "28.0.3",
56 | "prettier": "^2.3.2",
57 | "source-map-support": "^0.5.20",
58 | "supertest": "^6.1.3",
59 | "ts-jest": "28.0.1",
60 | "ts-loader": "^9.2.3",
61 | "ts-node": "^10.0.0",
62 | "tsconfig-paths": "4.0.0",
63 | "typescript": "^4.3.5"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/scripts/runner.sh:
--------------------------------------------------------------------------------
1 | npm install
2 | npm run build
3 | npm test
4 | npm run lint
5 | echo 'Done! 😍'
6 | echo 'now you can use the application by following commmand'
7 | echo 'node dist/cli.js -h'
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { CommandModule } from 'nestjs-command';
3 | import { ParserModule } from '../parser/parser.module';
4 |
5 | @Module({
6 | imports: [CommandModule, ParserModule],
7 | providers: [],
8 | })
9 | export class AppModule {}
10 |
--------------------------------------------------------------------------------
/src/cli.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { CommandModule, CommandService } from 'nestjs-command';
3 | import { AppModule } from './app/app.module';
4 |
5 | /**
6 | * Main application entry point
7 | */
8 | async function bootstrap() {
9 | const app = await NestFactory.createApplicationContext(AppModule, {
10 | logger: ['error'],
11 | });
12 |
13 | try {
14 | await app.select(CommandModule).get(CommandService).exec();
15 | await app.close();
16 | } catch (error) {
17 | console.error(error);
18 | await app.close();
19 | process.exit(1);
20 | }
21 | }
22 | /**
23 | * Bootstraps the application
24 | */
25 | bootstrap();
26 |
--------------------------------------------------------------------------------
/src/parser/command/parser.command.ts:
--------------------------------------------------------------------------------
1 | import { Command, Option } from 'nestjs-command';
2 | import { Injectable } from '@nestjs/common';
3 | import { ParserService } from '../service/parser.service';
4 | import { ParserCommandDTO } from '../dtos/parser-command-dto';
5 | import { validateDTO } from '../common';
6 |
7 | /**
8 | * Log parser command
9 | */
10 | @Injectable()
11 | export class ParserCommand {
12 | /**
13 | * Constructs the Log parser command class
14 | * @param parserService Injection of parser service
15 | */
16 | constructor(private readonly parserService: ParserService) {}
17 |
18 | /**
19 | * Parser command that takes the input log file, parses and writes the result to the output file as ajson content.
20 | * @param input address of the input file
21 | * @param output address of the output file
22 | * @param log_level log level to be filtered
23 | * @returns LogModel[]
24 | */
25 | @Command({
26 | command: '*',
27 | describe: 'parses a log file',
28 | })
29 | async parse(
30 | @Option({
31 | name: 'input',
32 | describe: 'input log file (ex: "input.log")',
33 | type: 'string',
34 | alias: 'i',
35 | required: true,
36 | })
37 | input: string,
38 | @Option({
39 | name: 'output',
40 | describe: 'output log file (ex: "output.log")',
41 | type: 'string',
42 | alias: 'o',
43 | default: 'output.log',
44 | required: true,
45 | })
46 | output: string,
47 | @Option({
48 | name: 'log-level',
49 | describe: 'log-level (ex: "error,[error,debug,warn,info]")',
50 | type: 'string',
51 | alias: 'l',
52 | default: 'error',
53 | required: false,
54 | })
55 | log_level: string,
56 | ) {
57 | try {
58 | const logFilter = log_level.split(',');
59 | const command = new ParserCommandDTO({
60 | input: input,
61 | output: output,
62 | logLevel: logFilter,
63 | });
64 | await validateDTO(command);
65 | return this.parserService
66 | .parse(command)
67 | .then(() => {
68 | console.log(`Success 😀. output is written in ${output}`);
69 | })
70 | .catch((error) => {
71 | console.error(error);
72 | });
73 | } catch (error) {
74 | console.log(error);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/parser/common/index.ts:
--------------------------------------------------------------------------------
1 | export * from './utils';
2 |
--------------------------------------------------------------------------------
/src/parser/common/utils.ts:
--------------------------------------------------------------------------------
1 | import { validate } from 'class-validator';
2 |
3 | /**
4 | * validates dto and returns bad request if it is wrong
5 | * @param dto dto
6 | * @param httpResponseGenerator http response service
7 | */
8 | export async function validateDTO(dto: any): Promise {
9 | const errors = await validate(dto);
10 |
11 | if (errors.length) throw new Error(`InvalidArgumentExcpetion ${errors}`);
12 |
13 | return dto;
14 | }
15 |
--------------------------------------------------------------------------------
/src/parser/dtos/parser-command-dto.ts:
--------------------------------------------------------------------------------
1 | import {
2 | IsDefined,
3 | IsEnum,
4 | IsNotEmpty,
5 | IsOptional,
6 | IsString,
7 | } from 'class-validator';
8 | import { LogLevel } from '../enum';
9 |
10 | /**
11 | * list of allowed properties
12 | */
13 | const allowedProperties = ['input', 'output', 'logLevel'];
14 | /**
15 | * Log parser command DTO
16 | */
17 | export class ParserCommandDTO {
18 | /**
19 | * addres of the log file input
20 | */
21 | @IsNotEmpty()
22 | @IsDefined()
23 | @IsString()
24 | input: string;
25 | //...........................................................................................................
26 | /**
27 | * address of the output log file
28 | */
29 | @IsNotEmpty()
30 | @IsDefined()
31 | @IsString()
32 | output: string;
33 | //...........................................................................................................
34 | /**
35 | * list of log levels to be filtered by the parser
36 | */
37 | @IsOptional()
38 | @IsEnum(LogLevel, { each: true })
39 | logLevel: LogLevel[];
40 | //...........................................................................................................
41 | /**
42 | * Constructs the DTO based on given properties
43 | * @param properties list of passed properties to the DTO
44 | */
45 | constructor(properties: any = {}) {
46 | Object.keys(properties).forEach((key: string) => {
47 | if (allowedProperties.includes(key))
48 | this[key as keyof this] = properties[key];
49 | });
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/parser/enum/index.ts:
--------------------------------------------------------------------------------
1 | export * from './log-level.enum';
2 |
--------------------------------------------------------------------------------
/src/parser/enum/log-level.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * An enum that represents the log levels the parser understands
3 | */
4 | export enum LogLevel {
5 | /**
6 | * Error log level
7 | */
8 | ERROR = 'error',
9 | /**
10 | * Info log level
11 | */
12 | INFO = 'info',
13 | /**
14 | * Warning log level
15 | */
16 | WARN = 'warn',
17 | /**
18 | * Debug log level
19 | */
20 | DEBUG = 'debug',
21 | }
22 |
--------------------------------------------------------------------------------
/src/parser/helper/file-helper.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, NotAcceptableException, Logger } from '@nestjs/common';
2 | import * as fs from 'fs';
3 | import * as rd from 'readline';
4 | import { Observable, of } from 'rxjs';
5 | /**
6 | * File helper class
7 | */
8 | @Injectable()
9 | export class FileHelper {
10 | //=======================================================================================================================================================================
11 | /**
12 | * Reads the input log file
13 | * @param path Address of the file to be red
14 | * @param filter Log level filter (An array of log levels)
15 | * @returns Promise>>
16 | */
17 | async readLogFile(
18 | path: string,
19 | filter: string[],
20 | ): Promise>> {
21 | return new Promise((resolve, reject) => {
22 | try {
23 | const reader = rd.createInterface(fs.createReadStream(path));
24 | const data: Array = [];
25 | reader.on('line', async (line: string) => {
26 | try {
27 | const log = await this.parsLog(line, filter);
28 | if (log) data.push(log);
29 | } catch (error) {
30 | Logger.warn(`Illigal format on line ${line}`);
31 | }
32 | });
33 | reader.on('close', () => {
34 | resolve(of(data));
35 | });
36 | } catch (error) {
37 | Logger.error(`file not readable or it does not exists`);
38 | reject(error);
39 | }
40 | });
41 | }
42 | //=======================================================================================================================================================================
43 | /**
44 | * Writes the given data (Parsed log json array) to the output log file
45 | * @param path address of the out put parsed log file
46 | * @param data data to be written inside the output log file
47 | * @returns Promise
48 | */
49 | async writeLogFile(path, data: T[]): Promise {
50 | return new Promise(function (resolve, reject) {
51 | fs.writeFile(path, JSON.stringify(data, null, 2), function (err) {
52 | if (err) reject(err);
53 | else resolve(data);
54 | });
55 | });
56 | }
57 | //=======================================================================================================================================================================
58 | /**
59 | * parses a given log information according to the log level (it uses different regex patterns to find desired parts of the log info)
60 | * @param log log to be parsed
61 | * @param filter Log level filter (An array of log levels)
62 | * @returns Promise
63 | */
64 | async parsLog(log: string, filter: string[]): Promise {
65 | try {
66 | const log_level: string = log
67 | .match('\\s-\\s\\w+\\s-\\s')[0]
68 | .replace(/\s-\s/g, '');
69 | if (!filter.includes(log_level) && filter.length > 0) return;
70 | const time_stamp = new Date(
71 | log.match(
72 | '[0-9]{1,4}-[0-9]{1,2}-[0-9]{1,2}[A-Z][0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}.[0-9]{1,3}[A-Z]',
73 | )?.[0],
74 | ).getTime();
75 | const log_info = JSON.parse(log.match('{(?:)(.*)}')[0]);
76 | const transaction_id = log_info.transactionId;
77 | const err = log_info.details;
78 | return {
79 | timestamp: time_stamp,
80 | logLevel: log_level,
81 | transactionId: transaction_id,
82 | err: err,
83 | };
84 | } catch (error) {
85 | throw new NotAcceptableException(error);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/parser/helper/index.ts:
--------------------------------------------------------------------------------
1 | export * from './file-helper';
2 |
--------------------------------------------------------------------------------
/src/parser/model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './log.model';
2 |
--------------------------------------------------------------------------------
/src/parser/model/log.model.ts:
--------------------------------------------------------------------------------
1 | import { LogLevel } from '../enum';
2 | /**
3 | * Log model (We generate the parsed log json objects based on this model)
4 | */
5 | export interface LogModel {
6 | /**
7 | * Timestamp of the log generated
8 | */
9 | timeStamp: Date;
10 | /**
11 | * level of the log (error,debug,warn,info)
12 | */
13 | logLevel: LogLevel;
14 | /**
15 | * transaction id of the log
16 | */
17 | transactionId: string;
18 | /**
19 | * error message of the log
20 | */
21 | err: string;
22 | }
23 |
--------------------------------------------------------------------------------
/src/parser/parser.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ParserCommand } from './command/parser.command';
3 | import { FileHelper } from './helper';
4 | import { ParserService } from './service/parser.service';
5 |
6 | /**
7 | * Parser module
8 | */
9 | @Module({
10 | imports: [],
11 | providers: [
12 | ParserCommand,
13 | ParserService,
14 | {
15 | provide: 'FILE_HELPER',
16 | useClass: FileHelper,
17 | },
18 | ],
19 | })
20 | export class ParserModule {}
21 |
--------------------------------------------------------------------------------
/src/parser/service/parser.service.ts:
--------------------------------------------------------------------------------
1 | import { Inject, Injectable, NotAcceptableException } from '@nestjs/common';
2 | import { FileHelper } from '../helper';
3 | import { take } from 'rxjs';
4 | import { LogModel } from '../model';
5 | import { ParserCommandDTO } from '../dtos/parser-command-dto';
6 |
7 | /**
8 | * Log parser service
9 | */
10 | @Injectable()
11 | export class ParserService {
12 | /**
13 | *Constructs the log parser service
14 | * @param file_helper file helper injection (useful to work with the log files) represented as a single tone class
15 | */
16 | constructor(
17 | @Inject('FILE_HELPER') private readonly file_helper: FileHelper,
18 | ) {}
19 | //==============================================================================================================
20 | /**
21 | * Parses the input log file based on the provided commands
22 | * @param command Command entered by the user (Comming from Command class)
23 | * @returns Promise
24 | */
25 | async parse(command: ParserCommandDTO): Promise {
26 | return new Promise(async (resolve, reject) => {
27 | try {
28 | (
29 | await this.file_helper.readLogFile(
30 | command.input,
31 | command.logLevel,
32 | )
33 | )
34 | .pipe(take(1))
35 | .subscribe(async (data: any) => {
36 | await this.file_helper.writeLogFile(command.output, data);
37 | resolve(data);
38 | });
39 | } catch (error) {
40 | reject(error);
41 | }
42 | }).catch((error) => {
43 | throw new NotAcceptableException(error);
44 | });
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/parser/service/test.log:
--------------------------------------------------------------------------------
1 | 2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}
2 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
3 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}
4 | 2021-08-09T02:12:51.255Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is started"}
5 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request the user information","userId": 16}
6 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"User information is gathered","user":{"id":10,"name":"Alice"}}
7 | 2021-08-09T02:12:51.258Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request user orders list","userId":16}
8 | 2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}
9 | 2021-08-09T02:12:51.259Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user": {"id": 16, "name": "Michael"}}
10 | 2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}
11 | 2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}
12 | 2021-08-09T02:12:51.265Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is successfully finished"}
13 |
--------------------------------------------------------------------------------
/test/integration-tests/factories/index.ts:
--------------------------------------------------------------------------------
1 | export * from './parser-command.factory';
2 |
--------------------------------------------------------------------------------
/test/integration-tests/factories/parser-command.factory.ts:
--------------------------------------------------------------------------------
1 | import { datatype } from 'faker';
2 | import * as path from 'path';
3 | export const FIXTURE_BASE_PATH = path.resolve(__dirname, '../fixtures');
4 | //=====================================================================================
5 | export const PARSE_COMMAND_INTEGRATION_TEST_CASE_1 = {
6 | data: {
7 | comman: '*',
8 | args: {
9 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
10 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
11 | 'log-level': 'debug',
12 | },
13 | },
14 | expectation: {
15 | should: 'should write parssed logs to the file',
16 | },
17 | };
18 | //=====================================================================================
19 | export const PARSE_COMMAND_INTEGRATION_TEST_CASE_2 = {
20 | data: {
21 | comman: '*',
22 | args: {
23 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
24 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
25 | 'log-level': 'error',
26 | },
27 | },
28 | expectation: {
29 | should: 'should write parssed logs to the file',
30 | },
31 | };
32 | //=====================================================================================
33 | export const PARSE_COMMAND_INTEGRATION_TEST_CASE_3 = {
34 | data: {
35 | comman: '*',
36 | args: {
37 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
38 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
39 | 'log-level': datatype.string(10),
40 | },
41 | },
42 | expectation: {
43 | should: 'should write parssed logs to the file',
44 | },
45 | };
46 |
--------------------------------------------------------------------------------
/test/integration-tests/fixtures/fixture-input.log:
--------------------------------------------------------------------------------
1 | 2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}
2 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
3 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}
4 | 2021-08-09T02:12:51.255Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is started"}
5 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request the user information","userId": 16}
6 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"User information is gathered","user":{"id":10,"name":"Alice"}}
7 | 2021-08-09T02:12:51.258Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request user orders list","userId":16}
8 | 2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}
9 | 2021-08-09T02:12:51.259Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user": {"id": 16, "name": "Michael"}}
10 | 2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}
11 | 2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}
12 | 2021-08-09T02:12:51.265Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is successfully finished"}
13 |
--------------------------------------------------------------------------------
/test/integration-tests/parser-command.spec.ts:
--------------------------------------------------------------------------------
1 | import { CommandModule, CommandModuleTest } from 'nestjs-command';
2 | import { AppModule } from '../../src/app/app.module';
3 | import { Test } from '@nestjs/testing';
4 | import {
5 | FIXTURE_BASE_PATH,
6 | PARSE_COMMAND_INTEGRATION_TEST_CASE_1,
7 | PARSE_COMMAND_INTEGRATION_TEST_CASE_2,
8 | PARSE_COMMAND_INTEGRATION_TEST_CASE_3,
9 | } from './factories';
10 | import * as fs from 'fs';
11 | describe('AppModule', () => {
12 | let commandModule: CommandModuleTest;
13 | let app;
14 | async function readFile(path: string): Promise {
15 | return new Promise(function (resolve, reject) {
16 | fs.readFile(path, 'utf-8', (err, data) => {
17 | if (err) {
18 | reject(err);
19 | } else {
20 | resolve(data);
21 | }
22 | });
23 | });
24 | }
25 |
26 | beforeEach(async () => {
27 | const moduleFixture = await Test.createTestingModule({
28 | imports: [AppModule],
29 | }).compile();
30 |
31 | app = moduleFixture.createNestApplication();
32 | await app.init();
33 | commandModule = new CommandModuleTest(app.select(CommandModule));
34 | });
35 | //===========================================================================================================
36 | it(PARSE_COMMAND_INTEGRATION_TEST_CASE_1.expectation.should, async () => {
37 | await commandModule.execute(
38 | PARSE_COMMAND_INTEGRATION_TEST_CASE_1.data.comman,
39 | PARSE_COMMAND_INTEGRATION_TEST_CASE_1.data.args,
40 | );
41 | const result = await readFile(FIXTURE_BASE_PATH + '/fixture-output.log');
42 | expect(JSON.parse(result).length).toBeGreaterThan(0);
43 | });
44 | //..........................................................................................................
45 | it(PARSE_COMMAND_INTEGRATION_TEST_CASE_2.expectation.should, async () => {
46 | await commandModule.execute(
47 | PARSE_COMMAND_INTEGRATION_TEST_CASE_2.data.comman,
48 | PARSE_COMMAND_INTEGRATION_TEST_CASE_2.data.args,
49 | );
50 | const result = await readFile(FIXTURE_BASE_PATH + '/fixture-output.log');
51 | expect(
52 | JSON.parse(result).filter(
53 | (log: { logLevel: string }) =>
54 | log.logLevel ==
55 | PARSE_COMMAND_INTEGRATION_TEST_CASE_2.data.args['log-level'],
56 | ).length,
57 | ).toBeGreaterThan(0);
58 | });
59 | //..........................................................................................................
60 | it(PARSE_COMMAND_INTEGRATION_TEST_CASE_3.expectation.should, async () => {
61 | try {
62 | await commandModule.execute(
63 | PARSE_COMMAND_INTEGRATION_TEST_CASE_3.data.comman,
64 | PARSE_COMMAND_INTEGRATION_TEST_CASE_3.data.args,
65 | );
66 | } catch (error) {
67 | expect(error).toBeDefined();
68 | }
69 | });
70 | afterAll(() => {
71 | fs.unlinkSync(FIXTURE_BASE_PATH + '/fixture-output.log');
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/test/unit-tests/factories/helper.factory.ts:
--------------------------------------------------------------------------------
1 | import { datatype } from 'faker';
2 |
3 | export const LOG_PARSER_TEST_CASE_1 = {
4 | data: `2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}`,
5 | logLevel: ['info'],
6 | expectation: {
7 | should:
8 | 'should return log object that matches the object in this test case ',
9 | value: {
10 | timestamp: 2354321571253,
11 | logLevel: 'info',
12 | transactionId: '9abc55b2-807b-4361-9dbe-aa88b1b2e978',
13 | err: 'Service is started',
14 | },
15 | },
16 | };
17 |
18 | export const LOG_PARSER_TEST_CASE_2 = {
19 | data: datatype.string(500),
20 | logLevel: ['info', 'error', 'debug', 'warn'],
21 | expectation: {
22 | should: 'should throw not acceptable exception ',
23 | },
24 | };
25 |
26 | export const LOG_PARSER_TEST_CASE_3 = {
27 | data: `2021-08-09T02:12:51.254Z - debug -`,
28 | logLevel: ['info', 'error', 'debug', 'warn'],
29 | expectation: {
30 | should: 'should throw not acceptable exception',
31 | },
32 | };
33 |
34 | export const LOG_PARSER_TEST_CASE_4 = {
35 | data: `2021-08-09T02:12:51. - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
36 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}`,
37 | logLevel: ['info', 'error', 'debug', 'warn'],
38 | expectation: {
39 | should: 'should throw not acceptable exception',
40 | },
41 | };
42 |
43 | export const LOG_PARSER_TEST_CASE_5 = {
44 | data: `2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}`,
45 | logLevel: [datatype.string(5)],
46 | expectation: {
47 | should:
48 | 'should return log object that matches the object in this test case ',
49 | value: undefined,
50 | },
51 | };
52 |
53 | export const LOG_PARSER_TEST_CASE_6 = {
54 | data: `2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}`,
55 | logLevel: ['debug'],
56 | expectation: {
57 | should: 'should contain a correct log level ',
58 | value: {
59 | logLevel: 'debug',
60 | },
61 | },
62 | };
63 |
64 | export const LOG_PARSER_TEST_CASE_7 = {
65 | data: `2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}`,
66 | logLevel: ['error'],
67 | expectation: {
68 | should: 'should contain a correct log level ',
69 | value: {
70 | logLevel: 'error',
71 | transactionId: '9abc55b2-807b-4361-9dbe-aa88b1b2e978',
72 | },
73 | },
74 | };
75 |
76 | export const LOG_PARSER_TEST_CASE_8 = {
77 | data: `2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}`,
78 | logLevel: ['error', 'warn'],
79 | expectation: {
80 | should: 'should contain a correct log level ',
81 | value: {
82 | logLevel: 'warn',
83 | transactionId: '9abc55b2-807b-4361-9dbe-aa88b1b2e978',
84 | err: 'Service finished with error',
85 | },
86 | },
87 | };
88 |
--------------------------------------------------------------------------------
/test/unit-tests/factories/index.ts:
--------------------------------------------------------------------------------
1 | export * from './parser.factory';
2 | export * from './helper.factory';
3 | export * from './utils.factory';
4 |
--------------------------------------------------------------------------------
/test/unit-tests/factories/parser.factory.ts:
--------------------------------------------------------------------------------
1 | import { datatype } from 'faker';
2 | import * as path from 'path';
3 |
4 | export const FIXTURE_BASE_PATH = path.resolve(__dirname, '../fixtures');
5 | //=====================================================================================
6 | export const PARSER_INPUT_TEST_CASE_1 = {
7 | data: {
8 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
9 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
10 | logLevel: ['error'],
11 | },
12 | expectation: {
13 | should: 'should return at least one log ',
14 | },
15 | };
16 | //=====================================================================================
17 | export const PARSER_INPUT_TEST_CASE_2 = {
18 | data: {
19 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
20 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
21 | logLevel: ['error', 'debug'],
22 | },
23 | expectation: {
24 | should: 'should return a list of logs and has debug and error inside ',
25 | },
26 | };
27 | //=====================================================================================
28 | export const PARSER_INPUT_TEST_CASE_3 = {
29 | data: {
30 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
31 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
32 | logLevel: ['unknown'],
33 | },
34 | expectation: {
35 | should: 'should return a list with 0 elements inside ',
36 | },
37 | };
38 | //=====================================================================================
39 | export const PARSER_INPUT_TEST_CASE_4 = {
40 | data: {
41 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
42 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
43 | logLevel: ['error', 'warn', 'debug'],
44 | },
45 | expectation: {
46 | should:
47 | 'should return a list of logs and has debug, warn and error inside ',
48 | },
49 | };
50 | //=====================================================================================
51 | export const PARSER_INPUT_TEST_CASE_5 = {
52 | data: {
53 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
54 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
55 | logLevel: ['error', 'warn', 'info', 'debug'],
56 | },
57 | expectation: {
58 | should:
59 | 'should return a list of logs and has debug, wanr, info and error inside ',
60 | },
61 | };
62 | //=====================================================================================
63 | export const PARSER_INPUT_TEST_CASE_6 = {
64 | data: {
65 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
66 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
67 | logLevel: [datatype.string(20)],
68 | },
69 | expectation: {
70 | should: 'should return a list with 0 elements inside ',
71 | },
72 | };
73 | //=====================================================================================
74 | export const PARSER_INPUT_TEST_CASE_7 = {
75 | data: {
76 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
77 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
78 | logLevel: [datatype.number(345464)],
79 | },
80 | expectation: {
81 | should: 'should throw error ',
82 | },
83 | };
84 | //=====================================================================================
85 | export const PARSER_INPUT_TEST_CASE_8 = {
86 | data: {
87 | input: FIXTURE_BASE_PATH + '/fixture-input.log',
88 | output: FIXTURE_BASE_PATH + '/fixture-output.log',
89 | logLevel: [datatype.string(20), datatype.string(20), datatype.string(20)],
90 | },
91 | expectation: {
92 | should: 'should return a list with 0 elements inside',
93 | },
94 | };
95 |
--------------------------------------------------------------------------------
/test/unit-tests/factories/utils.factory.ts:
--------------------------------------------------------------------------------
1 | import { datatype } from 'faker';
2 |
3 | export const DTO_VALIDATION_TEST_CASE_1 = {
4 | data: {
5 | input: 'input.log',
6 | output: 'output.log',
7 | logLevel: ['error', 'warn', 'info', 'debug'],
8 | },
9 | expectation: {
10 | should: 'should return ok',
11 | },
12 | };
13 | //===========================================================================================
14 | export const DTO_VALIDATION_TEST_CASE_2 = {
15 | data: {
16 | input: 'input.log',
17 | output: 'output.log',
18 | logLevel: [],
19 | },
20 | expectation: {
21 | should: 'should return ok',
22 | },
23 | };
24 | //===========================================================================================
25 | export const DTO_VALIDATION_TEST_CASE_3 = {
26 | data: {
27 | input: datatype.string(5),
28 | output: 'output.log',
29 | logLevel: ['error'],
30 | },
31 | expectation: {
32 | should: 'should return ok',
33 | },
34 | };
35 | //===========================================================================================
36 | export const DTO_VALIDATION_TEST_CASE_4 = {
37 | data: {
38 | input: datatype.string(5),
39 | output: datatype.string(5),
40 | logLevel: [],
41 | },
42 | expectation: {
43 | should: 'should return ok',
44 | },
45 | };
46 | //===========================================================================================
47 | export const DTO_VALIDATION_TEST_CASE_5 = {
48 | data: {
49 | input: datatype.number(5),
50 | output: datatype.number(5),
51 | logLevel: [],
52 | },
53 | expectation: {
54 | should: 'should return error',
55 | },
56 | };
57 | //===========================================================================================
58 | export const DTO_VALIDATION_TEST_CASE_6 = {
59 | data: {
60 | input: 'input.log',
61 | output: 'output.log',
62 | logLevel: [datatype.string(10)],
63 | },
64 | expectation: {
65 | should: 'should return error',
66 | },
67 | };
68 | //===========================================================================================
69 | export const DTO_VALIDATION_TEST_CASE_7 = {
70 | data: {
71 | input: 'input.log',
72 | output: 'output.log',
73 | logLevel: [datatype.number(200)],
74 | },
75 | expectation: {
76 | should: 'should return error',
77 | },
78 | };
79 | //===========================================================================================
80 | export const DTO_VALIDATION_TEST_CASE_8 = {
81 | data: {
82 | input: 'input.log',
83 | output: 'output.log',
84 | logLevel: datatype.number(200),
85 | },
86 | expectation: {
87 | should: 'should return error',
88 | },
89 | };
90 | //===========================================================================================
91 | export const DTO_VALIDATION_TEST_CASE_9 = {
92 | data: {
93 | input: 'input.log',
94 | logLevel: datatype.number(200),
95 | },
96 | expectation: {
97 | should: 'should return error',
98 | },
99 | };
100 | //===========================================================================================
101 | export const DTO_VALIDATION_TEST_CASE_10 = {
102 | data: {
103 | output: 'output.log',
104 | logLevel: datatype.number(200),
105 | },
106 | expectation: {
107 | should: 'should return error',
108 | },
109 | };
110 | //===========================================================================================
111 | export const DTO_VALIDATION_TEST_CASE_11 = {
112 | data: {
113 | logLevel: datatype.number(200),
114 | },
115 | expectation: {
116 | should: 'should return error',
117 | },
118 | };
119 | //===========================================================================================
120 | export const DTO_VALIDATION_TEST_CASE_12 = {
121 | data: {
122 | input: 'input.log',
123 | output: 'output.log',
124 | },
125 | expectation: {
126 | should: 'should return ok',
127 | },
128 | };
129 | //===========================================================================================
130 | export const DTO_VALIDATION_TEST_CASE_13 = {
131 | data: {
132 | input: true,
133 | output: 'output.log',
134 | },
135 | expectation: {
136 | should: 'should return error',
137 | },
138 | };
139 | //===========================================================================================
140 | export const DTO_VALIDATION_TEST_CASE_14 = {
141 | data: {
142 | input: 'input.log',
143 | output: false,
144 | },
145 | expectation: {
146 | should: 'should return error',
147 | },
148 | };
149 |
--------------------------------------------------------------------------------
/test/unit-tests/filehelper.spec.ts:
--------------------------------------------------------------------------------
1 | import { FileHelper } from '../../src/parser/helper';
2 | import {
3 | LOG_PARSER_TEST_CASE_1,
4 | LOG_PARSER_TEST_CASE_2,
5 | LOG_PARSER_TEST_CASE_3,
6 | LOG_PARSER_TEST_CASE_4,
7 | LOG_PARSER_TEST_CASE_5,
8 | LOG_PARSER_TEST_CASE_6,
9 | LOG_PARSER_TEST_CASE_7,
10 | LOG_PARSER_TEST_CASE_8,
11 | } from './factories';
12 |
13 | describe('tests the behavior of file helper class', () => {
14 | const fileHelper = new FileHelper();
15 | //==================================================================================================================
16 | it(LOG_PARSER_TEST_CASE_1.expectation.should, async () => {
17 | const result = await fileHelper.parsLog(
18 | LOG_PARSER_TEST_CASE_1.data,
19 | LOG_PARSER_TEST_CASE_1.logLevel,
20 | );
21 | expect(result.timestamp).toEqual(
22 | LOG_PARSER_TEST_CASE_1.expectation.value.timestamp,
23 | );
24 | expect(result.logLevel).toEqual(
25 | LOG_PARSER_TEST_CASE_1.expectation.value.logLevel,
26 | );
27 | expect(result.transactionId).toEqual(
28 | LOG_PARSER_TEST_CASE_1.expectation.value.transactionId,
29 | );
30 | expect(result.err).toEqual(LOG_PARSER_TEST_CASE_1.expectation.value.err);
31 | });
32 | //..................................................................................................................
33 | it(LOG_PARSER_TEST_CASE_2.expectation.should, async () => {
34 | try {
35 | await fileHelper.parsLog(
36 | LOG_PARSER_TEST_CASE_2.data,
37 | LOG_PARSER_TEST_CASE_2.logLevel,
38 | );
39 | } catch (error) {
40 | expect(error).toBeDefined();
41 | }
42 | });
43 | //..................................................................................................................
44 | it(LOG_PARSER_TEST_CASE_3.expectation.should, async () => {
45 | try {
46 | await fileHelper.parsLog(
47 | LOG_PARSER_TEST_CASE_3.data,
48 | LOG_PARSER_TEST_CASE_3.logLevel,
49 | );
50 | } catch (error) {
51 | expect(error).toBeDefined();
52 | }
53 | });
54 | //..................................................................................................................
55 | it(LOG_PARSER_TEST_CASE_4.expectation.should, async () => {
56 | try {
57 | await fileHelper.parsLog(
58 | LOG_PARSER_TEST_CASE_4.data,
59 | LOG_PARSER_TEST_CASE_4.logLevel,
60 | );
61 | } catch (error) {
62 | expect(error).toBeDefined();
63 | }
64 | });
65 | //..................................................................................................................
66 | it(LOG_PARSER_TEST_CASE_5.expectation.should, async () => {
67 | const result = await fileHelper.parsLog(
68 | LOG_PARSER_TEST_CASE_5.data,
69 | LOG_PARSER_TEST_CASE_5.logLevel,
70 | );
71 | expect(result).toBeUndefined();
72 | });
73 | //..................................................................................................................
74 | it(LOG_PARSER_TEST_CASE_6.expectation.should, async () => {
75 | const result = await fileHelper.parsLog(
76 | LOG_PARSER_TEST_CASE_6.data,
77 | LOG_PARSER_TEST_CASE_6.logLevel,
78 | );
79 | expect(result.logLevel).toEqual(
80 | LOG_PARSER_TEST_CASE_6.expectation.value.logLevel,
81 | );
82 | });
83 | //..................................................................................................................
84 | it(LOG_PARSER_TEST_CASE_7.expectation.should, async () => {
85 | const result = await fileHelper.parsLog(
86 | LOG_PARSER_TEST_CASE_7.data,
87 | LOG_PARSER_TEST_CASE_7.logLevel,
88 | );
89 | expect(result.logLevel).toEqual(
90 | LOG_PARSER_TEST_CASE_7.expectation.value.logLevel,
91 | );
92 | expect(result.transactionId).toEqual(
93 | LOG_PARSER_TEST_CASE_7.expectation.value.transactionId,
94 | );
95 | });
96 | //..................................................................................................................
97 | it(LOG_PARSER_TEST_CASE_8.expectation.should, async () => {
98 | const result = await fileHelper.parsLog(
99 | LOG_PARSER_TEST_CASE_8.data,
100 | LOG_PARSER_TEST_CASE_8.logLevel,
101 | );
102 | expect(result.logLevel).toEqual(
103 | LOG_PARSER_TEST_CASE_8.expectation.value.logLevel,
104 | );
105 | expect(result.transactionId).toEqual(
106 | LOG_PARSER_TEST_CASE_8.expectation.value.transactionId,
107 | );
108 | expect(result.err).toEqual(LOG_PARSER_TEST_CASE_8.expectation.value.err);
109 | });
110 | //..................................................................................................................
111 | //..................................................................................................................
112 | //..................................................................................................................
113 | //..................................................................................................................
114 | });
115 |
--------------------------------------------------------------------------------
/test/unit-tests/fixtures/fixture-input.log:
--------------------------------------------------------------------------------
1 | 2044-08-09T02:12:51.253Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service is started"}
2 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request the user information","userId": 10}
3 | 2021-08-09T02:12:51.254Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"About to request user orders list","userId": 10}
4 | 2021-08-09T02:12:51.255Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is started"}
5 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request the user information","userId": 16}
6 | 2021-08-09T02:12:51.257Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"User information is gathered","user":{"id":10,"name":"Alice"}}
7 | 2021-08-09T02:12:51.258Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"About to request user orders list","userId":16}
8 | 2021-08-09T02:12:51.259Z - error - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Cannot find user orders list","code": 404,"err":"Not found"}
9 | 2021-08-09T02:12:51.259Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user": {"id": 16, "name": "Michael"}}
10 | 2021-08-09T02:12:51.262Z - debug - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"User information is retrieved","user":{"id":16,"orders":[{"id":472,"items":{"id":7,"price":7.12}}]}}
11 | 2021-08-09T02:12:51.264Z - warn - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e978","details":"Service finished with error","code":404,"err":"Cannot find user orders list"}
12 | 2021-08-09T02:12:51.265Z - info - {"transactionId":"9abc55b2-807b-4361-9dbe-aa88b1b2e821","details":"Service is successfully finished"}
13 |
--------------------------------------------------------------------------------
/test/unit-tests/parser.service.spec.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import { ParserCommandDTO } from '../../src/parser/dtos/parser-command-dto';
3 | import { FileHelper } from '../../src/parser/helper';
4 | import { ParserService } from '../../src/parser/service/parser.service';
5 | import {
6 | FIXTURE_BASE_PATH,
7 | PARSER_INPUT_TEST_CASE_1,
8 | PARSER_INPUT_TEST_CASE_2,
9 | PARSER_INPUT_TEST_CASE_3,
10 | PARSER_INPUT_TEST_CASE_4,
11 | PARSER_INPUT_TEST_CASE_5,
12 | PARSER_INPUT_TEST_CASE_6,
13 | PARSER_INPUT_TEST_CASE_7,
14 | PARSER_INPUT_TEST_CASE_8,
15 | } from './factories';
16 |
17 | describe('tests the behavior of parser service class', () => {
18 | const fileHelper = new FileHelper();
19 | const service = new ParserService(fileHelper);
20 | //==================================================================================================================
21 | it(PARSER_INPUT_TEST_CASE_1.expectation.should, async () => {
22 | const result = await service.parse(
23 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_1.data),
24 | );
25 | expect(result.length).toBeGreaterThan(0);
26 | });
27 | //..................................................................................................................
28 | it(PARSER_INPUT_TEST_CASE_2.expectation.should, async () => {
29 | const result = await service.parse(
30 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_2.data),
31 | );
32 | expect(
33 | (
34 | await result.filter(
35 | (log: { logLevel: string }) => log.logLevel === 'debug',
36 | )
37 | ).length,
38 | ).toBeGreaterThan(0);
39 | expect(
40 | (
41 | await result.filter(
42 | (log: { logLevel: string }) => log.logLevel === 'error',
43 | )
44 | ).length,
45 | ).toBeGreaterThan(0);
46 | });
47 | //..................................................................................................................
48 | it(PARSER_INPUT_TEST_CASE_3.expectation.should, async () => {
49 | const result = await service.parse(
50 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_3.data),
51 | );
52 | expect(await result.length).toEqual(0);
53 | });
54 | //..................................................................................................................
55 | it(PARSER_INPUT_TEST_CASE_4.expectation.should, async () => {
56 | const result = await service.parse(
57 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_4.data),
58 | );
59 | expect(
60 | (
61 | await result.filter(
62 | (log: { logLevel: string }) => log.logLevel === 'warn',
63 | )
64 | ).length,
65 | ).toBeGreaterThan(0);
66 | expect(
67 | (
68 | await result.filter(
69 | (log: { logLevel: string }) => log.logLevel === 'error',
70 | )
71 | ).length,
72 | ).toBeGreaterThan(0);
73 | expect(
74 | (
75 | await result.filter(
76 | (log: { logLevel: string }) => log.logLevel === 'debug',
77 | )
78 | ).length,
79 | ).toBeGreaterThan(0);
80 | });
81 | //..................................................................................................................
82 | it(PARSER_INPUT_TEST_CASE_5.expectation.should, async () => {
83 | const result = await service.parse(
84 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_5.data),
85 | );
86 | expect(
87 | (
88 | await result.filter(
89 | (log: { logLevel: string }) => log.logLevel === 'warn',
90 | )
91 | ).length,
92 | ).toBeGreaterThan(0);
93 | expect(
94 | (
95 | await result.filter(
96 | (log: { logLevel: string }) => log.logLevel === 'error',
97 | )
98 | ).length,
99 | ).toBeGreaterThan(0);
100 | expect(
101 | (
102 | await result.filter(
103 | (log: { logLevel: string }) => log.logLevel === 'debug',
104 | )
105 | ).length,
106 | ).toBeGreaterThan(0);
107 | expect(
108 | (
109 | await result.filter(
110 | (log: { logLevel: string }) => log.logLevel === 'info',
111 | )
112 | ).length,
113 | ).toBeGreaterThan(0);
114 | });
115 | //..................................................................................................................
116 | it(PARSER_INPUT_TEST_CASE_6.expectation.should, async () => {
117 | const result = await service.parse(
118 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_6.data),
119 | );
120 | expect(
121 | (
122 | await result.filter(
123 | (log: { logLevel: string }) => log.logLevel === 'warn',
124 | )
125 | ).length,
126 | ).toEqual(0);
127 | expect(
128 | (
129 | await result.filter(
130 | (log: { logLevel: string }) => log.logLevel === 'error',
131 | )
132 | ).length,
133 | ).toEqual(0);
134 | expect(
135 | (
136 | await result.filter(
137 | (log: { logLevel: string }) => log.logLevel === 'debug',
138 | )
139 | ).length,
140 | ).toEqual(0);
141 | expect(
142 | (
143 | await result.filter(
144 | (log: { logLevel: string }) => log.logLevel === 'info',
145 | )
146 | ).length,
147 | ).toEqual(0);
148 | });
149 | //..................................................................................................................
150 | it(PARSER_INPUT_TEST_CASE_7.expectation.should, async () => {
151 | try {
152 | await service.parse(new ParserCommandDTO(PARSER_INPUT_TEST_CASE_7.data));
153 | } catch (error) {
154 | expect(error).toBeDefined();
155 | }
156 | });
157 | //..................................................................................................................
158 | it(PARSER_INPUT_TEST_CASE_8.expectation.should, async () => {
159 | const result = await service.parse(
160 | new ParserCommandDTO(PARSER_INPUT_TEST_CASE_8.data),
161 | );
162 | expect(
163 | (
164 | await result.filter(
165 | (log: { logLevel: string }) => log.logLevel === 'warn',
166 | )
167 | ).length,
168 | ).toEqual(0);
169 | expect(
170 | (
171 | await result.filter(
172 | (log: { logLevel: string }) => log.logLevel === 'error',
173 | )
174 | ).length,
175 | ).toEqual(0);
176 | expect(
177 | (
178 | await result.filter(
179 | (log: { logLevel: string }) => log.logLevel === 'debug',
180 | )
181 | ).length,
182 | ).toEqual(0);
183 | expect(
184 | (
185 | await result.filter(
186 | (log: { logLevel: string }) => log.logLevel === 'info',
187 | )
188 | ).length,
189 | ).toEqual(0);
190 | });
191 | //..................................................................................................................
192 | //==================================================================================================================
193 | afterAll(() => {
194 | fs.unlinkSync(FIXTURE_BASE_PATH + '/fixture-output.log');
195 | });
196 | });
197 |
--------------------------------------------------------------------------------
/test/unit-tests/utils.spec.ts:
--------------------------------------------------------------------------------
1 | import { validateDTO } from '../../src/parser/common';
2 | import { ParserCommandDTO } from '../../src/parser/dtos/parser-command-dto';
3 | import {
4 | DTO_VALIDATION_TEST_CASE_1,
5 | DTO_VALIDATION_TEST_CASE_10,
6 | DTO_VALIDATION_TEST_CASE_11,
7 | DTO_VALIDATION_TEST_CASE_12,
8 | DTO_VALIDATION_TEST_CASE_13,
9 | DTO_VALIDATION_TEST_CASE_14,
10 | DTO_VALIDATION_TEST_CASE_2,
11 | DTO_VALIDATION_TEST_CASE_3,
12 | DTO_VALIDATION_TEST_CASE_4,
13 | DTO_VALIDATION_TEST_CASE_5,
14 | DTO_VALIDATION_TEST_CASE_6,
15 | DTO_VALIDATION_TEST_CASE_7,
16 | DTO_VALIDATION_TEST_CASE_8,
17 | DTO_VALIDATION_TEST_CASE_9,
18 | } from './factories';
19 |
20 | describe('tests the functions inside utils file', () => {
21 | //==================================================================================================================
22 | it(DTO_VALIDATION_TEST_CASE_1.expectation.should, async () => {
23 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_1.data);
24 | await validateDTO(dto);
25 | expect(dto.input).toBeDefined();
26 | });
27 | //..................................................................................................................
28 | it(DTO_VALIDATION_TEST_CASE_2.expectation.should, async () => {
29 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_2.data);
30 | await validateDTO(dto);
31 | expect(dto.input).toBeDefined();
32 | });
33 | //..................................................................................................................
34 | it(DTO_VALIDATION_TEST_CASE_3.expectation.should, async () => {
35 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_3.data);
36 | await validateDTO(dto);
37 | expect(dto.input).toBeDefined();
38 | });
39 | //..................................................................................................................
40 | it(DTO_VALIDATION_TEST_CASE_4.expectation.should, async () => {
41 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_4.data);
42 | await validateDTO(dto);
43 | expect(dto.input).toBeDefined();
44 | });
45 | //..................................................................................................................
46 | it(DTO_VALIDATION_TEST_CASE_5.expectation.should, async () => {
47 | try {
48 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_5.data);
49 | await validateDTO(dto);
50 | } catch (error) {
51 | expect(error).toBeDefined();
52 | }
53 | });
54 | //..................................................................................................................
55 | it(DTO_VALIDATION_TEST_CASE_6.expectation.should, async () => {
56 | try {
57 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_6.data);
58 | await validateDTO(dto);
59 | } catch (error) {
60 | expect(error).toBeDefined();
61 | }
62 | });
63 | //..................................................................................................................
64 | it(DTO_VALIDATION_TEST_CASE_7.expectation.should, async () => {
65 | try {
66 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_7.data);
67 | await validateDTO(dto);
68 | } catch (error) {
69 | expect(error).toBeDefined();
70 | }
71 | });
72 | //..................................................................................................................
73 | it(DTO_VALIDATION_TEST_CASE_8.expectation.should, async () => {
74 | try {
75 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_8.data);
76 | await validateDTO(dto);
77 | } catch (error) {
78 | expect(error).toBeDefined();
79 | }
80 | });
81 | //..................................................................................................................
82 | it(DTO_VALIDATION_TEST_CASE_9.expectation.should, async () => {
83 | try {
84 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_9.data);
85 | await validateDTO(dto);
86 | } catch (error) {
87 | expect(error).toBeDefined();
88 | }
89 | });
90 | //..................................................................................................................
91 | it(DTO_VALIDATION_TEST_CASE_10.expectation.should, async () => {
92 | try {
93 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_10.data);
94 | await validateDTO(dto);
95 | } catch (error) {
96 | expect(error).toBeDefined();
97 | }
98 | });
99 | //..................................................................................................................
100 | it(DTO_VALIDATION_TEST_CASE_11.expectation.should, async () => {
101 | try {
102 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_11.data);
103 | await validateDTO(dto);
104 | } catch (error) {
105 | expect(error).toBeDefined();
106 | }
107 | });
108 | //..................................................................................................................
109 | it(DTO_VALIDATION_TEST_CASE_12.expectation.should, async () => {
110 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_12.data);
111 | await validateDTO(dto);
112 | expect(dto.input).toBeDefined();
113 | });
114 | //..................................................................................................................
115 | it(DTO_VALIDATION_TEST_CASE_13.expectation.should, async () => {
116 | try {
117 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_13.data);
118 | await validateDTO(dto);
119 | } catch (error) {
120 | expect(error).toBeDefined();
121 | }
122 | });
123 | //..................................................................................................................
124 | it(DTO_VALIDATION_TEST_CASE_14.expectation.should, async () => {
125 | try {
126 | const dto = new ParserCommandDTO(DTO_VALIDATION_TEST_CASE_14.data);
127 | await validateDTO(dto);
128 | } catch (error) {
129 | expect(error).toBeDefined();
130 | }
131 | });
132 | //..................................................................................................................
133 | });
134 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.compodoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "src/**/*"
4 | ],
5 | "exclude": [
6 | "node_modules/",
7 | "projects/"
8 | ]
9 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------