diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..b9e3a1b
Binary files /dev/null and b/.DS_Store differ
diff --git a/.babelrc b/.babelrc
index 7836d59..50b4d8f 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,20 +1,20 @@
{
- "presets": [
- "@babel/preset-env",
- [
- "@babel/preset-react",
- {
- "runtime": "automatic"
- }
- ],
- "@babel/preset-typescript"
+ "presets": [
+ "@babel/preset-env",
+ [
+ "@babel/preset-react",
+ {
+ "runtime": "automatic"
+ }
],
- "plugins": [
- [
- "@babel/plugin-transform-runtime",
- {
- "regenerator": true
- }
- ]
+ "@babel/preset-typescript"
+ ],
+ "plugins": [
+ [
+ "@babel/plugin-transform-runtime",
+ {
+ "regenerator": true
+ }
]
- }
\ No newline at end of file
+ ]
+}
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..36191bf
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+# EditorConfig http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# All files
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
index 4f23635..62950b0 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,33 +1,33 @@
module.exports = {
- parser: '@typescript-eslint/parser',
+ parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2020,
- sourceType: 'module',
+ sourceType: "module",
},
settings: {
react: {
- version: 'detect',
+ version: "detect",
},
},
extends: [
- 'plugin:react/recommended',
- 'plugin:react-hooks/recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:import/errors',
- 'plugin:import/warnings',
- 'plugin:import/typescript',
- 'plugin:jsx-a11y/recommended',
- 'plugin:eslint-comments/recommended',
- 'prettier',
- 'plugin:prettier/recommended',
+ "plugin:react/recommended",
+ "plugin:react-hooks/recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:import/errors",
+ "plugin:import/warnings",
+ "plugin:import/typescript",
+ "plugin:jsx-a11y/recommended",
+ "plugin:eslint-comments/recommended",
+ "prettier/@typescript-eslint",
+ "plugin:prettier/recommended",
],
rules: {
- 'no-unused-vars': 'off',
- '@typescript-eslint/no-unused-vars': ['error'],
- '@typescript-eslint/no-var-requires': 'off',
- 'react/prop-types': 'off',
- 'react/jsx-uses-react': 'off',
- 'react/react-in-jsx-scope': 'off',
- '@typescript-eslint/explicit-module-boundary-types': 'off',
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": ["error"],
+ "@typescript-eslint/no-var-requires": "off",
+ "react/prop-types": "off",
+ "react/jsx-uses-react": "off",
+ "react/react-in-jsx-scope": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off",
},
};
diff --git a/.github/workflows/integrate.yml b/.github/workflows/integrate.yml
new file mode 100644
index 0000000..795391e
--- /dev/null
+++ b/.github/workflows/integrate.yml
@@ -0,0 +1,18 @@
+name: Node Continuous Integration
+
+on:
+ pull_request:
+ branches: [ master ]
+
+
+jobs:
+ test_pull_request:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v1
+ with:
+ node-version: 12
+ - run: npm ci
+ - run: npm test
+ - run: npm run build
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index f8b83f7..e972148 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
+build
node_modules
-metrics/dist
-metrics/data
-.DS_Store
\ No newline at end of file
+.env
+metrics/
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 2b77d48..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "grpseek_splashpage"]
- path = grpseek_splashpage
- url = https://github.com/johncamilomcconnell/grpseek_splashpage.git
diff --git a/.prettierrc.js b/.prettierrc.js
index 81ed5f8..00df698 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -1,9 +1,9 @@
module.exports = {
- semi: true,
- trailingComma: 'es5',
- singleQuote: true,
- jsxSingleQuote: false,
- printWidth: 80,
- tabWidth: 2,
- endOfLine: 'auto'
- }
\ No newline at end of file
+ semi: true,
+ trailingComma: "es5",
+ singleQuote: true,
+ jsxSingleQuote: false,
+ printWidth: 80,
+ tabWidth: 2,
+ endOfLine: "auto",
+};
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0a77011..cac0e10 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,3 @@
{
- "editor.tabSize": 2
+ "editor.formatOnSave": true
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..92ef113
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,113 @@
+#### 1.0.0 (2023-09-16)
+
+##### Documentation Changes
+
+* fix typo (1f70c548)
+* fix readme (84fd40c8)
+* changelong, code of conduct, contributing, license (cd7b5466)
+
+##### New Features
+
+* add cli-support (842bb568)
+* add ssl certs, metric-dashboard, cli-tool (9a9444ef)
+* compile proto files to a descriptor set binary file && add server reflection (a493eb00)
+* add grpc-app (6dc5e389)
+* add concurrency test (3816f079)
+* add fetch component (095a1e18)
+* ci workflow (72e75547)
+
+##### Bug Fixes
+
+* generate dashboard (c7cac9bb)
+* generate dashboard (103e40dc)
+
+##### Other Changes
+
+* changelog (53881cbd)
+* created clusters and worker threads based on user input and send calls to grpc server for each worker thread. Incorrrect function is repeated for all threads (5f1377e4)
+* add configs (83f3c561)
+* //github.com/oslabs-beta/gRPSeek into dev (f5bc8822)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (0abc4c75)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (3407bd78)
+* //github.com/oslabs-beta/gRPSeek into npm-grpseek (4c196321)
+
+##### Refactors
+
+* clean repo (bb5a9352)
+
+##### Code Style Changes
+
+* format lte, cli, server & client (f2eec66b)
+
+#### 1.0.0 (2023-09-14)
+
+##### Documentation Changes
+
+* fix typo (1f70c548)
+* fix readme (84fd40c8)
+* changelong, code of conduct, contributing, license (cd7b5466)
+
+##### New Features
+
+* add ssl certs, metric-dashboard, cli-tool (9a9444ef)
+* compile proto files to a descriptor set binary file && add server reflection (a493eb00)
+* add grpc-app (6dc5e389)
+* add concurrency test (3816f079)
+* add fetch component (095a1e18)
+* ci workflow (72e75547)
+
+##### Other Changes
+
+* created clusters and worker threads based on user input and send calls to grpc server for each worker thread. Incorrrect function is repeated for all threads (5f1377e4)
+* add configs (83f3c561)
+* //github.com/oslabs-beta/gRPSeek into dev (f5bc8822)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (0abc4c75)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (3407bd78)
+* //github.com/oslabs-beta/gRPSeek into npm-grpseek (4c196321)
+
+##### Refactors
+
+* clean repo (bb5a9352)
+
+#### 1.0.0 (2023-09-07)
+
+##### Documentation Changes
+
+* fix typo (1f70c548)
+* fix readme (84fd40c8)
+* changelong, code of conduct, contributing, license (cd7b5466)
+
+##### New Features
+
+* compile proto files to a descriptor set binary file && add server reflection (a493eb00)
+* add grpc-app (6dc5e389)
+* add concurrency test (3816f079)
+* add fetch component (095a1e18)
+* ci workflow (72e75547)
+
+##### Other Changes
+
+* add configs (83f3c561)
+* //github.com/oslabs-beta/gRPSeek into dev (f5bc8822)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (0abc4c75)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (3407bd78)
+* //github.com/oslabs-beta/gRPSeek into npm-grpseek (4c196321)
+
+##### Refactors
+
+* clean repo (bb5a9352)
+
+#### 1.0.0 (2023-08-18)
+
+##### Other Changes
+
+* add configs (83f3c561)
+* //github.com/oslabs-beta/gRPSeek into dev (f5bc8822)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (0abc4c75)
+* //github.com/oslabs-beta/gRPSeek into miri/gui (3407bd78)
+* //github.com/oslabs-beta/gRPSeek into npm-grpseek (4c196321)
+
+##### Refactors
+
+* clean repo (bb5a9352)
+
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..adabfac
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,39 @@
+# Code of Conduct
+
+All participants of this repository are expected to abide by our Code of Conduct, both online and during in-person events that are hosted and/or associated with this repository.
+
+## The Pledge
+
+In the interest of fostering an open and welcoming environment, we pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## The Standards
+
+Examples of behaviour that contributes to creating a positive environment include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Referring to people by their preferred pronouns and using gender-neutral pronouns when uncertain
+
+Examples of unacceptable behaviour by participants include:
+
+- Trolling, insulting/derogatory comments, public or private harassment
+- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Not being respectful to reasonable communication boundaries, such as 'leave me alone,' 'go away,' or 'I’m not discussing this with you.'
+- The usage of sexualised language or imagery and unwelcome sexual attention or advances
+- Swearing, usage of strong or disturbing language
+- Demonstrating the graphics or any other content you know may be considered disturbing
+- Starting and/or participating in arguments related to politics
+- Assuming or promoting any kind of inequality including but not limited to: age, body size, disability, ethnicity, gender identity and expression, nationality and race, personal appearance, religion, or sexual identity and orientation
+- Attacking personal tastes
+- Other conduct which you know could reasonably be considered inappropriate in a professional setting.
+
+## Enforcement
+
+Violations of the Code of Conduct may be reported by sending an email to [grpseek@protonmail.com](mailto:grpseek@protonmail.com). All reports will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Further details of specific enforcement policies may be posted separately.
+
+We hold the right and responsibility to remove comments or other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any members for other behaviours that they deem inappropriate, threatening, offensive, or harmful.
+
+## Attribution
+
+This Code of Conduct is adapted from [dev.to](https://dev.to/code-of-conduct).
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..7faf06b
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,70 @@
+# Welcome to the gRPSeek contributing guide!
+
+Thank you for investing your time in contributing to our project! ✨
+
+In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
+
+## New contributor guide
+
+To get an overview of the project, read the [README](README.md). Here are some resources to help you get started with open source contributions:
+
+- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
+- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
+- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
+- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
+
+
+## Getting started
+
+To navigate our codebase with confidence, see the [Developer Guidelines](/src/README.md) 🎊.
+
+### Issues
+
+#### Create a new issue
+
+If you spot a problem with the docs, [search if an issue already exists](https://github.com/oslabs-beta/gRPSeek). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/oslabs-beta/gRPSeek/issues/new).
+
+#### Solve an issue
+
+Scan through our [existing issues](https://github.com/oslabs-beta/gRPSeek/issues) to find one that interests you. As a general rule, we don’t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
+
+### Make Changes
+
+#### Make changes in the UI
+
+Click **Make a contribution** at the bottom of any docs page to make small changes such as a typo, sentence fix, or a broken link. This takes you to the `.md` file where you can make your changes and [create a pull request](#pull-request) for a review.
+
+#### Make changes locally
+
+1. [Install Git LFS](https://docs.github.com/en/github/managing-large-files/versioning-large-files/installing-git-large-file-storage).
+
+2. Fork the repository.
+- Using GitHub Desktop:
+ - [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.
+ - Once Desktop is set up, you can use it to [fork the repo](https://github.com/open-source-labs/reactime.git)!
+
+- Using the command line:
+ - [Fork the repo](https://github.com/oslabs-beta/gRPSeek.git) so that you can make your changes without affecting the original project until you're ready to merge them.
+
+3. Create a working branch and start with your changes!
+
+### Commit your update
+
+Commit the changes once you are happy with them.
+
+### Pull Request
+
+When you're finished with the changes, create a pull request, also known as a PR.
+- Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
+- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
+- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
+Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request additional information.
+- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
+- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
+- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.
+
+### Your PR is merged!
+
+Congratulations 🎉 The gRPSeek team thanks you! ✨
+
+Once your PR is merged, your contributions will be publicly visible on [gRPSeek](https://github.com/oslabs-beta/gRPSeek)!
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..7be29a1
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,363 @@
+
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms of
+ a Secondary License.
+
+1.6. "Executable Form"
+
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+ means a work that combines Covered Software with other material, in a
+ separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+ means this document.
+
+1.9. "Licensable"
+
+ means having the right to grant, to the maximum extent possible, whether
+ at the time of the initial grant or subsequently, any and all of the
+ rights conveyed by this License.
+
+1.10. "Modifications"
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the License,
+ by the making, using, selling, offering for sale, having made, import,
+ or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights to
+ grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter the
+ recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty, or
+ limitations of liability) contained within the Source Code Form of the
+ Covered Software, except that You may alter any license notices to the
+ extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms of
+ this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be placed in a
+ text file included with all distributions of the Covered Software under
+ this License. Except to the extent prohibited by statute or regulation,
+ such description must be sufficiently detailed for a recipient of ordinary
+ skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing
+ basis, if such Contributor fails to notify You of the non-compliance by
+ some reasonable means prior to 60 days after You have come back into
+ compliance. Moreover, Your grants from a particular Contributor are
+ reinstated on an ongoing basis if such Contributor notifies You of the
+ non-compliance by some reasonable means, this is the first time You have
+ received notice of non-compliance with this License from such
+ Contributor, and You become compliant prior to 30 days after Your receipt
+ of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an "as is" basis,
+ without warranty of any kind, either expressed, implied, or statutory,
+ including, without limitation, warranties that the Covered Software is free
+ of defects, merchantable, fit for a particular purpose or non-infringing.
+ The entire risk as to the quality and performance of the Covered Software
+ is with You. Should any Covered Software prove defective in any respect,
+ You (not any Contributor) assume the cost of any necessary servicing,
+ repair, or correction. This disclaimer of warranty constitutes an essential
+ part of this License. No use of any Covered Software is authorized under
+ this License except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from
+ such party's negligence to the extent applicable law prohibits such
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
+ incidental or consequential damages, so this exclusion and limitation may
+ not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts
+ of a jurisdiction where the defendant maintains its principal place of
+ business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
+ in this Section shall prevent a party's ability to bring cross-claims or
+ counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides that
+ the language of a contract shall be construed against the drafter shall not
+ be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses If You choose to distribute Source Code Form that is
+ Incompatible With Secondary Licenses under the terms of this version of
+ the License, the notice described in Exhibit B of this License must be
+ attached.
+
+Exhibit A - Source Code Form License Notice
+
+ This Source Code Form is subject to the
+ terms of the Mozilla Public License, v.
+ 2.0. If a copy of the MPL was not
+ distributed with this file, You can
+ obtain one at
+ http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+ This Source Code Form is "Incompatible
+ With Secondary Licenses", as defined by
+ the Mozilla Public License, v. 2.0.
diff --git a/README.md b/README.md
index 466fef2..20f3b3a 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,109 @@
-# gRPSeek
+
-***gRPSeek*** is a load testing and metrics visualization tool. By utilizing this package, developers can increase observability of their gRPC servers and gain valuable insights into the performance of the services.
+![Downloads](https://img.shields.io/github/downloads/kennysghub/gRPSeek-v2/total) ![Contributors](https://img.shields.io/github/contributors/kennysghub/gRPSeek-v2?color=dark-green) ![Issues](https://img.shields.io/github/issues/kennysghub/gRPSeek-v2) ![License](https://img.shields.io/github/license/kennysghub/gRPSeek-v2)
-Check out our [website](https://www.grpseek.io/)!
+## Table Of Contents
-![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white)
-![Babel](https://img.shields.io/badge/Babel-F9DC3e?style=for-the-badge&logo=babel&logoColor=black)
-![Prometheus](https://img.shields.io/badge/Prometheus-E6522C?style=for-the-badge&logo=Prometheus&logoColor=white)
-![Express](https://img.shields.io/badge/Express.js-000000?style=for-the-badge&logo=express&logoColor=white)
-![React](https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)
-![ReactRouter](https://img.shields.io/badge/React_Router-CA4245?style=for-the-badge&logo=react-router&logoColor=white)
-![D3](https://img.shields.io/badge/d3.js-F9A03C?style=for-the-badge&logo=d3.js&logoColor=white)
-![Webpack](https://img.shields.io/badge/Webpack-8DD6F9?style=for-the-badge&logo=Webpack&logoColor=white)
-![Node](https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
-![Sass](https://img.shields.io/badge/Sass-CC6699?style=for-the-badge&logo=sass&logoColor=white)
+- [Table Of Contents](#table-of-contents)
+- [About The Project](#about-the-project)
+- [Built With](#built-with)
+- [Getting Started](#getting-started)
+ - [Prerequisites](#prerequisites)
+ - [Installation](#installation)
+- [Usage](#usage)
+- [Roadmap](#roadmap)
+- [Contributing](#contributing)
+ - [Creating A Pull Request](#creating-a-pull-request)
+- [License](#license)
+- [Authors](#authors)
+- [Acknowledgements](#acknowledgements)
-## Getting Started
-To get started with the package, ensure you have Node.js and npm installed on your system. Additionally, make sure you have a gRPC server set up and running. Follow these steps to use the package:
-```
-npm install grpseek
-```
-The npm package [gRPSeek](https://www.npmjs.com/package/grpseek) the gRPSeek team created, provides load testing for gRPC developers in Node.js. The way this package works under the hood is that it utilizes the worker thread module. Unlike child processes or clusters, worker threads can share memory by transferring ArrayBuffer instances or sharing the SharedArrayBuffer instances.
+## About The Project
+
+This tool is designed to provide comprehensive load testing for gRPC services, allowing developers to simulate various levels of load and analyze server response metrics. By offering real-time insights into latency, throughput, and stream message transmission, it enables the identification and mitigation of performance bottlenecks. The tool's robust testing capabilities ensure that new code does not introduce performance regression, and it plays a vital role in meeting required concurrency and inference response times. Integrated with visualizations and intuitive dashboards, it offers a complete solution for optimizing gRPC service performance and reliability.
+
+
+## Built With
+
+
+- [TypeScript](https://www.typescriptlang.org/)
+- [React](https://react.dev/)
+
+## Getting Started
+
+This is an example of how you may give instructions on setting up your project locally.
+To get a local copy up and running follow these simple example steps.
-The most important function in this npm package is loadTest. All you have to do is pass in three arguments:
+### Prerequisites
-1. `filepath` — The relative filepath to the gRPC client making the calls.
-2. `vu` — Number of virtual users.
-3. `seconds` — Number of seconds these concurrent requests will run.
-```javascript
-const timer = require('grpseek')
-const workerScriptPath = './greeter_client.js';
-timer(workerScriptPath, 400, 15)
+This program has no pre-requisites
+
+### Installation
+
+1. Clone the repo
+
+```
+git clone https://github.com/oslabs-beta/gRPSeek
```
-In this example, 400 worker threads are running the `greeter_client.js` file, for the duration of 15 seconds.
-
-
-
+2. Install dependencies
-This makes it extremely easy for developers in Node.js to load test their gRPC services without making massive changes to their code base or installing unnecessary dependencies. Worker threads are a native module to Node and does not require any other packages for the workers to run the client’s file.
+3. Have fun!
-## Protocol Buffers
-Protocol Buffers (ProtoBuf) are a binary serialization format created by Google in 2008, offering a compact and efficient alternative to JSON and XML. Proto files, or Protocol Buffer files, are the key to using Protocol Buffers. These files are used to define the structure of the data to be serialized or deserialized. They act as a contract or schema between services, ensuring consistent communication.
+## Usage
-## The Need for a Visualizer
-Understanding complex nested structures and repeated fields in proto files can be challenging, especially for a developer who’s working with protocol buffers for the first time. gRPSeek aims to enhance the developer experience of working with Protocol Buffers and gRPC by offering an intuitive visualization tool, powered by D3.js to alleviate the challenges of working with complex, deeply nested proto files. Our tool provides a clear view of the hierarchical structure of your proto files in a tree-like graph. Just import your proto file, or multiple proto files, and see your schema come to life.
-
-
-
+Coming Soon!
-## Troubleshooting and Support
+## Roadmap
-If you encounter any issues or have questions, please reach out to our support team: grpseek@gmail.com.
+See the [open issues](https://github.com/oslabs-beta/gRPSeek/issues) for a list of proposed features (and known issues).
+## Contributing
+Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
-## Contribution and Feedback
+- If you have suggestions for adding or removing projects, feel free to [open an issue](https://github.com/oslabs-beta/gRPSeek/issues/new) to discuss it, or directly create a pull request after you edit the _README.md_ file with necessary changes.
+- Please make sure you check your spelling and grammar.
+- Create individual PR for each suggestion.
+- Please also read through the [Code Of Conduct](https://github.com/oslabs-beta/gRPSeek/issues/) before posting your first idea as well.
-We welcome contributions and feedback from the community. If you find any bugs, have feature requests, or want to contribute code, please follow our contribution guidelines and submit a pull request. Your feedback helps us improve the package and provide a better experience for everyone.
+### Creating A Pull Request
-| Developed By | Github | LinkedIn |
-| :------------------: | :-------------: | :-------------: |
-| Miri Son | [![Github](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/msoncsswe) | [![LinkedIn](https://img.shields.io/badge/LinkedIn-%230077B5.svg?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/miri-son/) |
-| Kenny Nguyen | [![Github](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/kennysghub) | [![LinkedIn](https://img.shields.io/badge/LinkedIn-%230077B5.svg?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/kenknguyen/) |
-| Johnny McConnell | [![Github](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/johncamilomcconnell) | [![LinkedIn](https://img.shields.io/badge/LinkedIn-%230077B5.svg?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/john-camilo-mcconnell/) |
-| Patryk Ploszaj| [![Github](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/pploszaj) | [![LinkedIn](https://img.shields.io/badge/LinkedIn-%230077B5.svg?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/patryk-ploszaj07/) |
+1. Fork the Project
+2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
+3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
+4. Push to the Branch (`git push origin feature/AmazingFeature`)
+5. Open a Pull Request
+## License
+Distributed under the MPL-2.0 License. See [LICENSE](https://github.com/kennysghub/gRPSeek-v2/dev/LICENSE.md) for more information.
+## Acknowledgements
+Coming Soon!
diff --git a/__tests__/components/AddItem.test.tsx b/__tests__/components/AddItem.test.tsx
deleted file mode 100644
index fbcbafc..0000000
--- a/__tests__/components/AddItem.test.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import React from 'react';
-import { render, fireEvent, waitFor } from '@testing-library/react';
-import '@testing-library/jest-dom/extend-expect';
-import AddItem from '../../src/Pages/AddItem';
-import { TodoClient } from '../../src/generated/proto/ToDoServiceClientPb';
-// import { TodoItem, voidNoParams } from '../src/generated/proto/toDo_pb';
-
-jest.mock('../src/generated/proto/ToDoServiceClientPb');
-
-describe('AddItem', () => {
- beforeEach(() => {
- // Clear all instances and calls to constructor and all methods:
- (TodoClient as jest.Mock).mockClear();
- });
-
- it('renders without crashing', () => {
- render();
- });
-
- it('handles text input change', () => {
- const { getByLabelText } = render();
- const input = getByLabelText(/item:/i) as HTMLInputElement;
- fireEvent.change(input, { target: { value: 'Test' } });
- expect(input.value).toBe('Test');
- });
-
- it('handles id input change', () => {
- const { getByLabelText } = render();
- const input = getByLabelText(/id:/i) as HTMLInputElement;
- fireEvent.change(input, { target: { value: '1' } });
- expect(input.value).toBe('1');
- });
-
- it('handles form submission', async () => {
- const { getByText, getByLabelText } = render();
- const itemInput = getByLabelText(/item:/i) as HTMLInputElement;
- const idInput = getByLabelText(/id:/i) as HTMLInputElement;
- const button = getByText(/add to list/i);
-
- fireEvent.change(itemInput, { target: { value: 'Test' } });
- fireEvent.change(idInput, { target: { value: '1' } });
- fireEvent.click(button);
-
- // Assuming that the TodoClient.createTodo method returns a promise that resolves to an object with a toObject method that returns the created todo item
- await waitFor(() =>
- expect(
- (TodoClient.prototype.createTodo as jest.Mock).mock.calls.length
- ).toBe(1)
- );
-
- // Check if the new item is in the list
- expect(getByText(/test/i)).toBeInTheDocument();
- });
-});
diff --git a/__tests__/components/Home.test.tsx b/__tests__/components/Home.test.tsx
deleted file mode 100644
index 8cb7eb1..0000000
--- a/__tests__/components/Home.test.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React from 'react';
-import { render, fireEvent } from '@testing-library/react';
-import { createMemoryHistory } from 'history';
-import { Router } from 'react-router-dom';
-import Home from '../../src/Pages/Home';
-
-describe('Home component', () => {
- it('renders without crashing', () => {
- const history = createMemoryHistory();
- const { getByText } = render(
-
-
-
- );
-
- expect(getByText('gRPSeek')).toBeInTheDocument();
- expect(
- getByText('A POWERFUL VISUALIZATION TOOL FOR gRPC')
- ).toBeInTheDocument();
- expect(getByText('Start Seeking')).toBeInTheDocument();
- expect(getByText('Add Item Page')).toBeInTheDocument();
- });
-
- it('navigates to /main when Start Seeking button is clicked', () => {
- const history = createMemoryHistory();
- const { getByText } = render(
-
-
-
- );
-
- fireEvent.click(getByText('Start Seeking'));
- expect(history.location.pathname).toBe('/main');
- });
-
- it('navigates to /additem when Add Item Page link is clicked', () => {
- const history = createMemoryHistory();
- const { getByText } = render(
-
-
-
- );
-
- fireEvent.click(getByText('Add Item Page'));
- expect(history.location.pathname).toBe('/additem');
- });
-});
diff --git a/__tests__/components/Main.test.tsx b/__tests__/components/Main.test.tsx
deleted file mode 100644
index d5f0413..0000000
--- a/__tests__/components/Main.test.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import Main from '../../src/Pages/Main'; // adjust this import path to match your project structure
-import Dashboard from '../../src/client/components/Dashboard'; // adjust this import path to match your project structure
-
-jest.mock('../client/components/Dashboard', () => {
- return function DummyDashboard() {
- return
Dashboard
;
- };
-});
-
-describe('Main component', () => {
- it('renders without crashing', () => {
- const { getByTestId } = render();
- expect(getByTestId('dashboard')).toBeInTheDocument();
- });
-});
diff --git a/__tests__/grpc-server.test.ts b/__tests__/grpc-server.test.ts
new file mode 100644
index 0000000..eb22b47
--- /dev/null
+++ b/__tests__/grpc-server.test.ts
@@ -0,0 +1,53 @@
+// import * as grpc from '@grpc/grpc-js';
+// import * as protoLoader from '@grpc/proto-loader';
+// import { ProtoGrpcType } from '../proto/helloworld';
+// import { GreeterClient } from '../proto/greeterPackage/Greeter';
+// import { HelloRequest } from '../proto/greeterPackage/HelloRequest';
+// import { HelloReply } from '../proto/greeterPackage/HelloReply';
+
+// const PROTO_FILE = '../proto/helloworld.proto';
+// const PORT = '0.0.0.0:8082';
+
+// // Load proto files
+// const packageDef = protoLoader.loadSync(PROTO_FILE);
+// const grpcObj = grpc.loadPackageDefinition(
+// packageDef
+// ) as unknown as ProtoGrpcType;
+
+// // Create a new gRPC client
+// const greeterClient = new grpcObj.greeterPackage.Greeter(
+// PORT,
+// grpc.credentials.createInsecure()
+// ) as unknown as GreeterClient;
+
+// describe('gRPC Server', () => {
+// it('should handle SayHello RPC', (done) => {
+// const request: HelloRequest = { name: 'John' };
+
+// greeterClient.sayHello(request, (error, response: HelloReply) => {
+// expect(error).toBe(null);
+// expect(response.message).toBe('Hello from server');
+// done();
+// });
+// });
+
+// it('should handle SayHelloAgain RPC', (done) => {
+// const request: HelloRequest = { name: 'John' };
+
+// greeterClient.sayHelloAgain(request, (error, response: HelloReply) => {
+// expect(error).toBe(null);
+// expect(response.message).toBe('Hello again from server');
+// done();
+// });
+// });
+
+// it('should return error for invalid SayHello request', (done) => {
+// const request: HelloRequest = { name: '' };
+
+// greeterClient.sayHello(request, (error) => {
+// expect(error).not.toBe(null);
+// expect(error?.code).toBe(grpc.status.INVALID_ARGUMENT);
+// done();
+// });
+// });
+// });
diff --git a/assets/grpc-dash.jpg b/assets/grpc-dash.jpg
deleted file mode 100644
index 878de77..0000000
Binary files a/assets/grpc-dash.jpg and /dev/null differ
diff --git a/assets/icon.png b/assets/icon.png
deleted file mode 100644
index e7d2260..0000000
Binary files a/assets/icon.png and /dev/null differ
diff --git a/assets/logo.png b/assets/logo.png
deleted file mode 100644
index 35a35cd..0000000
Binary files a/assets/logo.png and /dev/null differ
diff --git a/assets/tree.jpg b/assets/tree.jpg
deleted file mode 100644
index c5164eb..0000000
Binary files a/assets/tree.jpg and /dev/null differ
diff --git a/cli/cli.js b/cli/cli.js
new file mode 100755
index 0000000..7cef246
--- /dev/null
+++ b/cli/cli.js
@@ -0,0 +1,155 @@
+#!/usr/bin/env node
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+var _a, _b, _c, _d, _e, _f, _g;
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.config = void 0;
+// process.env.GRPC_NODE_TRACE = 'api,channel';
+// process.env.GRPC_NODE_VERBOSITY = 'DEBUG';
+var commander_1 = require("commander");
+var fs = __importStar(require("fs"));
+var yaml = __importStar(require("js-yaml"));
+var path_1 = __importDefault(require("path"));
+var loadTester_1 = __importDefault(require("../server/loadTester"));
+// import { generateHTML } from '../utils/generateHTML';
+var cluster_1 = __importDefault(require("../server/cluster"));
+var clientInterceptor = new loadTester_1.default();
+var otherOptions = { interceptors: [clientInterceptor.interceptor] };
+// function findService(
+// grpcObject: Record,
+// serviceName: string
+// ): Record | null {
+// console.log(`Searching for service ${serviceName}...`);
+// if (grpcObject[serviceName]) {
+// console.log(`Service ${serviceName} found at current level.`);
+// return grpcObject[serviceName];
+// }
+// for (const key in grpcObject) {
+// if (typeof grpcObject[key] === 'object') {
+// console.log(`Descending into ${key}...`);
+// const nestedService = findService(grpcObject[key], serviceName);
+// if (nestedService) {
+// console.log(`Service ${serviceName} found in ${key}.`);
+// return nestedService;
+// }
+// }
+// }
+// console.log(`Service ${serviceName} not found.`);
+// return null;
+// }
+commander_1.program
+ .option('-c, --config ', 'Path to the YAML configuration file')
+ .option('-d, --duration ', 'set the duration of the load test in seconds', '10')
+ .option('-p, --proto ', 'path to the .proto file')
+ .option('-s, --service ', 'name of the gRPC service')
+ .option('-m, --method ', 'name of the method to test')
+ .option('--payload ', 'path to a JavaScript file that exports the payload')
+ .option('--callback ', 'path to a JavaScript file that exports the callback function')
+ .parse(process.argv);
+var options = commander_1.program.opts();
+exports.config = {
+ duration: 10,
+ packageName: '',
+ protoPath: '',
+ serviceName: '',
+ methodName: '',
+ payloadPath: '',
+ callbackPath: '',
+ host: '',
+}; // Initialize with default values
+// If a YAML config file is provided, use it to override command-line options
+if (options.config) {
+ if (typeof options.config === 'string') {
+ var configPath = path_1.default.resolve(process.cwd(), options.config);
+ var yamlConfig = yaml.load(fs.readFileSync(configPath, 'utf8'));
+ exports.config = yamlConfig;
+ }
+ else {
+ console.log('Please provide a valid path to the YAML configuration file');
+ process.exit(1);
+ }
+}
+else {
+ exports.config = {
+ duration: parseInt((_a = options.duration) !== null && _a !== void 0 ? _a : '10', 10),
+ protoPath: (_b = options.proto) !== null && _b !== void 0 ? _b : '',
+ serviceName: (_c = options.service) !== null && _c !== void 0 ? _c : '',
+ methodName: (_d = options.method) !== null && _d !== void 0 ? _d : '',
+ payloadPath: (_e = options.payload) !== null && _e !== void 0 ? _e : '',
+ callbackPath: (_f = options.callback) !== null && _f !== void 0 ? _f : '',
+ host: (_g = options.host) !== null && _g !== void 0 ? _g : '',
+ };
+}
+// Load the gRPC Object
+// const packageDef = protoLoader.loadSync(
+// path.resolve(__dirname, config.protoPath ?? '')
+// );
+// const grpcObj = grpc.loadPackageDefinition(packageDef);
+// // Create the gRPC client stub
+// const pkg = grpcObj[config.packageName ?? ''];
+// // Check if the service exists
+// if (!pkg) {
+// console.error(
+// `Service "${config.serviceName}" not found in the loaded .proto file.`
+// );
+// process.exit(1); // Exit with an error code
+// }
+// const methodName = config.methodName;
+// export const service = pkg[config.serviceName ?? ''];
+// export const client = new service(
+// `localhost:50052`,
+// grpc.credentials.createInsecure()
+// );
+// const clientInterceptor = new MetricInterceptor();
+// const callOptions = { interceptors: [clientInterceptor.interceptor] };
+// Dynamically import payload and callback
+// const payload = require(path.resolve(__dirname, config.payloadPath ?? ''));
+// const callback = require(path.resolve(__dirname, config.callbackPath ?? ''));
+// setTimeout(async () => {
+// generateHTML(clientInterceptor.latencyData);
+// }, 4000);
+// Initialize LoadTestEngine and add the call
+// WHAT??
+// const engine = new LoadTestEngine(config);
+// engine.addCall(
+// client[methodName ?? ''].bind(client),
+// payload,
+// otherOptions,
+// callback,
+// 0
+// );
+// // Start and stop load testing based on the duration
+// engine.run();
+// setTimeout(async () => {
+// generateHTML(clientInterceptor.latencyData);
+// engine.stopAll();
+// }, config.duration * 1000);
+(0, cluster_1.default)().catch(function (err) {
+ console.error('An error occured: ', err);
+ process.exit(1);
+});
diff --git a/cli/cli.ts b/cli/cli.ts
new file mode 100644
index 0000000..b3945ed
--- /dev/null
+++ b/cli/cli.ts
@@ -0,0 +1,171 @@
+#!/usr/bin/env node
+
+// process.env.GRPC_NODE_TRACE = 'api,channel';
+// process.env.GRPC_NODE_VERBOSITY = 'DEBUG';
+import { program } from 'commander';
+import * as fs from 'fs';
+import * as yaml from 'js-yaml';
+import path from 'path';
+import * as grpc from '@grpc/grpc-js';
+import * as protoLoader from '@grpc/proto-loader';
+
+import {
+ LoadTestEngine,
+ LoadTestConfig,
+} from '../load-test-engine/load-test-engine';
+import MetricInterceptor from '../server/loadTester';
+// import { generateHTML } from '../utils/generateHTML';
+import loadT from '../server/cluster';
+
+let clientInterceptor = new MetricInterceptor();
+const otherOptions = { interceptors: [clientInterceptor.interceptor] };
+// function findService(
+// grpcObject: Record,
+// serviceName: string
+// ): Record | null {
+// console.log(`Searching for service ${serviceName}...`);
+
+// if (grpcObject[serviceName]) {
+// console.log(`Service ${serviceName} found at current level.`);
+// return grpcObject[serviceName];
+// }
+
+// for (const key in grpcObject) {
+// if (typeof grpcObject[key] === 'object') {
+// console.log(`Descending into ${key}...`);
+// const nestedService = findService(grpcObject[key], serviceName);
+// if (nestedService) {
+// console.log(`Service ${serviceName} found in ${key}.`);
+// return nestedService;
+// }
+// }
+// }
+
+// console.log(`Service ${serviceName} not found.`);
+// return null;
+// }
+
+program
+ .option('-c, --config ', 'Path to the YAML configuration file')
+ .option(
+ '-d, --duration ',
+ 'set the duration of the load test in seconds',
+ '10'
+ )
+ .option('-p, --proto ', 'path to the .proto file')
+ .option('-s, --service ', 'name of the gRPC service')
+ .option('-m, --method ', 'name of the method to test')
+ .option(
+ '--payload ',
+ 'path to a JavaScript file that exports the payload'
+ )
+ .option(
+ '--callback ',
+ 'path to a JavaScript file that exports the callback function'
+ )
+ .parse(process.argv);
+
+const options = program.opts();
+
+export let config: LoadTestConfig = {
+ duration: 10,
+ packageName: '',
+ protoPath: '',
+ serviceName: '',
+ methodName: '',
+ payloadPath: '',
+ callbackPath: '',
+ host: '',
+}; // Initialize with default values
+
+interface IYamlConfig extends LoadTestConfig {
+ protoPath?: string;
+ serviceName?: string;
+ packageName?: string;
+ methodName?: string;
+ payloadPath?: string;
+ callbackPath?: string;
+ host?: string;
+}
+// If a YAML config file is provided, use it to override command-line options
+if (options.config) {
+ if (typeof options.config === 'string') {
+ const configPath = path.resolve(process.cwd(), options.config);
+ const yamlConfig: IYamlConfig = yaml.load(
+ fs.readFileSync(configPath, 'utf8')
+ ) as IYamlConfig;
+ config = yamlConfig;
+ } else {
+ console.log('Please provide a valid path to the YAML configuration file');
+ process.exit(1);
+ }
+} else {
+ config = {
+ duration: parseInt(options.duration ?? '10', 10),
+ protoPath: options.proto ?? '',
+ serviceName: options.service ?? '',
+ methodName: options.method ?? '',
+ payloadPath: options.payload ?? '',
+ callbackPath: options.callback ?? '',
+ host: options.host ?? '',
+ };
+}
+// Load the gRPC Object
+// const packageDef = protoLoader.loadSync(
+// path.resolve(__dirname, config.protoPath ?? '')
+// );
+// const grpcObj = grpc.loadPackageDefinition(packageDef);
+
+// // Create the gRPC client stub
+// const pkg = grpcObj[config.packageName ?? ''];
+
+// // Check if the service exists
+// if (!pkg) {
+// console.error(
+// `Service "${config.serviceName}" not found in the loaded .proto file.`
+// );
+// process.exit(1); // Exit with an error code
+// }
+// const methodName = config.methodName;
+
+// export const service = pkg[config.serviceName ?? ''];
+
+// export const client = new service(
+// `localhost:50052`,
+// grpc.credentials.createInsecure()
+// );
+
+// const clientInterceptor = new MetricInterceptor();
+// const callOptions = { interceptors: [clientInterceptor.interceptor] };
+
+// Dynamically import payload and callback
+// const payload = require(path.resolve(__dirname, config.payloadPath ?? ''));
+// const callback = require(path.resolve(__dirname, config.callbackPath ?? ''));
+
+// setTimeout(async () => {
+// generateHTML(clientInterceptor.latencyData);
+// }, 4000);
+
+// Initialize LoadTestEngine and add the call
+// WHAT??
+// const engine = new LoadTestEngine(config);
+
+// engine.addCall(
+// client[methodName ?? ''].bind(client),
+// payload,
+// otherOptions,
+// callback,
+// 0
+// );
+
+// // Start and stop load testing based on the duration
+// engine.run();
+
+// setTimeout(async () => {
+// generateHTML(clientInterceptor.latencyData);
+// engine.stopAll();
+// }, config.duration * 1000);
+loadT().catch((err) => {
+ console.error('An error occured: ', err);
+ process.exit(1);
+});
diff --git a/cli/lt.js b/cli/lt.js
new file mode 100755
index 0000000..2f68b09
--- /dev/null
+++ b/cli/lt.js
@@ -0,0 +1,176 @@
+#!/usr/bin/env node
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.client = exports.service = void 0;
+// process.env.GRPC_NODE_TRACE = 'api,channel';
+// process.env.GRPC_NODE_VERBOSITY = 'DEBUG';
+var commander_1 = require("commander");
+var fs_1 = __importDefault(require("fs"));
+var js_yaml_1 = __importDefault(require("js-yaml"));
+var path_1 = __importDefault(require("path"));
+var grpc = __importStar(require("@grpc/grpc-js"));
+var protoLoader = __importStar(require("@grpc/proto-loader"));
+var load_test_engine_1 = require("../load-test-engine/load-test-engine");
+var loadTester_1 = __importDefault(require("../server/loadTester"));
+var generateHTML_1 = require("../utils/generateHTML");
+var clientInterceptor = new loadTester_1.default();
+var otherOptions = { interceptors: [clientInterceptor.interceptor] };
+// function findService(
+// grpcObject: Record,
+// serviceName: string
+// ): Record | null {
+// console.log(`Searching for service ${serviceName}...`);
+// if (grpcObject[serviceName]) {
+// console.log(`Service ${serviceName} found at current level.`);
+// return grpcObject[serviceName];
+// }
+// for (const key in grpcObject) {
+// if (typeof grpcObject[key] === 'object') {
+// console.log(`Descending into ${key}...`);
+// const nestedService = findService(grpcObject[key], serviceName);
+// if (nestedService) {
+// console.log(`Service ${serviceName} found in ${key}.`);
+// return nestedService;
+// }
+// }
+// }
+// console.log(`Service ${serviceName} not found.`);
+// return null;
+// }
+commander_1.program
+ .option('-c, --config ', 'Path to the YAML configuration file')
+ .option('-d, --duration ', 'set the duration of the load test in seconds', '10')
+ .option('-p, --proto ', 'path to the .proto file')
+ .option('-s, --service ', 'name of the gRPC service')
+ .option('-m, --method ', 'name of the method to test')
+ .option('--payload ', 'path to a JavaScript file that exports the payload')
+ .option('--callback ', 'path to a JavaScript file that exports the callback function')
+ .option('-h, --host ', 'host to connect to', 'localhost')
+ .parse(process.argv);
+var options = commander_1.program.opts();
+var config = {
+ duration: 10,
+ packageName: '',
+ protoPath: '',
+ serviceName: '',
+ methodName: '',
+ payloadPath: '',
+ callbackPath: '',
+ host: '',
+}; // Initialize with default values
+// If a YAML config file is provided, use it to override command-line options
+if (options.config) {
+ if (typeof options.config === 'string') {
+ var configPath = path_1.default.resolve(process.cwd(), options.config);
+ var yamlConfig = js_yaml_1.default.load(fs_1.default.readFileSync(configPath, 'utf8'));
+ config = yamlConfig;
+ }
+ else {
+ console.log('Please provide a valid path to the YAML configuration file');
+ process.exit(1);
+ }
+}
+else {
+ config = {
+ duration: parseInt((_a = options.duration) !== null && _a !== void 0 ? _a : '10', 10),
+ protoPath: (_b = options.proto) !== null && _b !== void 0 ? _b : '',
+ serviceName: (_c = options.service) !== null && _c !== void 0 ? _c : '',
+ methodName: (_d = options.method) !== null && _d !== void 0 ? _d : '',
+ payloadPath: (_e = options.payload) !== null && _e !== void 0 ? _e : '',
+ callbackPath: (_f = options.callback) !== null && _f !== void 0 ? _f : '',
+ host: (_g = options.host) !== null && _g !== void 0 ? _g : '',
+ };
+}
+// Load the gRPC Object
+var packageDef = protoLoader.loadSync(path_1.default.resolve(__dirname, (_h = config.protoPath) !== null && _h !== void 0 ? _h : ''));
+var grpcObj = grpc.loadPackageDefinition(packageDef);
+// Create the gRPC client stub
+var pkg = grpcObj[(_j = config.packageName) !== null && _j !== void 0 ? _j : ''];
+// Check if the service exists
+if (!pkg) {
+ console.error("Service \"".concat(config.serviceName, "\" not found in the loaded .proto file."));
+ process.exit(1); // Exit with an error code
+}
+var methodName = config.methodName;
+exports.service = pkg[(_k = config.serviceName) !== null && _k !== void 0 ? _k : ''];
+exports.client = new exports.service("localhost:".concat(config.host), grpc.credentials.createInsecure());
+// const clientInterceptor = new MetricInterceptor();
+// const callOptions = { interceptors: [clientInterceptor.interceptor] };
+// Dynamically import payload and callback
+var payload = require(path_1.default.resolve(__dirname, (_l = config.payloadPath) !== null && _l !== void 0 ? _l : ''));
+var callback = require(path_1.default.resolve(__dirname, (_m = config.callbackPath) !== null && _m !== void 0 ? _m : ''));
+// Initialize LoadTestEngine and add the call
+var engine = new load_test_engine_1.LoadTestEngine(config);
+engine.addCall(exports.client[methodName !== null && methodName !== void 0 ? methodName : ''].bind(exports.client), payload, otherOptions, callback, 0);
+// // Start and stop load testing based on the duration
+engine.run();
+setTimeout(function () { return __awaiter(void 0, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ (0, generateHTML_1.generateHTML)(clientInterceptor.latencyData);
+ engine.stopAll();
+ return [2 /*return*/];
+ });
+}); }, config.duration * 1000);
diff --git a/cli/lt.ts b/cli/lt.ts
new file mode 100644
index 0000000..705ba12
--- /dev/null
+++ b/cli/lt.ts
@@ -0,0 +1,164 @@
+#!/usr/bin/env node
+
+// process.env.GRPC_NODE_TRACE = 'api,channel';
+// process.env.GRPC_NODE_VERBOSITY = 'DEBUG';
+import { program } from 'commander';
+import fs from 'fs';
+import yaml from 'js-yaml';
+import path from 'path';
+import * as grpc from '@grpc/grpc-js';
+import * as protoLoader from '@grpc/proto-loader';
+
+import {
+ LoadTestEngine,
+ LoadTestConfig,
+} from '../load-test-engine/load-test-engine';
+import MetricInterceptor from '../server/loadTester';
+import { generateHTML } from '../utils/generateHTML';
+
+let clientInterceptor = new MetricInterceptor();
+const otherOptions = { interceptors: [clientInterceptor.interceptor] };
+import loadT from '../server/cluster';
+// function findService(
+// grpcObject: Record,
+// serviceName: string
+// ): Record | null {
+// console.log(`Searching for service ${serviceName}...`);
+
+// if (grpcObject[serviceName]) {
+// console.log(`Service ${serviceName} found at current level.`);
+// return grpcObject[serviceName];
+// }
+
+// for (const key in grpcObject) {
+// if (typeof grpcObject[key] === 'object') {
+// console.log(`Descending into ${key}...`);
+// const nestedService = findService(grpcObject[key], serviceName);
+// if (nestedService) {
+// console.log(`Service ${serviceName} found in ${key}.`);
+// return nestedService;
+// }
+// }
+// }
+
+// console.log(`Service ${serviceName} not found.`);
+// return null;
+// }
+
+program
+ .option('-c, --config ', 'Path to the YAML configuration file')
+ .option(
+ '-d, --duration ',
+ 'set the duration of the load test in seconds',
+ '10'
+ )
+ .option('-p, --proto ', 'path to the .proto file')
+ .option('-s, --service ', 'name of the gRPC service')
+ .option('-m, --method ', 'name of the method to test')
+ .option(
+ '--payload ',
+ 'path to a JavaScript file that exports the payload'
+ )
+ .option(
+ '--callback ',
+ 'path to a JavaScript file that exports the callback function'
+ )
+ .option('-h, --host ', 'host to connect to', 'localhost')
+ .parse(process.argv);
+
+const options = program.opts();
+
+let config: LoadTestConfig = {
+ duration: 10,
+ packageName: '',
+ protoPath: '',
+ serviceName: '',
+ methodName: '',
+ payloadPath: '',
+ callbackPath: '',
+ host: '',
+}; // Initialize with default values
+
+interface IYamlConfig extends LoadTestConfig {
+ protoPath?: string;
+ serviceName?: string;
+ packageName?: string;
+ methodName?: string;
+ payloadPath?: string;
+ callbackPath?: string;
+ host?: string;
+}
+// If a YAML config file is provided, use it to override command-line options
+if (options.config) {
+ if (typeof options.config === 'string') {
+ const configPath = path.resolve(process.cwd(), options.config);
+ const yamlConfig: IYamlConfig = yaml.load(
+ fs.readFileSync(configPath, 'utf8')
+ ) as IYamlConfig;
+ config = yamlConfig;
+ } else {
+ console.log('Please provide a valid path to the YAML configuration file');
+ process.exit(1);
+ }
+} else {
+ config = {
+ duration: parseInt(options.duration ?? '10', 10),
+ protoPath: options.proto ?? '',
+ serviceName: options.service ?? '',
+ methodName: options.method ?? '',
+ payloadPath: options.payload ?? '',
+ callbackPath: options.callback ?? '',
+ host: options.host ?? '',
+ };
+}
+// Load the gRPC Object
+const packageDef = protoLoader.loadSync(
+ path.resolve(__dirname, config.protoPath ?? '')
+);
+const grpcObj = grpc.loadPackageDefinition(packageDef);
+
+// Create the gRPC client stub
+const pkg = grpcObj[config.packageName ?? ''];
+
+// Check if the service exists
+if (!pkg) {
+ console.error(
+ `Service "${config.serviceName}" not found in the loaded .proto file.`
+ );
+ process.exit(1); // Exit with an error code
+}
+const methodName = config.methodName;
+
+export const service = pkg[config.serviceName ?? ''];
+
+export const client = new service(
+ `localhost:${config.host}`,
+ grpc.credentials.createInsecure()
+);
+
+// const clientInterceptor = new MetricInterceptor();
+// const callOptions = { interceptors: [clientInterceptor.interceptor] };
+
+// Dynamically import payload and callback
+const payload = require(path.resolve(__dirname, config.payloadPath ?? ''));
+const callback = require(path.resolve(__dirname, config.callbackPath ?? ''));
+
+// Initialize LoadTestEngine and add the call
+
+const engine = new LoadTestEngine(config);
+
+engine.addCall(
+ client[methodName ?? ''].bind(client),
+ payload,
+ otherOptions,
+ callback,
+ 0
+);
+
+// // Start and stop load testing based on the duration
+engine.run();
+
+setTimeout(async () => {
+ generateHTML(clientInterceptor.latencyData);
+ engine.stopAll();
+}, config.duration * 1000);
diff --git a/coverage/clover.xml b/coverage/clover.xml
deleted file mode 100644
index 507b0d0..0000000
--- a/coverage/clover.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json
deleted file mode 100644
index 0967ef4..0000000
--- a/coverage/coverage-final.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css
deleted file mode 100644
index f418035..0000000
--- a/coverage/lcov-report/base.css
+++ /dev/null
@@ -1,224 +0,0 @@
-body, html {
- margin:0; padding: 0;
- height: 100%;
-}
-body {
- font-family: Helvetica Neue, Helvetica, Arial;
- font-size: 14px;
- color:#333;
-}
-.small { font-size: 12px; }
-*, *:after, *:before {
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- box-sizing:border-box;
- }
-h1 { font-size: 20px; margin: 0;}
-h2 { font-size: 14px; }
-pre {
- font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
- margin: 0;
- padding: 0;
- -moz-tab-size: 2;
- -o-tab-size: 2;
- tab-size: 2;
-}
-a { color:#0074D9; text-decoration:none; }
-a:hover { text-decoration:underline; }
-.strong { font-weight: bold; }
-.space-top1 { padding: 10px 0 0 0; }
-.pad2y { padding: 20px 0; }
-.pad1y { padding: 10px 0; }
-.pad2x { padding: 0 20px; }
-.pad2 { padding: 20px; }
-.pad1 { padding: 10px; }
-.space-left2 { padding-left:55px; }
-.space-right2 { padding-right:20px; }
-.center { text-align:center; }
-.clearfix { display:block; }
-.clearfix:after {
- content:'';
- display:block;
- height:0;
- clear:both;
- visibility:hidden;
- }
-.fl { float: left; }
-@media only screen and (max-width:640px) {
- .col3 { width:100%; max-width:100%; }
- .hide-mobile { display:none!important; }
-}
-
-.quiet {
- color: #7f7f7f;
- color: rgba(0,0,0,0.5);
-}
-.quiet a { opacity: 0.7; }
-
-.fraction {
- font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
- font-size: 10px;
- color: #555;
- background: #E8E8E8;
- padding: 4px 5px;
- border-radius: 3px;
- vertical-align: middle;
-}
-
-div.path a:link, div.path a:visited { color: #333; }
-table.coverage {
- border-collapse: collapse;
- margin: 10px 0 0 0;
- padding: 0;
-}
-
-table.coverage td {
- margin: 0;
- padding: 0;
- vertical-align: top;
-}
-table.coverage td.line-count {
- text-align: right;
- padding: 0 5px 0 20px;
-}
-table.coverage td.line-coverage {
- text-align: right;
- padding-right: 10px;
- min-width:20px;
-}
-
-table.coverage td span.cline-any {
- display: inline-block;
- padding: 0 5px;
- width: 100%;
-}
-.missing-if-branch {
- display: inline-block;
- margin-right: 5px;
- border-radius: 3px;
- position: relative;
- padding: 0 4px;
- background: #333;
- color: yellow;
-}
-
-.skip-if-branch {
- display: none;
- margin-right: 10px;
- position: relative;
- padding: 0 4px;
- background: #ccc;
- color: white;
-}
-.missing-if-branch .typ, .skip-if-branch .typ {
- color: inherit !important;
-}
-.coverage-summary {
- border-collapse: collapse;
- width: 100%;
-}
-.coverage-summary tr { border-bottom: 1px solid #bbb; }
-.keyline-all { border: 1px solid #ddd; }
-.coverage-summary td, .coverage-summary th { padding: 10px; }
-.coverage-summary tbody { border: 1px solid #bbb; }
-.coverage-summary td { border-right: 1px solid #bbb; }
-.coverage-summary td:last-child { border-right: none; }
-.coverage-summary th {
- text-align: left;
- font-weight: normal;
- white-space: nowrap;
-}
-.coverage-summary th.file { border-right: none !important; }
-.coverage-summary th.pct { }
-.coverage-summary th.pic,
-.coverage-summary th.abs,
-.coverage-summary td.pct,
-.coverage-summary td.abs { text-align: right; }
-.coverage-summary td.file { white-space: nowrap; }
-.coverage-summary td.pic { min-width: 120px !important; }
-.coverage-summary tfoot td { }
-
-.coverage-summary .sorter {
- height: 10px;
- width: 7px;
- display: inline-block;
- margin-left: 0.5em;
- background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
-}
-.coverage-summary .sorted .sorter {
- background-position: 0 -20px;
-}
-.coverage-summary .sorted-desc .sorter {
- background-position: 0 -10px;
-}
-.status-line { height: 10px; }
-/* yellow */
-.cbranch-no { background: yellow !important; color: #111; }
-/* dark red */
-.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
-.low .chart { border:1px solid #C21F39 }
-.highlighted,
-.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
- background: #C21F39 !important;
-}
-/* medium red */
-.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
-/* light red */
-.low, .cline-no { background:#FCE1E5 }
-/* light green */
-.high, .cline-yes { background:rgb(230,245,208) }
-/* medium green */
-.cstat-yes { background:rgb(161,215,106) }
-/* dark green */
-.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
-.high .chart { border:1px solid rgb(77,146,33) }
-/* dark yellow (gold) */
-.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
-.medium .chart { border:1px solid #f9cd0b; }
-/* light yellow */
-.medium { background: #fff4c2; }
-
-.cstat-skip { background: #ddd; color: #111; }
-.fstat-skip { background: #ddd; color: #111 !important; }
-.cbranch-skip { background: #ddd !important; color: #111; }
-
-span.cline-neutral { background: #eaeaea; }
-
-.coverage-summary td.empty {
- opacity: .5;
- padding-top: 4px;
- padding-bottom: 4px;
- line-height: 1;
- color: #888;
-}
-
-.cover-fill, .cover-empty {
- display:inline-block;
- height: 12px;
-}
-.chart {
- line-height: 0;
-}
-.cover-empty {
- background: white;
-}
-.cover-full {
- border-right: none !important;
-}
-pre.prettyprint {
- border: none !important;
- padding: 0 !important;
- margin: 0 !important;
-}
-.com { color: #999 !important; }
-.ignore-none { color: #999; font-weight: normal; }
-
-.wrapper {
- min-height: 100%;
- height: auto !important;
- height: 100%;
- margin: 0 auto -48px;
-}
-.footer, .push {
- height: 48px;
-}
diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js
deleted file mode 100644
index cc12130..0000000
--- a/coverage/lcov-report/block-navigation.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/* eslint-disable */
-var jumpToCode = (function init() {
- // Classes of code we would like to highlight in the file view
- var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
-
- // Elements to highlight in the file listing view
- var fileListingElements = ['td.pct.low'];
-
- // We don't want to select elements that are direct descendants of another match
- var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
-
- // Selecter that finds elements on the page to which we can jump
- var selector =
- fileListingElements.join(', ') +
- ', ' +
- notSelector +
- missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
-
- // The NodeList of matching elements
- var missingCoverageElements = document.querySelectorAll(selector);
-
- var currentIndex;
-
- function toggleClass(index) {
- missingCoverageElements
- .item(currentIndex)
- .classList.remove('highlighted');
- missingCoverageElements.item(index).classList.add('highlighted');
- }
-
- function makeCurrent(index) {
- toggleClass(index);
- currentIndex = index;
- missingCoverageElements.item(index).scrollIntoView({
- behavior: 'smooth',
- block: 'center',
- inline: 'center'
- });
- }
-
- function goToPrevious() {
- var nextIndex = 0;
- if (typeof currentIndex !== 'number' || currentIndex === 0) {
- nextIndex = missingCoverageElements.length - 1;
- } else if (missingCoverageElements.length > 1) {
- nextIndex = currentIndex - 1;
- }
-
- makeCurrent(nextIndex);
- }
-
- function goToNext() {
- var nextIndex = 0;
-
- if (
- typeof currentIndex === 'number' &&
- currentIndex < missingCoverageElements.length - 1
- ) {
- nextIndex = currentIndex + 1;
- }
-
- makeCurrent(nextIndex);
- }
-
- return function jump(event) {
- if (
- document.getElementById('fileSearch') === document.activeElement &&
- document.activeElement != null
- ) {
- // if we're currently focused on the search input, we don't want to navigate
- return;
- }
-
- switch (event.which) {
- case 78: // n
- case 74: // j
- goToNext();
- break;
- case 66: // b
- case 75: // k
- case 80: // p
- goToPrevious();
- break;
- }
- };
-})();
-window.addEventListener('keydown', jumpToCode);
diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png
deleted file mode 100644
index c1525b8..0000000
Binary files a/coverage/lcov-report/favicon.png and /dev/null differ
diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html
deleted file mode 100644
index ec38652..0000000
--- a/coverage/lcov-report/index.html
+++ /dev/null
@@ -1,101 +0,0 @@
-
-
-
-
-
- Code coverage report for All files
-
-
-
-
-
-
-
-
-
-
-
-
All files
-
-
-
- Unknown%
- Statements
- 0/0
-
-
-
-
- Unknown%
- Branches
- 0/0
-
-
-
-
- Unknown%
- Functions
- 0/0
-
-
-
-
- Unknown%
- Lines
- 0/0
-
-
-
-
-
- Press n or j to go to the next uncovered block, b, p or k for the previous block.
-