diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..9b1c8b1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +/dist diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..767297a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": ["oclif", "oclif-typescript", "prettier"], + "rules": { + "no-useless-constructor": "off" + } +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0ef035d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,22 @@ +version: 2 +updates: + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'weekly' + day: 'saturday' + versioning-strategy: 'increase' + labels: + - 'dependencies' + open-pull-requests-limit: 5 + pull-request-branch-name: + separator: '-' + commit-message: + # cause a release for non-dev-deps + prefix: fix(deps) + # no release for dev-deps + prefix-development: chore(dev-deps) + ignore: + - dependency-name: '@salesforce/dev-scripts' + - dependency-name: '*' + update-types: ['version-update:semver-major'] diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000..796eafa --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,10 @@ +name: automerge +on: + workflow_dispatch: + schedule: + - cron: '17 2,5,8,11 * * *' + +jobs: + automerge: + uses: oclif/github-workflows/.github/workflows/automerge.yml@main + secrets: inherit diff --git a/.github/workflows/failureNotifications.yml b/.github/workflows/failureNotifications.yml new file mode 100644 index 0000000..9243031 --- /dev/null +++ b/.github/workflows/failureNotifications.yml @@ -0,0 +1,43 @@ +name: failureNotifications + +on: + workflow_run: + workflows: + - version, tag and github release + - publish + types: + - completed + +jobs: + failure-notify: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - name: Announce Failure + id: slack + uses: slackapi/slack-github-action@v1.24.0 + env: + # for non-CLI-team-owned plugins, you can send this anywhere you like + SLACK_WEBHOOK_URL: ${{ secrets.CLI_ALERTS_SLACK_WEBHOOK }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + with: + payload: | + { + "text": "${{ github.event.workflow_run.name }} failed: ${{ github.event.workflow_run.repository.name }}", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": ":bh-alert: ${{ github.event.workflow_run.name }} failed: ${{ github.event.workflow_run.repository.name }} :bh-alert:" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Repo: ${{ github.event.workflow_run.repository.html_url }}\nWorkflow name: `${{ github.event.workflow_run.name }}`\nJob url: ${{ github.event.workflow_run.html_url }}" + } + } + ] + } diff --git a/.github/workflows/manualRelease.yml b/.github/workflows/manualRelease.yml new file mode 100644 index 0000000..8d8f05c --- /dev/null +++ b/.github/workflows/manualRelease.yml @@ -0,0 +1,36 @@ +name: manual release + +on: + workflow_dispatch: + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + - name: Conventional Changelog Action + id: changelog + uses: TriPSs/conventional-changelog-action@d360fad3a42feca6462f72c97c165d60a02d4bf2 + # overriding some of the basic behaviors to just get the changelog + with: + git-user-name: svc-cli-bot + git-user-email: svc_cli_bot@salesforce.com + github-token: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + output-file: false + # always do the release, even if there are no semantic commits + skip-on-empty: false + tag-prefix: '' + - uses: notiz-dev/github-action-json-property@7a701887f4b568b23eb7b78bb0fc49aaeb1b68d3 + id: packageVersion + with: + path: 'package.json' + prop_path: 'version' + - name: Create Github Release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.SVC_CLI_BOT_GITHUB_TOKEN }} + with: + tag_name: ${{ steps.packageVersion.outputs.prop }} + release_name: ${{ steps.packageVersion.outputs.prop }} diff --git a/.github/workflows/notify-slack-on-pr-open.yml b/.github/workflows/notify-slack-on-pr-open.yml new file mode 100644 index 0000000..13b5c9e --- /dev/null +++ b/.github/workflows/notify-slack-on-pr-open.yml @@ -0,0 +1,23 @@ +name: Pull Request Slack Notification + +on: + pull_request: + types: [opened, reopened] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Notify Slack on PR open + env: + WEBHOOK_URL : ${{ secrets.CLI_TEAM_SLACK_WEBHOOK_URL }} + PULL_REQUEST_AUTHOR_ICON_URL : ${{ github.event.pull_request.user.avatar_url }} + PULL_REQUEST_AUTHOR_NAME : ${{ github.event.pull_request.user.login }} + PULL_REQUEST_AUTHOR_PROFILE_URL: ${{ github.event.pull_request.user.html_url }} + PULL_REQUEST_BASE_BRANCH_NAME : ${{ github.event.pull_request.base.ref }} + PULL_REQUEST_COMPARE_BRANCH_NAME : ${{ github.event.pull_request.head.ref }} + PULL_REQUEST_NUMBER : ${{ github.event.pull_request.number }} + PULL_REQUEST_REPO: ${{ github.event.pull_request.head.repo.name }} + PULL_REQUEST_TITLE : ${{ github.event.pull_request.title }} + PULL_REQUEST_URL : ${{ github.event.pull_request.html_url }} + uses: salesforcecli/github-workflows/.github/actions/prNotification@main diff --git a/.github/workflows/onPushToMain.yml b/.github/workflows/onPushToMain.yml new file mode 100644 index 0000000..61eda8a --- /dev/null +++ b/.github/workflows/onPushToMain.yml @@ -0,0 +1,18 @@ +# test +name: version, tag and github release + +on: + push: + branches: [main] + +jobs: + release: + uses: oclif/github-workflows/.github/workflows/githubRelease.yml@main + secrets: inherit + + # most repos won't use this + # depends on previous job to avoid git collisions, not for any functionality reason + # docs: + # uses: salesforcecli/github-workflows/.github/workflows/publishTypedoc.yml@main + # secrets: inherit + # needs: release diff --git a/.github/workflows/onRelease.yml b/.github/workflows/onRelease.yml new file mode 100644 index 0000000..8876db4 --- /dev/null +++ b/.github/workflows/onRelease.yml @@ -0,0 +1,19 @@ +name: publish + +on: + release: + types: [released] + # support manual release in case something goes wrong and needs to be repeated or tested + workflow_dispatch: + inputs: + tag: + description: tag that needs to publish + type: string + required: true +jobs: + npm: + uses: oclif/github-workflows/.github/workflows/npmPublish.yml@main + with: + tag: latest + githubTag: ${{ github.event.release.tag_name || inputs.tag }} + secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4286a55 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,9 @@ +name: tests +on: + push: + branches-ignore: [main] + workflow_dispatch: + +jobs: + unit-tests: + uses: oclif/github-workflows/.github/workflows/unitTest.yml@main diff --git a/.gitignore b/.gitignore index 75d4433..d05954a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,13 @@ -.idea -dist -.pytest_cache -**/__pycache__ -.coverage -htmlcov +**/.DS_Store +*-debug.log +*-error.log +/.idea +/.nyc_output +/dist +/lib +/package-lock.json +/tmp +/yarn.lock +node_modules +oclif.lock +oclif.manifest.json diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..2febd2c --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,11 @@ +{ + "require": [ + "ts-node/register" + ], + "watch-extensions": [ + "ts" + ], + "recursive": true, + "reporter": "spec", + "timeout": 60000 +} diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..2c36974 --- /dev/null +++ b/.nycrc @@ -0,0 +1,15 @@ +{ + "extension": [ + ".ts", + ".tsx" + ], + "exclude": [ + "**/*.d.ts", + "test/**/*.ts" + ], + "reporter": [ + "lcov", + "text-summary" + ], + "all": true +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..6314335 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +"@oclif/prettier-config" diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..85d5d03 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Execute Command", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/bin/dev", + "args": [ + "hello", + "world", + ], + } + ] +} diff --git a/README.md b/README.md index 35fd766..696fc45 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,380 @@ -# track - A toggl Track personal CLI +oclif-hello-world +================= -![Use demonstration](docs/demo.png) +oclif example Hello World CLI -## Install -Add to your .zshenv: -```env -export TOGGL_API_TOKEN="email:password" -export TOGGL_WORKSPACE_ID=1234567890 -export TOGGL_DEFAULT_TIME_ENTRY="Doing stuff" -export TOGGL_DEFAULT_PROJECT=1234567890 +[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io) +[![CircleCI](https://circleci.com/gh/oclif/hello-world/tree/main.svg?style=shield)](https://circleci.com/gh/oclif/hello-world/tree/main) +[![GitHub license](https://img.shields.io/github/license/oclif/hello-world)](https://github.com/oclif/hello-world/blob/main/LICENSE) + + +* [Usage](#usage) +* [Commands](#commands) + +# Usage + +```sh-session +$ npm install -g track +$ track COMMAND +running command... +$ track (--version) +track/0.0.0 darwin-arm64 node-v20.2.0 +$ track --help [COMMAND] +USAGE + $ track COMMAND +... +``` + +# Commands + +* [`track hello PERSON`](#track-hello-person) +* [`track hello world`](#track-hello-world) +* [`track help [COMMANDS]`](#track-help-commands) +* [`track plugins`](#track-plugins) +* [`track plugins:install PLUGIN...`](#track-pluginsinstall-plugin) +* [`track plugins:inspect PLUGIN...`](#track-pluginsinspect-plugin) +* [`track plugins:install PLUGIN...`](#track-pluginsinstall-plugin-1) +* [`track plugins:link PLUGIN`](#track-pluginslink-plugin) +* [`track plugins:uninstall PLUGIN...`](#track-pluginsuninstall-plugin) +* [`track plugins reset`](#track-plugins-reset) +* [`track plugins:uninstall PLUGIN...`](#track-pluginsuninstall-plugin-1) +* [`track plugins:uninstall PLUGIN...`](#track-pluginsuninstall-plugin-2) +* [`track plugins update`](#track-plugins-update) + +## `track hello PERSON` + +Say hello + +``` +USAGE + $ track hello PERSON -f + +ARGUMENTS + PERSON Person to say hello to + +FLAGS + -f, --from= (required) Who is saying hello + +DESCRIPTION + Say hello + +EXAMPLES + $ oex hello friend --from oclif + hello friend from oclif! (./src/commands/hello/index.ts) +``` + +_See code: [src/commands/hello/index.ts](https://github.com/ulisesantana/track/blob/v0.0.0/src/commands/hello/index.ts)_ + +## `track hello world` + +Say hello world + +``` +USAGE + $ track hello world + +DESCRIPTION + Say hello world + +EXAMPLES + $ track hello world + hello world! (./src/commands/hello/world.ts) ``` -Install in your shell (requires Python >= 3.9.6): -```shell -poetry build -pip install dist/track-0.1.0.tar.gz +_See code: [src/commands/hello/world.ts](https://github.com/ulisesantana/track/blob/v0.0.0/src/commands/hello/world.ts)_ + +## `track help [COMMANDS]` + +Display help for track. + +``` +USAGE + $ track help [COMMANDS] [-n] + +ARGUMENTS + COMMANDS Command to show help for. + +FLAGS + -n, --nested-commands Include all nested commands in the output. + +DESCRIPTION + Display help for track. +``` + +_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.2.20/src/commands/help.ts)_ + +## `track plugins` + +List installed plugins. + +``` +USAGE + $ track plugins [--json] [--core] + +FLAGS + --core Show core plugins. + +GLOBAL FLAGS + --json Format output as json. + +DESCRIPTION + List installed plugins. + +EXAMPLES + $ track plugins ``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/index.ts)_ + +## `track plugins:install PLUGIN...` + +Installs a plugin into the CLI. + +``` +USAGE + $ track plugins:install PLUGIN... + +ARGUMENTS + PLUGIN Plugin to install. + +FLAGS + -f, --force Run yarn install with force flag. + -h, --help Show CLI help. + -s, --silent Silences yarn output. + -v, --verbose Show verbose yarn output. + +GLOBAL FLAGS + --json Format output as json. + +DESCRIPTION + Installs a plugin into the CLI. + Can be installed from npm or a git url. + + Installation of a user-installed plugin will override a core plugin. + + e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command + will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in + the CLI without the need to patch and update the whole CLI. + + +ALIASES + $ track plugins add + +EXAMPLES + $ track plugins add myplugin + + $ track plugins add https://github.com/someuser/someplugin + + $ track plugins add someuser/someplugin +``` + +## `track plugins:inspect PLUGIN...` + +Displays installation properties of a plugin. + +``` +USAGE + $ track plugins:inspect PLUGIN... + +ARGUMENTS + PLUGIN [default: .] Plugin to inspect. + +FLAGS + -h, --help Show CLI help. + -v, --verbose + +GLOBAL FLAGS + --json Format output as json. + +DESCRIPTION + Displays installation properties of a plugin. + +EXAMPLES + $ track plugins inspect myplugin +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/inspect.ts)_ + +## `track plugins:install PLUGIN...` + +Installs a plugin into the CLI. + +``` +USAGE + $ track plugins:install PLUGIN... + +ARGUMENTS + PLUGIN Plugin to install. + +FLAGS + -f, --force Run yarn install with force flag. + -h, --help Show CLI help. + -s, --silent Silences yarn output. + -v, --verbose Show verbose yarn output. + +GLOBAL FLAGS + --json Format output as json. + +DESCRIPTION + Installs a plugin into the CLI. + Can be installed from npm or a git url. + + Installation of a user-installed plugin will override a core plugin. + + e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command + will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in + the CLI without the need to patch and update the whole CLI. + + +ALIASES + $ track plugins add + +EXAMPLES + $ track plugins install myplugin + + $ track plugins install https://github.com/someuser/someplugin + + $ track plugins install someuser/someplugin +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/install.ts)_ + +## `track plugins:link PLUGIN` + +Links a plugin into the CLI for development. + +``` +USAGE + $ track plugins:link PLUGIN + +ARGUMENTS + PATH [default: .] path to plugin + +FLAGS + -h, --help Show CLI help. + -v, --verbose + --[no-]install Install dependencies after linking the plugin. + +DESCRIPTION + Links a plugin into the CLI for development. + Installation of a linked plugin will override a user-installed or core plugin. + + e.g. If you have a user-installed or core plugin that has a 'hello' command, installing a linked plugin with a 'hello' + command will override the user-installed or core plugin implementation. This is useful for development work. + + +EXAMPLES + $ track plugins link myplugin +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/link.ts)_ + +## `track plugins:uninstall PLUGIN...` + +Removes a plugin from the CLI. + +``` +USAGE + $ track plugins:uninstall PLUGIN... + +ARGUMENTS + PLUGIN plugin to uninstall + +FLAGS + -h, --help Show CLI help. + -v, --verbose + +DESCRIPTION + Removes a plugin from the CLI. + +ALIASES + $ track plugins unlink + $ track plugins remove + +EXAMPLES + $ track plugins remove myplugin +``` + +## `track plugins reset` + +Remove all user-installed and linked plugins. + +``` +USAGE + $ track plugins reset +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/reset.ts)_ + +## `track plugins:uninstall PLUGIN...` + +Removes a plugin from the CLI. + +``` +USAGE + $ track plugins:uninstall PLUGIN... + +ARGUMENTS + PLUGIN plugin to uninstall + +FLAGS + -h, --help Show CLI help. + -v, --verbose + +DESCRIPTION + Removes a plugin from the CLI. + +ALIASES + $ track plugins unlink + $ track plugins remove + +EXAMPLES + $ track plugins uninstall myplugin +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/uninstall.ts)_ + +## `track plugins:uninstall PLUGIN...` + +Removes a plugin from the CLI. + +``` +USAGE + $ track plugins:uninstall PLUGIN... + +ARGUMENTS + PLUGIN plugin to uninstall + +FLAGS + -h, --help Show CLI help. + -v, --verbose + +DESCRIPTION + Removes a plugin from the CLI. + +ALIASES + $ track plugins unlink + $ track plugins remove + +EXAMPLES + $ track plugins unlink myplugin +``` + +## `track plugins update` + +Update installed plugins. + +``` +USAGE + $ track plugins update [-h] [-v] + +FLAGS + -h, --help Show CLI help. + -v, --verbose + +DESCRIPTION + Update installed plugins. +``` + +_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.1.8/src/commands/plugins/update.ts)_ + diff --git a/bin/dev.cmd b/bin/dev.cmd new file mode 100644 index 0000000..077b57a --- /dev/null +++ b/bin/dev.cmd @@ -0,0 +1,3 @@ +@echo off + +node "%~dp0\dev" %* \ No newline at end of file diff --git a/bin/dev.js b/bin/dev.js new file mode 100755 index 0000000..93e1c6a --- /dev/null +++ b/bin/dev.js @@ -0,0 +1,6 @@ +#!/usr/bin/env ts-node +// eslint-disable-next-line node/shebang, unicorn/prefer-top-level-await +(async () => { + const oclif = await import('@oclif/core') + await oclif.execute({development: true, dir: __dirname}) +})() diff --git a/bin/run.cmd b/bin/run.cmd new file mode 100644 index 0000000..968fc30 --- /dev/null +++ b/bin/run.cmd @@ -0,0 +1,3 @@ +@echo off + +node "%~dp0\run" %* diff --git a/bin/run.js b/bin/run.js new file mode 100755 index 0000000..405685d --- /dev/null +++ b/bin/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +// eslint-disable-next-line unicorn/prefer-top-level-await +(async () => { + const oclif = await import('@oclif/core') + await oclif.execute({development: false, dir: __dirname}) +})() diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css new file mode 100644 index 0000000..f418035 --- /dev/null +++ b/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +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/bin/dev.js.html b/coverage/lcov-report/bin/dev.js.html new file mode 100644 index 0000000..7f0eb07 --- /dev/null +++ b/coverage/lcov-report/bin/dev.js.html @@ -0,0 +1,103 @@ + + + + + + Code coverage report for bin/dev.js + + + + + + + + + +
+
+

All files / bin dev.js

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7  +  +  +  +  +  + 
#!/usr/bin/env ts-node
+// eslint-disable-next-line node/shebang, unicorn/prefer-top-level-await
+(async () => {
+  const oclif = await import('@oclif/core')
+  await oclif.execute({development: true, dir: __dirname})
+})()
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/bin/index.html b/coverage/lcov-report/bin/index.html new file mode 100644 index 0000000..3e0e357 --- /dev/null +++ b/coverage/lcov-report/bin/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for bin + + + + + + + + + +
+
+

All files bin

+
+ +
+ 0% + Statements + 0/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
dev.js +
+
0%0/3100%0/00%0/10%0/3
run.js +
+
0%0/3100%0/00%0/10%0/3
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/bin/run.js.html b/coverage/lcov-report/bin/run.js.html new file mode 100644 index 0000000..6dae427 --- /dev/null +++ b/coverage/lcov-report/bin/run.js.html @@ -0,0 +1,106 @@ + + + + + + Code coverage report for bin/run.js + + + + + + + + + +
+
+

All files / bin run.js

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8  +  +  +  +  +  +  + 
#!/usr/bin/env node
+ 
+// eslint-disable-next-line unicorn/prefer-top-level-await
+(async () => {
+  const oclif = await import('@oclif/core')
+  await oclif.execute({development: false, dir: __dirname})
+})()
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js new file mode 100644 index 0000000..cc12130 --- /dev/null +++ b/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* 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/coverage/lcov-report/block-navigation.js.html b/coverage/lcov-report/coverage/lcov-report/block-navigation.js.html new file mode 100644 index 0000000..46d4d82 --- /dev/null +++ b/coverage/lcov-report/coverage/lcov-report/block-navigation.js.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for coverage/lcov-report/block-navigation.js + + + + + + + + + +
+
+

All files / coverage/lcov-report block-navigation.js

+
+ +
+ 0% + Statements + 0/30 +
+ + +
+ 0% + Branches + 0/19 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 0% + Lines + 0/30 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/* 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);
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/coverage/lcov-report/index.html b/coverage/lcov-report/coverage/lcov-report/index.html new file mode 100644 index 0000000..c4152df --- /dev/null +++ b/coverage/lcov-report/coverage/lcov-report/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for coverage/lcov-report + + + + + + + + + +
+
+

All files coverage/lcov-report

+
+ +
+ 0% + Statements + 0/656 +
+ + +
+ 0% + Branches + 0/329 +
+ + +
+ 0% + Functions + 0/54 +
+ + +
+ 0% + Lines + 0/120 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
block-navigation.js +
+
0%0/300%0/190%0/60%0/30
prettify.js +
+
0%0/5360%0/2860%0/290%0/1
sorter.js +
+
0%0/900%0/240%0/190%0/89
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/coverage/lcov-report/prettify.js.html b/coverage/lcov-report/coverage/lcov-report/prettify.js.html new file mode 100644 index 0000000..9e5d16f --- /dev/null +++ b/coverage/lcov-report/coverage/lcov-report/prettify.js.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for coverage/lcov-report/prettify.js + + + + + + + + + +
+
+

All files / coverage/lcov-report prettify.js

+
+ +
+ 0% + Statements + 0/536 +
+ + +
+ 0% + Branches + 0/286 +
+ + +
+ 0% + Functions + 0/29 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3  +  + 
/* eslint-disable */
+window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/coverage/lcov-report/sorter.js.html b/coverage/lcov-report/coverage/lcov-report/sorter.js.html new file mode 100644 index 0000000..0d2f899 --- /dev/null +++ b/coverage/lcov-report/coverage/lcov-report/sorter.js.html @@ -0,0 +1,673 @@ + + + + + + Code coverage report for coverage/lcov-report/sorter.js + + + + + + + + + +
+
+

All files / coverage/lcov-report sorter.js

+
+ +
+ 0% + Statements + 0/90 +
+ + +
+ 0% + Branches + 0/24 +
+ + +
+ 0% + Functions + 0/19 +
+ + +
+ 0% + Lines + 0/89 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +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 +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 +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 +156 +157 +158 +159 +160 +161 +162 +163 +164 +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 +196 +197  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/* eslint-disable */
+var addSorting = (function() {
+    'use strict';
+    var cols,
+        currentSort = {
+            index: 0,
+            desc: false
+        };
+ 
+    // returns the summary table element
+    function getTable() {
+        return document.querySelector('.coverage-summary');
+    }
+    // returns the thead element of the summary table
+    function getTableHeader() {
+        return getTable().querySelector('thead tr');
+    }
+    // returns the tbody element of the summary table
+    function getTableBody() {
+        return getTable().querySelector('tbody');
+    }
+    // returns the th element for nth column
+    function getNthColumn(n) {
+        return getTableHeader().querySelectorAll('th')[n];
+    }
+ 
+    function onFilterInput() {
+        const searchValue = document.getElementById('fileSearch').value;
+        const rows = document.getElementsByTagName('tbody')[0].children;
+        for (let i = 0; i < rows.length; i++) {
+            const row = rows[i];
+            if (
+                row.textContent
+                    .toLowerCase()
+                    .includes(searchValue.toLowerCase())
+            ) {
+                row.style.display = '';
+            } else {
+                row.style.display = 'none';
+            }
+        }
+    }
+ 
+    // loads the search box
+    function addSearchBox() {
+        var template = document.getElementById('filterTemplate');
+        var templateClone = template.content.cloneNode(true);
+        templateClone.getElementById('fileSearch').oninput = onFilterInput;
+        template.parentElement.appendChild(templateClone);
+    }
+ 
+    // loads all columns
+    function loadColumns() {
+        var colNodes = getTableHeader().querySelectorAll('th'),
+            colNode,
+            cols = [],
+            col,
+            i;
+ 
+        for (i = 0; i < colNodes.length; i += 1) {
+            colNode = colNodes[i];
+            col = {
+                key: colNode.getAttribute('data-col'),
+                sortable: !colNode.getAttribute('data-nosort'),
+                type: colNode.getAttribute('data-type') || 'string'
+            };
+            cols.push(col);
+            if (col.sortable) {
+                col.defaultDescSort = col.type === 'number';
+                colNode.innerHTML =
+                    colNode.innerHTML + '<span class="sorter"></span>';
+            }
+        }
+        return cols;
+    }
+    // attaches a data attribute to every tr element with an object
+    // of data values keyed by column name
+    function loadRowData(tableRow) {
+        var tableCols = tableRow.querySelectorAll('td'),
+            colNode,
+            col,
+            data = {},
+            i,
+            val;
+        for (i = 0; i < tableCols.length; i += 1) {
+            colNode = tableCols[i];
+            col = cols[i];
+            val = colNode.getAttribute('data-value');
+            if (col.type === 'number') {
+                val = Number(val);
+            }
+            data[col.key] = val;
+        }
+        return data;
+    }
+    // loads all row data
+    function loadData() {
+        var rows = getTableBody().querySelectorAll('tr'),
+            i;
+ 
+        for (i = 0; i < rows.length; i += 1) {
+            rows[i].data = loadRowData(rows[i]);
+        }
+    }
+    // sorts the table using the data for the ith column
+    function sortByIndex(index, desc) {
+        var key = cols[index].key,
+            sorter = function(a, b) {
+                a = a.data[key];
+                b = b.data[key];
+                return a < b ? -1 : a > b ? 1 : 0;
+            },
+            finalSorter = sorter,
+            tableBody = document.querySelector('.coverage-summary tbody'),
+            rowNodes = tableBody.querySelectorAll('tr'),
+            rows = [],
+            i;
+ 
+        if (desc) {
+            finalSorter = function(a, b) {
+                return -1 * sorter(a, b);
+            };
+        }
+ 
+        for (i = 0; i < rowNodes.length; i += 1) {
+            rows.push(rowNodes[i]);
+            tableBody.removeChild(rowNodes[i]);
+        }
+ 
+        rows.sort(finalSorter);
+ 
+        for (i = 0; i < rows.length; i += 1) {
+            tableBody.appendChild(rows[i]);
+        }
+    }
+    // removes sort indicators for current column being sorted
+    function removeSortIndicators() {
+        var col = getNthColumn(currentSort.index),
+            cls = col.className;
+ 
+        cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
+        col.className = cls;
+    }
+    // adds sort indicators for current column being sorted
+    function addSortIndicators() {
+        getNthColumn(currentSort.index).className += currentSort.desc
+            ? ' sorted-desc'
+            : ' sorted';
+    }
+    // adds event listeners for all sorter widgets
+    function enableUI() {
+        var i,
+            el,
+            ithSorter = function ithSorter(i) {
+                var col = cols[i];
+ 
+                return function() {
+                    var desc = col.defaultDescSort;
+ 
+                    if (currentSort.index === i) {
+                        desc = !currentSort.desc;
+                    }
+                    sortByIndex(i, desc);
+                    removeSortIndicators();
+                    currentSort.index = i;
+                    currentSort.desc = desc;
+                    addSortIndicators();
+                };
+            };
+        for (i = 0; i < cols.length; i += 1) {
+            if (cols[i].sortable) {
+                // add the click event handler on the th so users
+                // dont have to click on those tiny arrows
+                el = getNthColumn(i).querySelector('.sorter').parentElement;
+                if (el.addEventListener) {
+                    el.addEventListener('click', ithSorter(i));
+                } else {
+                    el.attachEvent('onclick', ithSorter(i));
+                }
+            }
+        }
+    }
+    // adds sorting functionality to the UI
+    return function() {
+        if (!getTable()) {
+            return;
+        }
+        cols = loadColumns();
+        loadData();
+        addSearchBox();
+        addSortIndicators();
+        enableUI();
+    };
+})();
+ 
+window.addEventListener('load', addSorting);
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/dist/commands/hello/index.html b/coverage/lcov-report/dist/commands/hello/index.html new file mode 100644 index 0000000..e0e0823 --- /dev/null +++ b/coverage/lcov-report/dist/commands/hello/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for dist/commands/hello + + + + + + + + + +
+
+

All files dist/commands/hello

+
+ +
+ 0% + Statements + 0/17 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js +
+
0%0/9100%0/00%0/10%0/9
world.js +
+
0%0/8100%0/00%0/10%0/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/dist/commands/hello/index.js.html b/coverage/lcov-report/dist/commands/hello/index.js.html new file mode 100644 index 0000000..41ab179 --- /dev/null +++ b/coverage/lcov-report/dist/commands/hello/index.js.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for dist/commands/hello/index.js + + + + + + + + + +
+
+

All files / dist/commands/hello index.js

+
+ +
+ 0% + Statements + 0/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const core_1 = require("@oclif/core");
+class Hello extends core_1.Command {
+    static args = {
+        person: core_1.Args.string({ description: 'Person to say hello to', required: true }),
+    };
+    static description = 'Say hello';
+    static examples = [
+        `$ oex hello friend --from oclif
+hello friend from oclif! (./src/commands/hello/index.ts)
+`,
+    ];
+    static flags = {
+        from: core_1.Flags.string({ char: 'f', description: 'Who is saying hello', required: true }),
+    };
+    async run() {
+        const { args, flags } = await this.parse(Hello);
+        this.log(`hello ${args.person} from ${flags.from}! (./src/commands/hello/index.ts)`);
+    }
+}
+exports.default = Hello;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/dist/commands/hello/world.js.html b/coverage/lcov-report/dist/commands/hello/world.js.html new file mode 100644 index 0000000..39007db --- /dev/null +++ b/coverage/lcov-report/dist/commands/hello/world.js.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for dist/commands/hello/world.js + + + + + + + + + +
+
+

All files / dist/commands/hello world.js

+
+ +
+ 0% + Statements + 0/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const core_1 = require("@oclif/core");
+class World extends core_1.Command {
+    static args = {};
+    static description = 'Say hello world';
+    static examples = [
+        `<%= config.bin %> <%= command.id %>
+hello world! (./src/commands/hello/world.ts)
+`,
+    ];
+    static flags = {};
+    async run() {
+        this.log('hello world! (./src/commands/hello/world.ts)');
+    }
+}
+exports.default = World;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/dist/index.html b/coverage/lcov-report/dist/index.html new file mode 100644 index 0000000..5ffa86e --- /dev/null +++ b/coverage/lcov-report/dist/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for dist + + + + + + + + + +
+
+

All files dist

+
+ +
+ 0% + Statements + 0/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js +
+
0%0/5100%0/00%0/10%0/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/dist/index.js.html b/coverage/lcov-report/dist/index.js.html new file mode 100644 index 0000000..7962b3a --- /dev/null +++ b/coverage/lcov-report/dist/index.js.html @@ -0,0 +1,100 @@ + + + + + + Code coverage report for dist/index.js + + + + + + + + + +
+
+

All files / dist index.js

+
+ +
+ 0% + Statements + 0/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6  +  +  +  +  + 
"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.run = void 0;
+var core_1 = require("@oclif/core");
+Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png new file mode 100644 index 0000000..c1525b8 Binary files /dev/null and b/coverage/lcov-report/favicon.png differ diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html new file mode 100644 index 0000000..6770c60 --- /dev/null +++ b/coverage/lcov-report/index.html @@ -0,0 +1,266 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 9.62% + Statements + 78/810 +
+ + +
+ 3.33% + Branches + 12/360 +
+ + +
+ 14.58% + Functions + 14/96 +
+ + +
+ 28.51% + Lines + 77/270 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
bin +
+
0%0/6100%0/00%0/20%0/6
coverage/lcov-report +
+
0%0/6560%0/3290%0/540%0/120
dist +
+
0%0/5100%0/00%0/10%0/4
dist/commands/hello +
+
0%0/17100%0/00%0/20%0/17
src +
+
0%0/00%0/00%0/00%0/0
src/application/cases +
+
73.8%31/4250%6/1266.66%6/973.8%31/42
src/application/repositories +
+
0%0/00%0/00%0/00%0/0
src/core +
+
80%4/5100%0/00%0/180%4/5
src/core/entities +
+
45.31%29/6430.76%4/1321.73%5/2345.9%28/61
src/core/errors +
+
92.85%13/1433.33%2/675%3/492.85%13/14
src/core/types +
+
100%1/1100%0/0100%0/0100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000..6ed6831 Binary files /dev/null and b/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..2bb296a --- /dev/null +++ b/coverage/lcov-report/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/lcov-report/src/application/cases/continue-with-last-time-entry.case.ts.html b/coverage/lcov-report/src/application/cases/continue-with-last-time-entry.case.ts.html new file mode 100644 index 0000000..193ba1f --- /dev/null +++ b/coverage/lcov-report/src/application/cases/continue-with-last-time-entry.case.ts.html @@ -0,0 +1,160 @@ + + + + + + Code coverage report for src/application/cases/continue-with-last-time-entry.case.ts + + + + + + + + + +
+
+

All files / src/application/cases continue-with-last-time-entry.case.ts

+
+ +
+ 100% + Statements + 8/8 +
+ + +
+ 66.66% + Branches + 2/3 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +261x +  +  +  +1x +  +  +2x +2x +  +  +  +2x +2x +1x +  +  +  +  +  +  +  +1x +  +  + 
import {TimeEntry, TimeHelper} from "../../core";
+import {TimeEntryRepository} from "../repositories/time-entry.repository";
+ 
+ 
+export class ContinueWithLastTimeEntryUseCase {
+ 
+  constructor(
+    private readonly timeEntryRepository: TimeEntryRepository,
+    private readonly timeHelper: TimeHelper = new TimeHelper()
+  ) {}
+ 
+  async exec(): ReturnType<TimeEntryRepository['getLastEntry']> {
+    const lastEntry = await this.timeEntryRepository.getLastEntry();
+    if (lastEntry) {
+      return this.timeEntryRepository.createEntry(new TimeEntry({
+        description: lastEntry.description,
+        id: lastEntry.id,
+        pid: lastEntry.pid,
+        wid: lastEntry.wid,
+      }), this.timeHelper.getCurrentUtcDate());
+    }
+ 
+    return lastEntry
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/cases/get-current-time-entry.case.ts.html b/coverage/lcov-report/src/application/cases/get-current-time-entry.case.ts.html new file mode 100644 index 0000000..3cfb776 --- /dev/null +++ b/coverage/lcov-report/src/application/cases/get-current-time-entry.case.ts.html @@ -0,0 +1,169 @@ + + + + + + Code coverage report for src/application/cases/get-current-time-entry.case.ts + + + + + + + + + +
+
+

All files / src/application/cases get-current-time-entry.case.ts

+
+ +
+ 100% + Statements + 11/11 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 11/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +291x +  +  +  +  +  +  +1x +  +  +3x +3x +  +  +  +3x +3x +2x +2x +1x +  +  +1x +  +  +1x +  +  + 
import {Nullable, Project, ProjectNotFoundError, TimeEntry} from "../../core";
+import {ProjectRepository, TimeEntryRepository} from "../repositories";
+import { UseCase } from "./use-case";
+ 
+type Input = undefined
+type Output = Promise<Nullable<[TimeEntry, Project]>>
+ 
+export class GetCurrentTimeEntryUseCase implements UseCase<Input, Output>{
+ 
+  constructor(
+    private readonly timeEntryRepository: TimeEntryRepository,
+    private readonly projectRepository: ProjectRepository
+  ) {}
+ 
+  async exec(): Output {
+    const currentEntry = await this.timeEntryRepository.getCurrentEntry();
+    if (currentEntry) {
+      const project = await this.projectRepository.getProjectById(currentEntry.pid);
+      if (project === null) {
+        throw new ProjectNotFoundError(currentEntry.pid)
+      }
+ 
+      return [currentEntry, project];
+    }
+ 
+    return null
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/cases/get-current-week-report.case.ts.html b/coverage/lcov-report/src/application/cases/get-current-week-report.case.ts.html new file mode 100644 index 0000000..6b3f6c8 --- /dev/null +++ b/coverage/lcov-report/src/application/cases/get-current-week-report.case.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/application/cases/get-current-week-report.case.ts + + + + + + + + + +
+
+

All files / src/application/cases get-current-week-report.case.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +231x +  +  +  +  +  +  +1x +  +  +1x +1x +  +  +  +1x +  +  +  +1x +  +  + 
import {Report} from "../../core";
+import {ProjectRepository, TimeEntryRepository} from "../repositories";
+import {UseCase} from "./use-case";
+ 
+type Input = undefined
+type Output = Promise<Report>
+ 
+export class GetCurrentWeekReportUseCase implements UseCase<Input, Output> {
+ 
+    constructor(
+        private readonly timeEntryRepository: TimeEntryRepository,
+        private readonly projectRepository: ProjectRepository
+    ) {}
+ 
+    async exec() {
+        const [entries, projects] = await Promise.all([
+            this.timeEntryRepository.getCurrentWeekEntries(),
+            this.projectRepository.getProjects()
+        ])
+        return Report.create(entries, projects)
+    }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/cases/index.html b/coverage/lcov-report/src/application/cases/index.html new file mode 100644 index 0000000..81edc62 --- /dev/null +++ b/coverage/lcov-report/src/application/cases/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/application/cases + + + + + + + + + +
+
+

All files src/application/cases

+
+ +
+ 73.8% + Statements + 31/42 +
+ + +
+ 50% + Branches + 6/12 +
+ + +
+ 66.66% + Functions + 6/9 +
+ + +
+ 73.8% + Lines + 31/42 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
continue-with-last-time-entry.case.ts +
+
100%8/866.66%2/3100%2/2100%8/8
get-current-time-entry.case.ts +
+
100%11/11100%4/4100%2/2100%11/11
get-current-week-report.case.ts +
+
100%6/6100%0/0100%2/2100%6/6
index.ts +
+
100%4/4100%0/0100%0/0100%4/4
start-time-entry.case.ts +
+
15.38%2/130%0/50%0/315.38%2/13
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/cases/index.ts.html b/coverage/lcov-report/src/application/cases/index.ts.html new file mode 100644 index 0000000..28398c4 --- /dev/null +++ b/coverage/lcov-report/src/application/cases/index.ts.html @@ -0,0 +1,94 @@ + + + + + + Code coverage report for src/application/cases/index.ts + + + + + + + + + +
+
+

All files / src/application/cases index.ts

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +41x +1x +1x +1x
export * from "./continue-with-last-time-entry.case"
+export * from "./get-current-time-entry.case"
+export * from "./get-current-week-report.case"
+export * from "./start-time-entry.case"
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/cases/start-time-entry.case.ts.html b/coverage/lcov-report/src/application/cases/start-time-entry.case.ts.html new file mode 100644 index 0000000..3b23bad --- /dev/null +++ b/coverage/lcov-report/src/application/cases/start-time-entry.case.ts.html @@ -0,0 +1,211 @@ + + + + + + Code coverage report for src/application/cases/start-time-entry.case.ts + + + + + + + + + +
+
+

All files / src/application/cases start-time-entry.case.ts

+
+ +
+ 15.38% + Statements + 2/13 +
+ + +
+ 0% + Branches + 0/5 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 15.38% + Lines + 2/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +431x +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {ProjectNotFoundError, TimeEntry, TimeHelper, isValidId} from "../../core";
+import {TimeEntryRepository} from "../repositories";
+import {ProjectRepository} from "../repositories/project.repository";
+import {UseCase} from "./use-case";
+ 
+type Input = {
+  description: string,
+  project: number | string
+}
+type Output = Promise<void>
+ 
+export class StartTimeEntryUseCase implements UseCase<Input, Output> {
+ 
+  constructor(
+    private readonly timeEntryRepository: TimeEntryRepository,
+    private readonly projectRepository: ProjectRepository,
+    private readonly timeHelper: TimeHelper = new TimeHelper()
+  ) {}
+ 
+  async exec({description, project}: Input) {
+    const pid = await this.getProjecId(project);
+    await this.timeEntryRepository.createEntry(new TimeEntry({
+      description,
+      pid,
+      wid: this.timeEntryRepository.workspaceId,
+    }), this.timeHelper.getCurrentUtcDate())
+  }
+ 
+  private async getProjecId(project: number | string) {
+    if (isValidId(project)) {
+      return project
+    }
+    
+    const p = await this.projectRepository.getProjectByName(project)
+    if (p === null) {
+      throw new ProjectNotFoundError(project)
+    }
+ 
+    return p.id
+ 
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/repositories/index.html b/coverage/lcov-report/src/application/repositories/index.html new file mode 100644 index 0000000..284fef2 --- /dev/null +++ b/coverage/lcov-report/src/application/repositories/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/application/repositories + + + + + + + + + +
+
+

All files src/application/repositories

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/application/repositories/index.ts.html b/coverage/lcov-report/src/application/repositories/index.ts.html new file mode 100644 index 0000000..a3cf254 --- /dev/null +++ b/coverage/lcov-report/src/application/repositories/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for src/application/repositories/index.ts + + + + + + + + + +
+
+

All files / src/application/repositories index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3  +  + 
export * from "./project.repository"
+export * from "./time-entry.repository"
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/commands/hello/index.html b/coverage/lcov-report/src/commands/hello/index.html new file mode 100644 index 0000000..1241d38 --- /dev/null +++ b/coverage/lcov-report/src/commands/hello/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/commands/hello + + + + + + + + + +
+
+

All files src/commands/hello

+
+ +
+ 100% + Statements + 17/17 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 17/17 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%9/9100%0/0100%1/1100%9/9
world.ts +
+
100%8/8100%0/0100%1/1100%8/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/commands/hello/index.ts.html b/coverage/lcov-report/src/commands/hello/index.ts.html new file mode 100644 index 0000000..08c515e --- /dev/null +++ b/coverage/lcov-report/src/commands/hello/index.ts.html @@ -0,0 +1,160 @@ + + + + + + Code coverage report for src/commands/hello/index.ts + + + + + + + + + +
+
+

All files / src/commands/hello index.ts

+
+ +
+ 100% + Statements + 9/9 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 9/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26  +1x +1x +  +1x +  +  +1x +1x +  +  +  +  +1x +  +  +  +1x +1x +  +  +1x +  +  +  + 
import {Args, Command, Flags} from '@oclif/core'
+ 
+export default class Hello extends Command {
+  static args = {
+    person: Args.string({description: 'Person to say hello to', required: true}),
+  }
+ 
+  static description = 'Say hello'
+ 
+  static examples = [
+    `$ oex hello friend --from oclif
+hello friend from oclif! (./src/commands/hello/index.ts)
+`,
+  ]
+ 
+  static flags = {
+    from: Flags.string({char: 'f', description: 'Who is saying hello', required: true}),
+  }
+ 
+  async run(): Promise<void> {
+    const {args, flags} = await this.parse(Hello)
+ 
+    this.log(`hello ${args.person} from ${flags.from}! (./src/commands/hello/index.ts)`)
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/commands/hello/world.ts.html b/coverage/lcov-report/src/commands/hello/world.ts.html new file mode 100644 index 0000000..d3ad0a5 --- /dev/null +++ b/coverage/lcov-report/src/commands/hello/world.ts.html @@ -0,0 +1,142 @@ + + + + + + Code coverage report for src/commands/hello/world.ts + + + + + + + + + +
+
+

All files / src/commands/hello world.ts

+
+ +
+ 100% + Statements + 8/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 8/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20  +1x +1x +  +1x +1x +1x +  +  +  +  +1x +  +1x +  +  +1x +  +  + 
import {Command} from '@oclif/core'
+ 
+export default class World extends Command {
+  static args = {}
+ 
+  static description = 'Say hello world'
+ 
+  static examples = [
+    `<%= config.bin %> <%= command.id %>
+hello world! (./src/commands/hello/world.ts)
+`,
+  ]
+ 
+  static flags = {}
+ 
+  async run(): Promise<void> {
+    this.log('hello world! (./src/commands/hello/world.ts)')
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/index.html b/coverage/lcov-report/src/core/entities/index.html new file mode 100644 index 0000000..e92774a --- /dev/null +++ b/coverage/lcov-report/src/core/entities/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/core/entities + + + + + + + + + +
+
+

All files src/core/entities

+
+ +
+ 45.31% + Statements + 29/64 +
+ + +
+ 30.76% + Branches + 4/13 +
+ + +
+ 21.73% + Functions + 5/23 +
+ + +
+ 45.9% + Lines + 28/61 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%7/7100%0/00%0/1100%6/6
project.ts +
+
100%3/3100%0/0100%1/1100%3/3
report-entry.ts +
+
33.33%2/60%0/10%0/333.33%2/6
report.ts +
+
50%5/10100%0/040%2/555.55%5/9
time-entry-list.ts +
+
18.18%2/110%0/20%0/420%2/10
time-entry.ts +
+
58.33%7/1266.66%4/625%1/458.33%7/12
time-helper.ts +
+
20%3/150%0/420%1/520%3/15
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/index.ts.html b/coverage/lcov-report/src/core/entities/index.ts.html new file mode 100644 index 0000000..c12d6d3 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/index.ts.html @@ -0,0 +1,103 @@ + + + + + + Code coverage report for src/core/entities/index.ts + + + + + + + + + +
+
+

All files / src/core/entities index.ts

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +71x +1x +1x +1x +1x +1x + 
export * from './project'
+export * from './report'
+export * from './time-entry'
+export * from './time-entry-list'
+export * from './time-helper'
+export {ReportEntry} from "./report-entry";
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/project.ts.html b/coverage/lcov-report/src/core/entities/project.ts.html new file mode 100644 index 0000000..8a13255 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/project.ts.html @@ -0,0 +1,112 @@ + + + + + + Code coverage report for src/core/entities/project.ts + + + + + + + + + +
+
+

All files / src/core/entities project.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +101x +  +  +  +  +1x +1x +  +  + 
export class Project {
+  id: number;
+  name: string;
+ 
+  constructor(id: number, name: string) {
+    this.id = id;
+    this.name = name;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/report-entry.ts.html b/coverage/lcov-report/src/core/entities/report-entry.ts.html new file mode 100644 index 0000000..cbc3020 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/report-entry.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/core/entities/report-entry.ts + + + + + + + + + +
+
+

All files / src/core/entities report-entry.ts

+
+ +
+ 33.33% + Statements + 2/6 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 33.33% + Lines + 2/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +191x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {Project} from "./project";
+import {TimeEntry} from "./time-entry";
+ 
+export class ReportEntry {
+    private constructor(
+        private readonly entry: TimeEntry,
+        private readonly project: Project
+    ) {
+    }
+ 
+    static create(entry: TimeEntry, project: Project = new Project(entry.pid, "Unknown project")): ReportEntry {
+        return new ReportEntry(entry, project)
+    }
+ 
+    toString() {
+        return `${this.entry} (${this.project.name})`
+    }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/report.ts.html b/coverage/lcov-report/src/core/entities/report.ts.html new file mode 100644 index 0000000..ba59d28 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/report.ts.html @@ -0,0 +1,157 @@ + + + + + + Code coverage report for src/core/entities/report.ts + + + + + + + + + +
+
+

All files / src/core/entities report.ts

+
+ +
+ 50% + Statements + 5/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 40% + Functions + 2/5 +
+ + +
+ 55.55% + Lines + 5/9 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +1x +  +1x +  +1x +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  + 
import {Project} from "./project";
+import {ReportEntry} from "./report-entry";
+import {TimeEntryList} from "./time-entry-list";
+import {TimeHelper} from "./time-helper";
+ 
+export class Report {
+    readonly entries: ReportEntry[]
+    readonly totalDuration: number
+ 
+    private constructor(entries: TimeEntryList, projects: Record<string, Project>) {
+        this.totalDuration = entries.getTotalDuration()
+        this.entries = Object.values(entries.groupEntriesByDescription())
+            .map(entry => ReportEntry.create(entry, projects[entry.pid]))
+    }
+ 
+    static create(entries: TimeEntryList, projects: Record<string, Project>): Report {
+        return new Report(entries, projects)
+    }
+ 
+    toString() {
+        const report = TimeHelper.secondsToHmsString(this.totalDuration)
+        return report + this.entries.map(entry => entry.toString()).join('\n')
+    }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/time-entry-list.ts.html b/coverage/lcov-report/src/core/entities/time-entry-list.ts.html new file mode 100644 index 0000000..8b3d708 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/time-entry-list.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/core/entities/time-entry-list.ts + + + + + + + + + +
+
+

All files / src/core/entities time-entry-list.ts

+
+ +
+ 18.18% + Statements + 2/11 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 20% + Lines + 2/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +281x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {TimeEntry} from "./time-entry";
+ 
+export class TimeEntryList {
+  values: TimeEntry[];
+ 
+  constructor(values: TimeEntry[]) {
+    this.values = values;
+  }
+ 
+  getTotalDuration(): number {
+    return this.values.reduce((total, entry) => total + entry.duration, 0)
+  }
+ 
+  groupEntriesByDescription(): Record<string, TimeEntry> {
+    const groupedEntries: Record<string, TimeEntry> = {};
+ 
+    for (const entry of this.values) {
+      if (groupedEntries[entry.description]) {
+        groupedEntries[entry.description].duration += entry.duration;
+      } else {
+        groupedEntries[entry.description] = new TimeEntry(entry)
+      }
+    }
+ 
+    return groupedEntries;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/time-entry.ts.html b/coverage/lcov-report/src/core/entities/time-entry.ts.html new file mode 100644 index 0000000..0bddeb0 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/time-entry.ts.html @@ -0,0 +1,211 @@ + + + + + + Code coverage report for src/core/entities/time-entry.ts + + + + + + + + + +
+
+

All files / src/core/entities time-entry.ts

+
+ +
+ 58.33% + Statements + 7/12 +
+ + +
+ 66.66% + Branches + 4/6 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 58.33% + Lines + 7/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +431x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +5x +5x +5x +5x +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {TimeHelper} from "./time-helper";
+ 
+export interface TimeEntryParams {
+  description: string,
+  duration?: number,
+  id?: number,
+  pid: number,
+  wid: number
+}
+ 
+export class TimeEntry {
+  description: string;
+  id: number;
+  pid: number;
+  wid: number;
+ 
+  private _duration: number;
+ 
+  constructor({ description, duration, id, pid, wid}: TimeEntryParams) {
+    this.id = id || Math.floor(Math.random() * 10**16);
+    this.pid = pid;
+    this.wid = wid;
+    this.description = description;
+    this._duration = duration || -1; // according to Toggl docs
+  }
+ 
+  get duration(): number {
+    if (this._duration < 0) {
+      return Math.floor(Date.now() / 1000) + this._duration;
+    }
+ 
+    return this._duration;
+  }
+ 
+  set duration(value: number) {
+    this._duration = value;
+  }
+ 
+  toString(): string {
+    return `${TimeHelper.secondsToHmsString(this.duration)} - ${this.description}`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/entities/time-helper.ts.html b/coverage/lcov-report/src/core/entities/time-helper.ts.html new file mode 100644 index 0000000..446cd46 --- /dev/null +++ b/coverage/lcov-report/src/core/entities/time-helper.ts.html @@ -0,0 +1,190 @@ + + + + + + Code coverage report for src/core/entities/time-helper.ts + + + + + + + + + +
+
+

All files / src/core/entities time-helper.ts

+
+ +
+ 20% + Statements + 3/15 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 20% + Lines + 3/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +361x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export class TimeHelper {
+  private static addZeroPrefix(number: number): string {
+    return number > 9 ? number.toString() : `0${number}`;
+  }
+ 
+  getCurrentUtcDate(): string {
+    const now = new Date();
+    return now.toISOString();
+  }
+ 
+  getWeekDates(date: Date): [Date, Date] {
+    const dayOfWeek = date.getDay() === 0 ? 6 : date.getDay() - 1
+ 
+    const startOfWeek = new Date(date);
+    startOfWeek.setDate(date.getDate() - dayOfWeek);
+ 
+    const endOfWeek = new Date(startOfWeek);
+    endOfWeek.setDate(startOfWeek.getDate() + 6);
+ 
+    return [startOfWeek, endOfWeek];
+  }
+ 
+ 
+ 
+  secondsToHmsString(seconds: number): string {
+    return TimeHelper.secondsToHmsString(seconds)
+  }
+ 
+  static secondsToHmsString(seconds: number): string {
+    const hours = Math.floor(seconds / 3600);
+    const minutes = Math.floor((seconds % 3600) / 60);
+    const remainingSeconds = seconds % 60;
+    return `${TimeHelper.addZeroPrefix(hours)}h ${TimeHelper.addZeroPrefix(minutes)}m ${TimeHelper.addZeroPrefix(remainingSeconds)}s`;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/errors/core.error.ts.html b/coverage/lcov-report/src/core/errors/core.error.ts.html new file mode 100644 index 0000000..8a9e53b --- /dev/null +++ b/coverage/lcov-report/src/core/errors/core.error.ts.html @@ -0,0 +1,133 @@ + + + + + + Code coverage report for src/core/errors/core.error.ts + + + + + + + + + +
+
+

All files / src/core/errors core.error.ts

+
+ +
+ 66.66% + Statements + 2/3 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 66.66% + Lines + 2/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17  +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  + 
/* eslint-disable perfectionist/sort-classes */
+import { ErrorCodes } from './error-codes'
+export abstract class CoreError extends Error {
+  abstract readonly code: ErrorCodes
+ 
+  protected constructor (message: string) {
+    super(message)
+  }
+ 
+  static isError (error: unknown): error is CoreError {
+    return typeof error === 'object' &&
+      error !== null &&
+      Object.hasOwn(error, 'code') &&
+      Object.hasOwn(error, 'message')
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/errors/error-codes.ts.html b/coverage/lcov-report/src/core/errors/error-codes.ts.html new file mode 100644 index 0000000..c1672bb --- /dev/null +++ b/coverage/lcov-report/src/core/errors/error-codes.ts.html @@ -0,0 +1,94 @@ + + + + + + Code coverage report for src/core/errors/error-codes.ts + + + + + + + + + +
+
+

All files / src/core/errors error-codes.ts

+
+ +
+ 100% + Statements + 2/2 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 2/2 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +41x +1x +  + 
export enum ErrorCodes {
+  ProjectNotFound = 'PROJECT_NOT_FOUND',
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/errors/index.html b/coverage/lcov-report/src/core/errors/index.html new file mode 100644 index 0000000..51695a1 --- /dev/null +++ b/coverage/lcov-report/src/core/errors/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/core/errors + + + + + + + + + +
+
+

All files src/core/errors

+
+ +
+ 92.85% + Statements + 13/14 +
+ + +
+ 33.33% + Branches + 2/6 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 92.85% + Lines + 13/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
core.error.ts +
+
66.66%2/30%0/450%1/266.66%2/3
error-codes.ts +
+
100%2/2100%2/2100%1/1100%2/2
index.ts +
+
100%3/3100%0/0100%0/0100%3/3
project-not-found.error.ts +
+
100%6/6100%0/0100%1/1100%6/6
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/errors/index.ts.html b/coverage/lcov-report/src/core/errors/index.ts.html new file mode 100644 index 0000000..9787257 --- /dev/null +++ b/coverage/lcov-report/src/core/errors/index.ts.html @@ -0,0 +1,94 @@ + + + + + + Code coverage report for src/core/errors/index.ts + + + + + + + + + +
+
+

All files / src/core/errors index.ts

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +41x +1x +1x + 
export * from './core.error'
+export * from './error-codes'
+export * from './project-not-found.error'
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/errors/project-not-found.error.ts.html b/coverage/lcov-report/src/core/errors/project-not-found.error.ts.html new file mode 100644 index 0000000..e0a673a --- /dev/null +++ b/coverage/lcov-report/src/core/errors/project-not-found.error.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for src/core/errors/project-not-found.error.ts + + + + + + + + + +
+
+

All files / src/core/errors project-not-found.error.ts

+
+ +
+ 100% + Statements + 6/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 6/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +121x +1x +  +1x +1x +  +  +1x +1x +  +  + 
import { CoreError } from './core.error'
+import { ErrorCodes } from './error-codes'
+ 
+export class ProjectNotFoundError extends CoreError {
+  readonly code = ErrorCodes.ProjectNotFound
+ 
+  constructor (key: number | string) {
+    super(`Project "${key}" not found.`)
+    this.name = 'ProjectNotFoundError'
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/index.html b/coverage/lcov-report/src/core/index.html new file mode 100644 index 0000000..89f8550 --- /dev/null +++ b/coverage/lcov-report/src/core/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/core + + + + + + + + + +
+
+

All files src/core

+
+ +
+ 80% + Statements + 4/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 80% + Lines + 4/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
80%4/5100%0/00%0/180%4/5
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/index.ts.html b/coverage/lcov-report/src/core/index.ts.html new file mode 100644 index 0000000..69c9bea --- /dev/null +++ b/coverage/lcov-report/src/core/index.ts.html @@ -0,0 +1,109 @@ + + + + + + Code coverage report for src/core/index.ts + + + + + + + + + +
+
+

All files / src/core index.ts

+
+ +
+ 80% + Statements + 4/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 80% + Lines + 4/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +91x +1x +1x +  +  +1x +  +  + 
export * from './entities'
+export * from './errors'
+export * from './types'
+ 
+ 
+export function isValidId(input: number | string): input is number {
+   return /^\d+$/.test(String(input))
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/types/index.html b/coverage/lcov-report/src/core/types/index.html new file mode 100644 index 0000000..6c96833 --- /dev/null +++ b/coverage/lcov-report/src/core/types/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/core/types + + + + + + + + + +
+
+

All files src/core/types

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
100%1/1100%0/0100%0/0100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/core/types/index.ts.html b/coverage/lcov-report/src/core/types/index.ts.html new file mode 100644 index 0000000..c07bd87 --- /dev/null +++ b/coverage/lcov-report/src/core/types/index.ts.html @@ -0,0 +1,88 @@ + + + + + + Code coverage report for src/core/types/index.ts + + + + + + + + + +
+
+

All files / src/core/types index.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +21x + 
export * from './nullable'
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/index.html b/coverage/lcov-report/src/index.html new file mode 100644 index 0000000..aad273a --- /dev/null +++ b/coverage/lcov-report/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/src/index.ts.html b/coverage/lcov-report/src/index.ts.html new file mode 100644 index 0000000..9234367 --- /dev/null +++ b/coverage/lcov-report/src/index.ts.html @@ -0,0 +1,88 @@ + + + + + + Code coverage report for src/index.ts + + + + + + + + + +
+
+

All files / src index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2  + 
export {run} from '@oclif/core'
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/commands/hello/index.html b/coverage/lcov-report/test/commands/hello/index.html new file mode 100644 index 0000000..67f6f24 --- /dev/null +++ b/coverage/lcov-report/test/commands/hello/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for test/commands/hello + + + + + + + + + +
+
+

All files test/commands/hello

+
+ +
+ 0% + Statements + 0/6 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 0% + Lines + 0/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.test.ts +
+
0%0/3100%0/00%0/20%0/3
world.test.ts +
+
0%0/3100%0/00%0/20%0/3
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/commands/hello/index.test.ts.html b/coverage/lcov-report/test/commands/hello/index.test.ts.html new file mode 100644 index 0000000..335252d --- /dev/null +++ b/coverage/lcov-report/test/commands/hello/index.test.ts.html @@ -0,0 +1,115 @@ + + + + + + Code coverage report for test/commands/hello/index.test.ts + + + + + + + + + +
+
+

All files / test/commands/hello index.test.ts

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11  +  +  +  +  +  +  +  +  +  + 
import {expect, test} from '@oclif/test'
+ 
+describe('hello', () => {
+  test
+  .stdout()
+  .command(['hello', 'friend', '--from=oclif'])
+  .it('runs hello cmd', ctx => {
+    expect(ctx.stdout).to.contain('hello friend from oclif!')
+  })
+})
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/commands/hello/world.test.ts.html b/coverage/lcov-report/test/commands/hello/world.test.ts.html new file mode 100644 index 0000000..4090aaa --- /dev/null +++ b/coverage/lcov-report/test/commands/hello/world.test.ts.html @@ -0,0 +1,115 @@ + + + + + + Code coverage report for test/commands/hello/world.test.ts + + + + + + + + + +
+
+

All files / test/commands/hello world.test.ts

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11  +  +  +  +  +  +  +  +  +  + 
import {expect, test} from '@oclif/test'
+ 
+describe('hello world', () => {
+  test
+  .stdout()
+  .command(['hello:world'])
+  .it('runs hello world cmd', ctx => {
+    expect(ctx.stdout).to.contain('hello world!')
+  })
+})
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/core/index.html b/coverage/lcov-report/test/core/index.html new file mode 100644 index 0000000..9c783d0 --- /dev/null +++ b/coverage/lcov-report/test/core/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for test/core + + + + + + + + + +
+
+

All files test/core

+
+ +
+ 0% + Statements + 0/73 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/19 +
+ + +
+ 0% + Lines + 0/73 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
is-valid-id.test.ts +
+
0%0/5100%0/00%0/20%0/5
time-entry-list.test.ts +
+
0%0/45100%0/00%0/120%0/45
time-entry.test.ts +
+
0%0/15100%0/00%0/30%0/15
time-helper.test.ts +
+
0%0/8100%0/00%0/20%0/8
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/core/is-valid-id.test.ts.html b/coverage/lcov-report/test/core/is-valid-id.test.ts.html new file mode 100644 index 0000000..e8b07f8 --- /dev/null +++ b/coverage/lcov-report/test/core/is-valid-id.test.ts.html @@ -0,0 +1,118 @@ + + + + + + Code coverage report for test/core/is-valid-id.test.ts + + + + + + + + + +
+
+

All files / test/core is-valid-id.test.ts

+
+ +
+ 0% + Statements + 0/5 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/5 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12  +  +  +  +  +  +  +  +  +  +  + 
import { expect } from 'chai';
+ 
+import {isValidId} from '../../src/core';
+ 
+describe('Id validator', () => {
+  it('should validate ids with just digits', () => {
+    expect(isValidId("123")).to.be.true;
+    expect(isValidId("abc")).to.be.false;
+    expect(isValidId("12a")).to.be.false;
+  });
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/core/time-entry-list.test.ts.html b/coverage/lcov-report/test/core/time-entry-list.test.ts.html new file mode 100644 index 0000000..12edc2a --- /dev/null +++ b/coverage/lcov-report/test/core/time-entry-list.test.ts.html @@ -0,0 +1,355 @@ + + + + + + Code coverage report for test/core/time-entry-list.test.ts + + + + + + + + + +
+
+

All files / test/core time-entry-list.test.ts

+
+ +
+ 0% + Statements + 0/45 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/12 +
+ + +
+ 0% + Lines + 0/45 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { expect } from 'chai';
+ 
+import {TimeEntry, TimeEntryList} from "../../src/core";
+ 
+describe('TimeEntryList', () => {
+  describe('getTotalDuration', () => {
+    it('should return 0 for an empty list', () => {
+      const list = new TimeEntryList([]);
+      expect(list.getTotalDuration()).to.equal(0);
+    });
+ 
+    it('should return the correct total duration for a single entry', () => {
+      const entry = new TimeEntry({ description: 'Task 1', duration: 60, id: 1, pid: 100, wid: 200 });
+      const list = new TimeEntryList([entry]);
+      expect(list.getTotalDuration()).to.equal(60);
+    });
+ 
+    it('should return the correct total duration for multiple entries', () => {
+      const entries = [
+        new TimeEntry({ description: 'Task 1', duration: 60, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'Task 2', duration: 150, id: 2, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      expect(list.getTotalDuration()).to.equal(210);
+    });
+ 
+    it('should handle durations with floating point numbers correctly', () => {
+      const entries = [
+        new TimeEntry({ description: 'Task 1', duration: 60.5, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'Task 2', duration: 59.5, id: 2, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      expect(list.getTotalDuration()).to.be.closeTo(120, 0.1);
+    });
+  });
+ 
+  describe('groupEntriesByDescription', () => {
+    it('should handle an empty list', () => {
+      const list = new TimeEntryList([]);
+      expect(list.groupEntriesByDescription()).to.deep.equal({});
+    });
+ 
+    it('should group entries correctly by description', () => {
+      const entries = [
+        new TimeEntry({ description: 'Task', duration: 60, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'Task', duration: 40, id: 2, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'Meeting', duration: 30, id: 3, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      const grouped = list.groupEntriesByDescription();
+ 
+      expect(Object.keys(grouped)).to.have.lengthOf(2);
+      expect(grouped.Task.duration).to.equal(100);
+      expect(grouped.Meeting.duration).to.equal(30);
+    });
+ 
+    it('should handle unique descriptions', () => {
+      const entries = [
+        new TimeEntry({ description: 'Task 1', duration: 60, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'Task 2', duration: 40, id: 2, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      const grouped = list.groupEntriesByDescription();
+ 
+      expect(grouped['Task 1'].duration).to.equal(60);
+      expect(grouped['Task 2'].duration).to.equal(40);
+    });
+ 
+    it('should handle entries with empty descriptions', () => {
+      const entries = [
+        new TimeEntry({ description: '', duration: 60, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: '', duration: 40, id: 2, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      const grouped = list.groupEntriesByDescription();
+      expect(grouped[''].duration).to.equal(100);
+    });
+ 
+    it('should treat descriptions with different cases as distinct', () => {
+      const entries = [
+        new TimeEntry({ description: 'Task', duration: 30, id: 1, pid: 100, wid: 200 }),
+        new TimeEntry({ description: 'task', duration: 70, id: 2, pid: 100, wid: 200 }),
+      ];
+      const list = new TimeEntryList(entries);
+      const grouped = list.groupEntriesByDescription();
+      expect(grouped.Task.duration).to.equal(30);
+      expect(grouped.task.duration).to.equal(70);
+    });
+  });
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/core/time-entry.test.ts.html b/coverage/lcov-report/test/core/time-entry.test.ts.html new file mode 100644 index 0000000..f7799e8 --- /dev/null +++ b/coverage/lcov-report/test/core/time-entry.test.ts.html @@ -0,0 +1,163 @@ + + + + + + Code coverage report for test/core/time-entry.test.ts + + + + + + + + + +
+
+

All files / test/core time-entry.test.ts

+
+ +
+ 0% + Statements + 0/15 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 0% + Lines + 0/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {expect} from 'chai';
+import 'mocha';
+ 
+import {TimeEntry} from "../../src/core";
+ 
+describe('TimeEntry', () => {
+  it('should correctly initialize a TimeEntry object', () => {
+    const timeEntry = new TimeEntry({description: "Prueba de descripción", duration: 3600, id: 1, pid: 100, wid: 200});
+ 
+    expect(timeEntry.id).to.equal(1);
+    expect(timeEntry.pid).to.equal(100);
+    expect(timeEntry.wid).to.equal(200);
+    expect(timeEntry.description).to.equal("Prueba de descripción");
+    expect(timeEntry.duration).to.equal(3600);
+  });
+ 
+  it('should return the correct string representation', () => {
+    const timeEntry = new TimeEntry({description: "Prueba de descripción", duration: 3600, id: 1, pid: 100, wid: 200})
+    let expectedStr = "01h 00m 00s - Prueba de descripción";
+    expect(timeEntry.toString()).to.equal(expectedStr);
+ 
+    timeEntry.duration = (Math.floor(Date.now() / 1000) - 3665) * -1;
+    expectedStr = "01h 01m 05s - Prueba de descripción";
+    expect(timeEntry.toString()).to.equal(expectedStr);
+  });
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/core/time-helper.test.ts.html b/coverage/lcov-report/test/core/time-helper.test.ts.html new file mode 100644 index 0000000..45bcae1 --- /dev/null +++ b/coverage/lcov-report/test/core/time-helper.test.ts.html @@ -0,0 +1,211 @@ + + + + + + Code coverage report for test/core/time-helper.test.ts + + + + + + + + + +
+
+

All files / test/core time-helper.test.ts

+
+ +
+ 0% + Statements + 0/8 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { expect } from 'chai';
+ 
+import {TimeHelper} from "../../src/core";
+ 
+describe('TimeHelper.getWeekDates', () => {
+  const th = new TimeHelper()
+  // Define an array of test cases with descriptions
+  const testCases = [
+    {
+      date: new Date(2023, 3, 24, 12), // April 24, 2023
+      description: 'a given Monday',
+      expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023
+      expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023
+    },
+    {
+      date: new Date(2023, 3, 26, 12), // April 26, 2023
+      description: 'a given Wednesday',
+      expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023
+      expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023
+    },
+    {
+      date: new Date(2023, 3, 30, 12), // April 30, 2023
+      description: 'a given Sunday',
+      expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023
+      expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023
+    },
+    {
+      date: new Date(2023, 0, 1, 12), // January 1, 2023
+      description: 'New Year (January 1st)',
+      expectedEnd: new Date(2023, 0, 1, 12), // January 1, 2023
+      expectedStart: new Date(2022, 11, 26, 12) // December 26, 2022
+    }
+  ];
+ 
+  for (const { date, description, expectedEnd, expectedStart } of testCases) {
+    it(`should return correct start and end weekday dates for ${description}`, () => {
+      const [start, end] = th.getWeekDates(date);
+      expect(start).to.deep.equal(expectedStart);
+      expect(end).to.deep.equal(expectedEnd);
+    });
+  }
+});
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/doubles/index.html b/coverage/lcov-report/test/doubles/index.html new file mode 100644 index 0000000..1e5202d --- /dev/null +++ b/coverage/lcov-report/test/doubles/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for test/doubles + + + + + + + + + +
+
+

All files test/doubles

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/test/doubles/index.ts.html b/coverage/lcov-report/test/doubles/index.ts.html new file mode 100644 index 0000000..4841821 --- /dev/null +++ b/coverage/lcov-report/test/doubles/index.ts.html @@ -0,0 +1,91 @@ + + + + + + Code coverage report for test/doubles/index.ts + + + + + + + + + +
+
+

All files / test/doubles index.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3  +  + 
export * from "./project.repository.double"
+export * from "./time-entry.repository.double"
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 0000000..7f9629f --- /dev/null +++ b/coverage/lcov.info @@ -0,0 +1,1074 @@ +TN: +SF:bin/dev.js +FN:3,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:3,0 +DA:4,0 +DA:5,0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:bin/run.js +FN:4,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:4,0 +DA:5,0 +DA:6,0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:coverage/lcov-report/block-navigation.js +FN:2,init +FN:24,toggleClass +FN:31,makeCurrent +FN:41,goToPrevious +FN:52,goToNext +FN:65,jump +FNF:6 +FNH:0 +FNDA:0,init +FNDA:0,toggleClass +FNDA:0,makeCurrent +FNDA:0,goToPrevious +FNDA:0,goToNext +FNDA:0,jump +DA:2,0 +DA:4,0 +DA:7,0 +DA:10,0 +DA:14,0 +DA:20,0 +DA:25,0 +DA:28,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:53,0 +DA:55,0 +DA:59,0 +DA:62,0 +DA:65,0 +DA:66,0 +DA:71,0 +DA:74,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:83,0 +DA:87,0 +LF:30 +LH:0 +BRDA:43,0,0,0 +BRDA:43,0,1,0 +BRDA:43,1,0,0 +BRDA:43,1,1,0 +BRDA:45,2,0,0 +BRDA:45,2,1,0 +BRDA:55,3,0,0 +BRDA:55,3,1,0 +BRDA:56,4,0,0 +BRDA:56,4,1,0 +BRDA:66,5,0,0 +BRDA:66,5,1,0 +BRDA:67,6,0,0 +BRDA:67,6,1,0 +BRDA:74,7,0,0 +BRDA:74,7,1,0 +BRDA:74,7,2,0 +BRDA:74,7,3,0 +BRDA:74,7,4,0 +BRF:19 +BRH:0 +end_of_record +TN: +SF:coverage/lcov-report/prettify.js +FN:2,(anonymous_0) +FN:2,k +FN:2,ab +FN:2,T +FN:2,X +FN:2,(anonymous_5) +FN:2,W +FN:2,(anonymous_7) +FN:2,a +FN:2,aa +FN:2,B +FN:2,o +FN:2,g +FN:2,(anonymous_13) +FN:2,(anonymous_14) +FN:2,i +FN:2,Q +FN:2,ae +FN:2,ad +FN:2,ai +FN:2,D +FN:2,c +FN:2,q +FN:2,d +FN:2,y +FN:2,b +FN:2,Y +FN:2,(anonymous_27) +FN:2,U +FNF:29 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,k +FNDA:0,ab +FNDA:0,T +FNDA:0,X +FNDA:0,(anonymous_5) +FNDA:0,W +FNDA:0,(anonymous_7) +FNDA:0,a +FNDA:0,aa +FNDA:0,B +FNDA:0,o +FNDA:0,g +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,i +FNDA:0,Q +FNDA:0,ae +FNDA:0,ad +FNDA:0,ai +FNDA:0,D +FNDA:0,c +FNDA:0,q +FNDA:0,d +FNDA:0,y +FNDA:0,b +FNDA:0,Y +FNDA:0,(anonymous_27) +FNDA:0,U +DA:2,0 +LF:1 +LH:0 +BRDA:2,0,0,0 +BRDA:2,0,1,0 +BRDA:2,1,0,0 +BRDA:2,1,1,0 +BRDA:2,2,0,0 +BRDA:2,2,1,0 +BRDA:2,3,0,0 +BRDA:2,3,1,0 +BRDA:2,4,0,0 +BRDA:2,4,1,0 +BRDA:2,5,0,0 +BRDA:2,5,1,0 +BRDA:2,6,0,0 +BRDA:2,6,1,0 +BRDA:2,7,0,0 +BRDA:2,7,1,0 +BRDA:2,8,0,0 +BRDA:2,8,1,0 +BRDA:2,9,0,0 +BRDA:2,9,1,0 +BRDA:2,10,0,0 +BRDA:2,10,1,0 +BRDA:2,11,0,0 +BRDA:2,11,1,0 +BRDA:2,11,2,0 +BRDA:2,11,3,0 +BRDA:2,12,0,0 +BRDA:2,12,1,0 +BRDA:2,13,0,0 +BRDA:2,13,1,0 +BRDA:2,14,0,0 +BRDA:2,14,1,0 +BRDA:2,15,0,0 +BRDA:2,15,1,0 +BRDA:2,16,0,0 +BRDA:2,16,1,0 +BRDA:2,17,0,0 +BRDA:2,17,1,0 +BRDA:2,18,0,0 +BRDA:2,18,1,0 +BRDA:2,19,0,0 +BRDA:2,19,1,0 +BRDA:2,20,0,0 +BRDA:2,20,1,0 +BRDA:2,21,0,0 +BRDA:2,21,1,0 +BRDA:2,22,0,0 +BRDA:2,22,1,0 +BRDA:2,23,0,0 +BRDA:2,23,1,0 +BRDA:2,24,0,0 +BRDA:2,24,1,0 +BRDA:2,25,0,0 +BRDA:2,25,1,0 +BRDA:2,26,0,0 +BRDA:2,26,1,0 +BRDA:2,27,0,0 +BRDA:2,27,1,0 +BRDA:2,28,0,0 +BRDA:2,28,1,0 +BRDA:2,29,0,0 +BRDA:2,29,1,0 +BRDA:2,30,0,0 +BRDA:2,30,1,0 +BRDA:2,31,0,0 +BRDA:2,31,1,0 +BRDA:2,32,0,0 +BRDA:2,32,1,0 +BRDA:2,33,0,0 +BRDA:2,33,1,0 +BRDA:2,34,0,0 +BRDA:2,34,1,0 +BRDA:2,35,0,0 +BRDA:2,35,1,0 +BRDA:2,36,0,0 +BRDA:2,36,1,0 +BRDA:2,37,0,0 +BRDA:2,37,1,0 +BRDA:2,38,0,0 +BRDA:2,38,1,0 +BRDA:2,39,0,0 +BRDA:2,39,1,0 +BRDA:2,40,0,0 +BRDA:2,40,1,0 +BRDA:2,41,0,0 +BRDA:2,41,1,0 +BRDA:2,42,0,0 +BRDA:2,42,1,0 +BRDA:2,43,0,0 +BRDA:2,43,1,0 +BRDA:2,44,0,0 +BRDA:2,44,1,0 +BRDA:2,45,0,0 +BRDA:2,45,1,0 +BRDA:2,46,0,0 +BRDA:2,46,1,0 +BRDA:2,47,0,0 +BRDA:2,47,1,0 +BRDA:2,48,0,0 +BRDA:2,48,1,0 +BRDA:2,49,0,0 +BRDA:2,49,1,0 +BRDA:2,50,0,0 +BRDA:2,50,1,0 +BRDA:2,50,2,0 +BRDA:2,51,0,0 +BRDA:2,51,1,0 +BRDA:2,52,0,0 +BRDA:2,52,1,0 +BRDA:2,53,0,0 +BRDA:2,53,1,0 +BRDA:2,54,0,0 +BRDA:2,54,1,0 +BRDA:2,55,0,0 +BRDA:2,55,1,0 +BRDA:2,56,0,0 +BRDA:2,56,1,0 +BRDA:2,57,0,0 +BRDA:2,57,1,0 +BRDA:2,58,0,0 +BRDA:2,58,1,0 +BRDA:2,59,0,0 +BRDA:2,59,1,0 +BRDA:2,60,0,0 +BRDA:2,60,1,0 +BRDA:2,61,0,0 +BRDA:2,61,1,0 +BRDA:2,62,0,0 +BRDA:2,62,1,0 +BRDA:2,63,0,0 +BRDA:2,63,1,0 +BRDA:2,64,0,0 +BRDA:2,64,1,0 +BRDA:2,65,0,0 +BRDA:2,65,1,0 +BRDA:2,66,0,0 +BRDA:2,66,1,0 +BRDA:2,67,0,0 +BRDA:2,67,1,0 +BRDA:2,68,0,0 +BRDA:2,68,1,0 +BRDA:2,69,0,0 +BRDA:2,69,1,0 +BRDA:2,70,0,0 +BRDA:2,70,1,0 +BRDA:2,71,0,0 +BRDA:2,71,1,0 +BRDA:2,72,0,0 +BRDA:2,72,1,0 +BRDA:2,73,0,0 +BRDA:2,73,1,0 +BRDA:2,74,0,0 +BRDA:2,74,1,0 +BRDA:2,75,0,0 +BRDA:2,75,1,0 +BRDA:2,76,0,0 +BRDA:2,76,1,0 +BRDA:2,77,0,0 +BRDA:2,77,1,0 +BRDA:2,78,0,0 +BRDA:2,78,1,0 +BRDA:2,79,0,0 +BRDA:2,79,1,0 +BRDA:2,80,0,0 +BRDA:2,80,1,0 +BRDA:2,81,0,0 +BRDA:2,81,1,0 +BRDA:2,82,0,0 +BRDA:2,82,1,0 +BRDA:2,83,0,0 +BRDA:2,83,1,0 +BRDA:2,84,0,0 +BRDA:2,84,1,0 +BRDA:2,85,0,0 +BRDA:2,85,1,0 +BRDA:2,86,0,0 +BRDA:2,86,1,0 +BRDA:2,87,0,0 +BRDA:2,87,1,0 +BRDA:2,88,0,0 +BRDA:2,88,1,0 +BRDA:2,89,0,0 +BRDA:2,89,1,0 +BRDA:2,89,2,0 +BRDA:2,90,0,0 +BRDA:2,90,1,0 +BRDA:2,91,0,0 +BRDA:2,91,1,0 +BRDA:2,92,0,0 +BRDA:2,92,1,0 +BRDA:2,93,0,0 +BRDA:2,93,1,0 +BRDA:2,94,0,0 +BRDA:2,94,1,0 +BRDA:2,95,0,0 +BRDA:2,95,1,0 +BRDA:2,96,0,0 +BRDA:2,96,1,0 +BRDA:2,97,0,0 +BRDA:2,97,1,0 +BRDA:2,98,0,0 +BRDA:2,98,1,0 +BRDA:2,99,0,0 +BRDA:2,99,1,0 +BRDA:2,100,0,0 +BRDA:2,100,1,0 +BRDA:2,101,0,0 +BRDA:2,101,1,0 +BRDA:2,102,0,0 +BRDA:2,102,1,0 +BRDA:2,103,0,0 +BRDA:2,103,1,0 +BRDA:2,104,0,0 +BRDA:2,104,1,0 +BRDA:2,105,0,0 +BRDA:2,105,1,0 +BRDA:2,106,0,0 +BRDA:2,106,1,0 +BRDA:2,107,0,0 +BRDA:2,107,1,0 +BRDA:2,108,0,0 +BRDA:2,108,1,0 +BRDA:2,109,0,0 +BRDA:2,109,1,0 +BRDA:2,110,0,0 +BRDA:2,110,1,0 +BRDA:2,111,0,0 +BRDA:2,111,1,0 +BRDA:2,112,0,0 +BRDA:2,112,1,0 +BRDA:2,113,0,0 +BRDA:2,113,1,0 +BRDA:2,114,0,0 +BRDA:2,114,1,0 +BRDA:2,115,0,0 +BRDA:2,115,1,0 +BRDA:2,116,0,0 +BRDA:2,116,1,0 +BRDA:2,117,0,0 +BRDA:2,117,1,0 +BRDA:2,118,0,0 +BRDA:2,118,1,0 +BRDA:2,119,0,0 +BRDA:2,119,1,0 +BRDA:2,120,0,0 +BRDA:2,120,1,0 +BRDA:2,121,0,0 +BRDA:2,121,1,0 +BRDA:2,122,0,0 +BRDA:2,122,1,0 +BRDA:2,123,0,0 +BRDA:2,123,1,0 +BRDA:2,124,0,0 +BRDA:2,124,1,0 +BRDA:2,125,0,0 +BRDA:2,125,1,0 +BRDA:2,126,0,0 +BRDA:2,126,1,0 +BRDA:2,127,0,0 +BRDA:2,127,1,0 +BRDA:2,128,0,0 +BRDA:2,128,1,0 +BRDA:2,128,2,0 +BRDA:2,129,0,0 +BRDA:2,129,1,0 +BRDA:2,130,0,0 +BRDA:2,130,1,0 +BRDA:2,131,0,0 +BRDA:2,131,1,0 +BRDA:2,131,2,0 +BRDA:2,131,3,0 +BRDA:2,131,4,0 +BRDA:2,132,0,0 +BRDA:2,132,1,0 +BRDA:2,133,0,0 +BRDA:2,133,1,0 +BRDA:2,134,0,0 +BRDA:2,134,1,0 +BRDA:2,135,0,0 +BRDA:2,135,1,0 +BRDA:2,136,0,0 +BRDA:2,136,1,0 +BRDA:2,137,0,0 +BRDA:2,137,1,0 +BRDA:2,138,0,0 +BRDA:2,138,1,0 +BRF:286 +BRH:0 +end_of_record +TN: +SF:coverage/lcov-report/sorter.js +FN:2,(anonymous_0) +FN:11,getTable +FN:15,getTableHeader +FN:19,getTableBody +FN:23,getNthColumn +FN:27,onFilterInput +FN:45,addSearchBox +FN:53,loadColumns +FN:78,loadRowData +FN:97,loadData +FN:106,sortByIndex +FN:108,(anonymous_11) +FN:120,(anonymous_12) +FN:137,removeSortIndicators +FN:145,addSortIndicators +FN:151,enableUI +FN:154,ithSorter +FN:157,(anonymous_17) +FN:184,(anonymous_18) +FNF:19 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,getTable +FNDA:0,getTableHeader +FNDA:0,getTableBody +FNDA:0,getNthColumn +FNDA:0,onFilterInput +FNDA:0,addSearchBox +FNDA:0,loadColumns +FNDA:0,loadRowData +FNDA:0,loadData +FNDA:0,sortByIndex +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,removeSortIndicators +FNDA:0,addSortIndicators +FNDA:0,enableUI +FNDA:0,ithSorter +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +DA:2,0 +DA:5,0 +DA:12,0 +DA:16,0 +DA:20,0 +DA:24,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:37,0 +DA:39,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:54,0 +DA:56,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:74,0 +DA:79,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:94,0 +DA:98,0 +DA:101,0 +DA:102,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:138,0 +DA:139,0 +DA:141,0 +DA:142,0 +DA:146,0 +DA:154,0 +DA:155,0 +DA:157,0 +DA:158,0 +DA:160,0 +DA:161,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:170,0 +DA:171,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:178,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:196,0 +LF:89 +LH:0 +BRDA:32,0,0,0 +BRDA:32,0,1,0 +BRDA:65,1,0,0 +BRDA:65,1,1,0 +BRDA:68,2,0,0 +BRDA:68,2,1,0 +BRDA:89,3,0,0 +BRDA:89,3,1,0 +BRDA:111,4,0,0 +BRDA:111,4,1,0 +BRDA:111,5,0,0 +BRDA:111,5,1,0 +BRDA:119,6,0,0 +BRDA:119,6,1,0 +BRDA:146,7,0,0 +BRDA:146,7,1,0 +BRDA:160,8,0,0 +BRDA:160,8,1,0 +BRDA:171,9,0,0 +BRDA:171,9,1,0 +BRDA:175,10,0,0 +BRDA:175,10,1,0 +BRDA:185,11,0,0 +BRDA:185,11,1,0 +BRF:24 +BRH:0 +end_of_record +TN: +SF:dist/index.js +FN:5,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:2,0 +DA:3,0 +DA:4,0 +DA:5,0 +LF:4 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:dist/commands/hello/index.js +FN:17,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:2,0 +DA:3,0 +DA:5,0 +DA:8,0 +DA:9,0 +DA:14,0 +DA:18,0 +DA:19,0 +DA:22,0 +LF:9 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:dist/commands/hello/world.js +FN:13,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:2,0 +DA:3,0 +DA:5,0 +DA:6,0 +DA:7,0 +DA:12,0 +DA:14,0 +DA:17,0 +LF:8 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/index.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/application/cases/continue-with-last-time-entry.case.ts +FN:7,(anonymous_0) +FN:12,(anonymous_1) +FNF:2 +FNH:2 +FNDA:2,(anonymous_0) +FNDA:2,(anonymous_1) +DA:1,1 +DA:5,1 +DA:8,2 +DA:9,2 +DA:13,2 +DA:14,2 +DA:15,1 +DA:23,1 +LF:8 +LH:8 +BRDA:9,0,0,0 +BRDA:14,1,0,1 +BRDA:14,1,1,1 +BRF:3 +BRH:2 +end_of_record +TN: +SF:src/application/cases/get-current-time-entry.case.ts +FN:10,(anonymous_0) +FN:15,(anonymous_1) +FNF:2 +FNH:2 +FNDA:3,(anonymous_0) +FNDA:3,(anonymous_1) +DA:1,1 +DA:8,1 +DA:11,3 +DA:12,3 +DA:16,3 +DA:17,3 +DA:18,2 +DA:19,2 +DA:20,1 +DA:23,1 +DA:26,1 +LF:11 +LH:11 +BRDA:17,0,0,2 +BRDA:17,0,1,1 +BRDA:19,1,0,1 +BRDA:19,1,1,1 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/application/cases/get-current-week-report.case.ts +FN:10,(anonymous_0) +FN:15,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:1,1 +DA:8,1 +DA:11,1 +DA:12,1 +DA:16,1 +DA:20,1 +LF:6 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/application/cases/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/application/cases/start-time-entry.case.ts +FN:14,(anonymous_0) +FN:20,(anonymous_1) +FN:29,(anonymous_2) +FNF:3 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +DA:1,1 +DA:12,1 +DA:15,0 +DA:16,0 +DA:17,0 +DA:21,0 +DA:22,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:39,0 +LF:13 +LH:2 +BRDA:17,0,0,0 +BRDA:30,1,0,0 +BRDA:30,1,1,0 +BRDA:35,2,0,0 +BRDA:35,2,1,0 +BRF:5 +BRH:0 +end_of_record +TN: +SF:src/application/repositories/index.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/index.ts +FN:6,isValidId +FNF:1 +FNH:0 +FNDA:0,isValidId +DA:1,1 +DA:2,1 +DA:3,1 +DA:6,1 +DA:7,0 +LF:5 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/entities/index.ts +FN:6,(anonymous_4) +FNF:1 +FNH:0 +FNDA:0,(anonymous_4) +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +LF:6 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/entities/project.ts +FN:5,(anonymous_0) +FNF:1 +FNH:1 +FNDA:1,(anonymous_0) +DA:1,1 +DA:6,1 +DA:7,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/entities/report-entry.ts +FN:5,(anonymous_0) +FN:11,(anonymous_1) +FN:15,(anonymous_2) +FNF:3 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +DA:1,1 +DA:4,1 +DA:6,0 +DA:7,0 +DA:12,0 +DA:16,0 +LF:6 +LH:2 +BRDA:11,0,0,0 +BRF:1 +BRH:0 +end_of_record +TN: +SF:src/core/entities/report.ts +FN:10,(anonymous_0) +FN:13,(anonymous_1) +FN:16,(anonymous_2) +FN:20,(anonymous_3) +FN:22,(anonymous_4) +FNF:5 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:2,1 +DA:4,1 +DA:6,1 +DA:11,1 +DA:12,0 +DA:13,0 +DA:17,1 +DA:21,0 +DA:22,0 +LF:9 +LH:5 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/entities/time-entry-list.ts +FN:6,(anonymous_0) +FN:10,(anonymous_1) +FN:11,(anonymous_2) +FN:14,(anonymous_3) +FNF:4 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:1,1 +DA:3,1 +DA:7,0 +DA:11,0 +DA:15,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:25,0 +LF:10 +LH:2 +BRDA:18,0,0,0 +BRDA:18,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/core/entities/time-entry.ts +FN:19,(anonymous_0) +FN:27,(anonymous_1) +FN:35,(anonymous_2) +FN:39,(anonymous_3) +FNF:4 +FNH:1 +FNDA:5,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:1,1 +DA:11,1 +DA:20,5 +DA:21,5 +DA:22,5 +DA:23,5 +DA:24,5 +DA:28,0 +DA:29,0 +DA:32,0 +DA:36,0 +DA:40,0 +LF:12 +LH:7 +BRDA:20,0,0,5 +BRDA:20,0,1,2 +BRDA:24,1,0,5 +BRDA:24,1,1,3 +BRDA:28,2,0,0 +BRDA:28,2,1,0 +BRF:6 +BRH:4 +end_of_record +TN: +SF:src/core/entities/time-helper.ts +FN:2,(anonymous_0) +FN:6,(anonymous_1) +FN:11,(anonymous_2) +FN:25,(anonymous_3) +FN:29,(anonymous_4) +FNF:5 +FNH:1 +FNDA:0,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:1,1 +DA:3,0 +DA:7,1 +DA:8,1 +DA:12,0 +DA:14,0 +DA:15,0 +DA:17,0 +DA:18,0 +DA:20,0 +DA:26,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +LF:15 +LH:3 +BRDA:3,0,0,0 +BRDA:3,0,1,0 +BRDA:12,1,0,0 +BRDA:12,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/core/errors/core.error.ts +FN:6,(anonymous_0) +FN:10,(anonymous_1) +FNF:2 +FNH:1 +FNDA:1,(anonymous_0) +FNDA:0,(anonymous_1) +DA:3,1 +DA:7,1 +DA:11,0 +LF:3 +LH:2 +BRDA:11,0,0,0 +BRDA:11,0,1,0 +BRDA:11,0,2,0 +BRDA:11,0,3,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/core/errors/error-codes.ts +FN:1,(anonymous_0) +FNF:1 +FNH:1 +FNDA:1,(anonymous_0) +DA:1,1 +DA:2,1 +LF:2 +LH:2 +BRDA:1,0,0,1 +BRDA:1,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/core/errors/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/errors/project-not-found.error.ts +FN:7,(anonymous_0) +FNF:1 +FNH:1 +FNDA:1,(anonymous_0) +DA:1,1 +DA:2,1 +DA:4,1 +DA:5,1 +DA:8,1 +DA:9,1 +LF:6 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/core/types/index.ts +FNF:0 +FNH:0 +DA:1,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record diff --git a/package.json b/package.json new file mode 100644 index 0000000..6386b82 --- /dev/null +++ b/package.json @@ -0,0 +1,78 @@ +{ + "author": "Ulises Santana @ulisesantana", + "bin": { + "track": "./bin/run.js" + }, + "dependencies": { + "@oclif/core": "^3", + "@oclif/plugin-help": "^5", + "@oclif/plugin-plugins": "^4" + }, + "description": "A CLI for Toggl Track", + "devDependencies": { + "@oclif/prettier-config": "^0.2.1", + "@oclif/test": "^3", + "@types/chai": "^4", + "@types/mocha": "^9.0.0", + "@types/node": "^18", + "chai": "^4.3.10", + "eslint": "^8.53.0", + "eslint-config-oclif": "^5", + "eslint-config-oclif-typescript": "^3", + "eslint-config-prettier": "^9.0.0", + "mocha": "^10", + "nyc": "15.1.0", + "oclif": "^3.17.2", + "shx": "^0.3.3", + "sinon": "17.0.1", + "ts-node": "^10.9.1", + "typescript": "^5" + }, + "engines": { + "node": ">=18.0.0" + }, + "files": [ + "/bin", + "/dist", + "/oclif.manifest.json" + ], + "homepage": "https://github.com/ulisesantana/track", + "license": "MIT", + "main": "dist/index.js", + "name": "track", + "oclif": { + "bin": "track", + "dirname": "track", + "commands": "./dist/commands", + "plugins": [ + "@oclif/plugin-help", + "@oclif/plugin-plugins" + ], + "topicSeparator": " ", + "topics": { + "hello": { + "description": "Say hello to the world and others" + } + } + }, + "repository": "ulisesantana/track", + "scripts": { + "build": "shx rm -rf dist && tsc -b", + "create:use-case": "./scripts/templates/generate-use-case.mjs", + "lint": "eslint . --ext .ts", + "lint:fix": "npm run lint -- --fix", + "postpack": "shx rm -f oclif.manifest.json", + "posttest": "npm run lint", + "prepack": "npm run build && oclif manifest && oclif readme", + "prepare": "npm run build", + "test": "mocha --forbid-only --bail \"test/**/*.test.ts\"", + "test:coverage": "nyc mocha --forbid-only --bail \"test/**/*.test.ts\"", + "version": "oclif readme && git add README.md" + }, + "version": "0.0.0", + "bugs": "https://github.com/ulisesantana/track/issues", + "keywords": [ + "oclif" + ], + "types": "dist/index.d.ts" +} diff --git a/scripts/templates/generate-use-case.mjs b/scripts/templates/generate-use-case.mjs new file mode 100755 index 0000000..221f992 --- /dev/null +++ b/scripts/templates/generate-use-case.mjs @@ -0,0 +1,111 @@ +#!/usr/bin/env node +import * as readline from 'node:readline/promises' +import * as fs from 'node:fs/promises' +import {stdin as input, stdout as output} from 'node:process' +import {EOL} from 'node:os' + +const rl = readline.createInterface({ input, output }) +await createUseCase(rl, fs) +rl.close() + +async function createUseCase(rl, fs) { + const answer = await rl.question('What is your new use case?\n') + const useCase = answer.replaceAll(" ", "-") + const useCasePath = `src/application/cases/${useCase}.case.ts` + const useCaseClass = generateUseCase(useCase) + const useCaseTestPath = `test/application/cases/${useCase}.case.test.ts` + const useCaseTest = generateUseCaseTest(useCase) + await Promise.all([ + fs.writeFile(useCasePath, useCaseClass), + fs.writeFile(useCaseTestPath, useCaseTest), + updateFile(fs, 'src/application/cases/index.ts', `export * from "./${useCase}.case"`) + ]) + console.log(`Use case "${answer}" created at ${useCasePath}.`) +} + +async function updateFile(fs, path, update) { + const file = await fs.readFile(path) + const imports = file.toString().split(EOL).filter(Boolean).concat(update).sort().join(EOL) + await fs.writeFile(path, imports) +} + +function pascalize(useCase) { + return useCase + .split("-") + .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase()) + .join(""); +} + +function generateUseCase(useCase) { + const pascalizedUseCase = `${pascalize(useCase)}UseCase` + return ` +import { UseCase } from "./use-case"; + +type Input = undefined +type Output = Promise + +export class ${pascalizedUseCase} implements UseCase{ + + constructor() {} + + async exec() { + return null + } +}` +} +function generateUseCaseTest(useCase) { + const pascalizedUseCase = `${pascalize(useCase)}UseCase` + return ` +import {expect} from 'chai'; +import sinon from 'sinon'; + +import {${pascalizedUseCase}} from '../../../src/application/cases' +import {ProjectRepository, TimeEntryRepository} from "../../../src/application/repositories"; +import {TimeHelper} from '../../../src/core'; +import {ProjectRepositoryDouble, TimeEntryRepositoryDouble} from "../../doubles"; + + +describe('${pascalizedUseCase}', () => { + let useCase: ${pascalizedUseCase}; + let timeEntryRepositoryMock: sinon.SinonStubbedInstance; + let projectRepositoryMock: sinon.SinonStubbedInstance; + let timeHelperMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + timeEntryRepositoryMock = sinon.createStubInstance(TimeEntryRepositoryDouble); + projectRepositoryMock = sinon.createStubInstance(ProjectRepositoryDouble); + timeHelperMock = sinon.createStubInstance(TimeHelper); + useCase = new ${pascalizedUseCase}(timeEntryRepositoryMock, projectRepositoryMock, timeHelperMock); + }); + + afterEach(() => { + sinon.restore(); + }); + + + it('should do something successfully', async () => { + const input = {description: 'Test Task', project: 123}; + timeEntryRepositoryMock.createEntry.resolves(); + projectRepositoryMock.getProjectByName.resolves(null); + + await useCase.exec(input); + + sinon.assert.calledWith(timeEntryRepositoryMock.createEntry, sinon.match.has('pid', 123)); + }); + + it('should throw an error for any reason', async () => { + const input = {description: 'Test Task', project: 'Unknown Project'}; + projectRepositoryMock.getProjectByName.resolves(null); + + try { + await useCase.exec(input); + expect.fail('should have thrown an error'); + } catch (error) { + expect(error).to.be.instanceOf(Error); + } + }); + +}); + +}` +} diff --git a/src/application/cases/continue-with-last-time-entry.case.ts b/src/application/cases/continue-with-last-time-entry.case.ts new file mode 100644 index 0000000..7365140 --- /dev/null +++ b/src/application/cases/continue-with-last-time-entry.case.ts @@ -0,0 +1,25 @@ +import {TimeEntry, TimeHelper} from "../../core"; +import {TimeEntryRepository} from "../repositories/time-entry.repository"; + + +export class ContinueWithLastTimeEntryUseCase { + + constructor( + private readonly timeEntryRepository: TimeEntryRepository, + private readonly timeHelper: TimeHelper = new TimeHelper() + ) {} + + async exec(): ReturnType { + const lastEntry = await this.timeEntryRepository.getLastEntry(); + if (lastEntry) { + return this.timeEntryRepository.createEntry(new TimeEntry({ + description: lastEntry.description, + id: lastEntry.id, + pid: lastEntry.pid, + wid: lastEntry.wid, + }), this.timeHelper.getCurrentUtcDate()); + } + + return lastEntry + } +} diff --git a/src/application/cases/get-current-time-entry.case.ts b/src/application/cases/get-current-time-entry.case.ts new file mode 100644 index 0000000..f042eeb --- /dev/null +++ b/src/application/cases/get-current-time-entry.case.ts @@ -0,0 +1,28 @@ +import {Nullable, Project, ProjectNotFoundError, TimeEntry} from "../../core"; +import {ProjectRepository, TimeEntryRepository} from "../repositories"; +import { UseCase } from "./use-case"; + +type Input = undefined +type Output = Promise> + +export class GetCurrentTimeEntryUseCase implements UseCase{ + + constructor( + private readonly timeEntryRepository: TimeEntryRepository, + private readonly projectRepository: ProjectRepository + ) {} + + async exec(): Output { + const currentEntry = await this.timeEntryRepository.getCurrentEntry(); + if (currentEntry) { + const project = await this.projectRepository.getProjectById(currentEntry.pid); + if (project === null) { + throw new ProjectNotFoundError(currentEntry.pid) + } + + return [currentEntry, project]; + } + + return null + } +} diff --git a/src/application/cases/get-current-week-report.case.ts b/src/application/cases/get-current-week-report.case.ts new file mode 100644 index 0000000..a239c8f --- /dev/null +++ b/src/application/cases/get-current-week-report.case.ts @@ -0,0 +1,22 @@ +import {Report} from "../../core"; +import {ProjectRepository, TimeEntryRepository} from "../repositories"; +import {UseCase} from "./use-case"; + +type Input = undefined +type Output = Promise + +export class GetCurrentWeekReportUseCase implements UseCase { + + constructor( + private readonly timeEntryRepository: TimeEntryRepository, + private readonly projectRepository: ProjectRepository + ) {} + + async exec() { + const [entries, projects] = await Promise.all([ + this.timeEntryRepository.getCurrentWeekEntries(), + this.projectRepository.getProjects() + ]) + return new Report(entries, projects) + } +} diff --git a/src/application/cases/index.ts b/src/application/cases/index.ts new file mode 100644 index 0000000..9e4f882 --- /dev/null +++ b/src/application/cases/index.ts @@ -0,0 +1,4 @@ +export * from "./continue-with-last-time-entry.case" +export * from "./get-current-time-entry.case" +export * from "./get-current-week-report.case" +export * from "./start-time-entry.case" \ No newline at end of file diff --git a/src/application/cases/start-time-entry.case.ts b/src/application/cases/start-time-entry.case.ts new file mode 100644 index 0000000..3123cf6 --- /dev/null +++ b/src/application/cases/start-time-entry.case.ts @@ -0,0 +1,42 @@ +import {ProjectNotFoundError, TimeEntry, TimeHelper, isValidId} from "../../core"; +import {TimeEntryRepository} from "../repositories"; +import {ProjectRepository} from "../repositories/project.repository"; +import {UseCase} from "./use-case"; + +type Input = { + description: string, + project: number | string +} +type Output = Promise + +export class StartTimeEntryUseCase implements UseCase { + + constructor( + private readonly timeEntryRepository: TimeEntryRepository, + private readonly projectRepository: ProjectRepository, + private readonly timeHelper: TimeHelper = new TimeHelper() + ) {} + + async exec({description, project}: Input) { + const pid = await this.getProjecId(project); + await this.timeEntryRepository.createEntry(new TimeEntry({ + description, + pid, + wid: this.timeEntryRepository.workspaceId, + }), this.timeHelper.getCurrentUtcDate()) + } + + private async getProjecId(project: number | string) { + if (isValidId(project)) { + return project + } + + const p = await this.projectRepository.getProjectByName(project) + if (p === null) { + throw new ProjectNotFoundError(project) + } + + return p.id + + } +} diff --git a/src/application/cases/use-case.ts b/src/application/cases/use-case.ts new file mode 100644 index 0000000..605d67b --- /dev/null +++ b/src/application/cases/use-case.ts @@ -0,0 +1,3 @@ +export interface UseCase { + exec (input?: Input): Output +} \ No newline at end of file diff --git a/src/application/repositories/index.ts b/src/application/repositories/index.ts new file mode 100644 index 0000000..16de2b4 --- /dev/null +++ b/src/application/repositories/index.ts @@ -0,0 +1,2 @@ +export * from "./project.repository" +export * from "./time-entry.repository" diff --git a/src/application/repositories/project.repository.ts b/src/application/repositories/project.repository.ts new file mode 100644 index 0000000..c525cb4 --- /dev/null +++ b/src/application/repositories/project.repository.ts @@ -0,0 +1,10 @@ +import {Nullable, Project} from "../../core"; + +export interface ProjectRepository { + getProjectById(id: number): Promise>; + + getProjectByName(name: string): Promise>; + + getProjects(): Promise>; + workspaceId: number +} diff --git a/src/application/repositories/time-entry.repository.ts b/src/application/repositories/time-entry.repository.ts new file mode 100644 index 0000000..773c576 --- /dev/null +++ b/src/application/repositories/time-entry.repository.ts @@ -0,0 +1,17 @@ +import {Nullable, TimeEntry, TimeEntryList} from '../../core'; + +export interface TimeEntryRepository { + createEntry(entry: TimeEntry, start: string): Promise; + + getCurrentEntry(): Promise>; + + getCurrentWeekEntries(): Promise; + + getLastEntry(): Promise>; + + getTodayEntries(): Promise; + + updateEntry(entry: Partial): Promise; + + workspaceId: number; +} diff --git a/src/commands/hello/index.ts b/src/commands/hello/index.ts new file mode 100644 index 0000000..7cdd57d --- /dev/null +++ b/src/commands/hello/index.ts @@ -0,0 +1,25 @@ +import {Args, Command, Flags} from '@oclif/core' + +export default class Hello extends Command { + static args = { + person: Args.string({description: 'Person to say hello to', required: true}), + } + + static description = 'Say hello' + + static examples = [ + `$ oex hello friend --from oclif +hello friend from oclif! (./src/commands/hello/index.ts) +`, + ] + + static flags = { + from: Flags.string({char: 'f', description: 'Who is saying hello', required: true}), + } + + async run(): Promise { + const {args, flags} = await this.parse(Hello) + + this.log(`hello ${args.person} from ${flags.from}! (./src/commands/hello/index.ts)`) + } +} diff --git a/src/commands/hello/world.ts b/src/commands/hello/world.ts new file mode 100644 index 0000000..8111043 --- /dev/null +++ b/src/commands/hello/world.ts @@ -0,0 +1,19 @@ +import {Command} from '@oclif/core' + +export default class World extends Command { + static args = {} + + static description = 'Say hello world' + + static examples = [ + `<%= config.bin %> <%= command.id %> +hello world! (./src/commands/hello/world.ts) +`, + ] + + static flags = {} + + async run(): Promise { + this.log('hello world! (./src/commands/hello/world.ts)') + } +} diff --git a/src/core/entities/duration.ts b/src/core/entities/duration.ts new file mode 100644 index 0000000..d7dd6f2 --- /dev/null +++ b/src/core/entities/duration.ts @@ -0,0 +1,31 @@ +import {TimeHelper} from "./time-helper"; + +export class Duration { + constructor(private duration: number = -1) { + } + + private static isDuration(duration: Duration | number): duration is Duration { + return duration instanceof Duration; + } + + get value() { + if (this.duration < 0) { + return Math.floor(Date.now() / 1000) + this.duration; + } + + return this.duration; + } + + set value(duration: Duration | number) { + this.duration = (Duration.isDuration(duration) ? duration.value : duration) as number; + } + + add(duration: Duration | number) { + this.duration += (Duration.isDuration(duration) ? duration.value : duration) as number + } + + toString() { + return `${TimeHelper.secondsToHmsString(this.value as number)}` + } + +} diff --git a/src/core/entities/index.ts b/src/core/entities/index.ts new file mode 100644 index 0000000..09bf54c --- /dev/null +++ b/src/core/entities/index.ts @@ -0,0 +1,7 @@ +export * from './duration' +export * from './project' +export * from './report' +export * from './report-entry'; +export * from './time-entry' +export * from './time-entry-list' +export * from './time-helper' diff --git a/src/core/entities/project.ts b/src/core/entities/project.ts new file mode 100644 index 0000000..7386f89 --- /dev/null +++ b/src/core/entities/project.ts @@ -0,0 +1,4 @@ +export class Project { + + constructor(readonly id: number, readonly name: string) {} +} diff --git a/src/core/entities/report-entry.ts b/src/core/entities/report-entry.ts new file mode 100644 index 0000000..6555485 --- /dev/null +++ b/src/core/entities/report-entry.ts @@ -0,0 +1,13 @@ +import {Project} from "./project"; +import {TimeEntry} from "./time-entry"; + +export class ReportEntry { + constructor( + private readonly entry: TimeEntry, + private readonly project: Project = new Project(entry.pid, "Unknown project") + ) {} + + toString() { + return `${this.entry} (${this.project.name})` + } +} diff --git a/src/core/entities/report.ts b/src/core/entities/report.ts new file mode 100644 index 0000000..7bbb508 --- /dev/null +++ b/src/core/entities/report.ts @@ -0,0 +1,20 @@ +import {Duration} from "./duration"; +import {Project} from "./project"; +import {ReportEntry} from "./report-entry"; +import {TimeEntryList} from "./time-entry-list"; + +export class Report { + readonly entries: ReportEntry[] + readonly totalDuration: Duration + + constructor(entries: TimeEntryList, projects: Record) { + this.totalDuration = entries.getTotalDuration() + this.entries = Object.values(entries.groupEntriesByDescription()) + .map(entry => new ReportEntry(entry, projects[entry.pid])) + } + + toString() { + const report = this.totalDuration.toString() + return [report, ...this.entries.map(entry => ` - ${entry}` )].join('\n') + } +} diff --git a/src/core/entities/time-entry-list.ts b/src/core/entities/time-entry-list.ts new file mode 100644 index 0000000..84e86b4 --- /dev/null +++ b/src/core/entities/time-entry-list.ts @@ -0,0 +1,34 @@ +import { Duration } from "./duration"; +import {TimeEntry} from "./time-entry"; + +export class TimeEntryList { + values: TimeEntry[]; + + constructor(values: TimeEntry[]) { + this.values = values; + } + + getTotalDuration(): Duration { + const totalDuration = new Duration(0) + + for (const {duration} of this.values) { + totalDuration.add(duration) + } + + return totalDuration + } + + groupEntriesByDescription(): Record { + const groupedEntries: Record = {}; + + for (const entry of this.values) { + if (groupedEntries[entry.description]) { + groupedEntries[entry.description].duration.add(entry.duration); + } else { + groupedEntries[entry.description] = new TimeEntry(entry) + } + } + + return groupedEntries; + } +} diff --git a/src/core/entities/time-entry.ts b/src/core/entities/time-entry.ts new file mode 100644 index 0000000..d27aaf2 --- /dev/null +++ b/src/core/entities/time-entry.ts @@ -0,0 +1,29 @@ +import {Duration} from "./duration"; + +export interface TimeEntryParams { + description: string, + duration?: Duration, + id?: number, + pid: number, + wid: number +} + +export class TimeEntry { + description: string; + duration: Duration; + id: number; + pid: number; + wid: number; + + constructor({ description, duration, id, pid, wid}: TimeEntryParams) { + this.id = id || Math.floor(Math.random() * 10**16); + this.pid = pid; + this.wid = wid; + this.description = description; + this.duration = duration || new Duration(); + } + + toString(): string { + return `${this.duration} - ${this.description}`; + } +} diff --git a/src/core/entities/time-helper.ts b/src/core/entities/time-helper.ts new file mode 100644 index 0000000..4b44403 --- /dev/null +++ b/src/core/entities/time-helper.ts @@ -0,0 +1,35 @@ +export class TimeHelper { + private static addZeroPrefix(number: number): string { + return number > 9 ? number.toString() : `0${number}`; + } + + getCurrentUtcDate(): string { + const now = new Date(); + return now.toISOString(); + } + + getWeekDates(date: Date): [Date, Date] { + const dayOfWeek = date.getDay() === 0 ? 6 : date.getDay() - 1 + + const startOfWeek = new Date(date); + startOfWeek.setDate(date.getDate() - dayOfWeek); + + const endOfWeek = new Date(startOfWeek); + endOfWeek.setDate(startOfWeek.getDate() + 6); + + return [startOfWeek, endOfWeek]; + } + + + + secondsToHmsString(seconds: number): string { + return TimeHelper.secondsToHmsString(seconds) + } + + static secondsToHmsString(seconds: number): string { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const remainingSeconds = seconds % 60; + return `${TimeHelper.addZeroPrefix(hours)}h ${TimeHelper.addZeroPrefix(minutes)}m ${TimeHelper.addZeroPrefix(remainingSeconds)}s`; + } +} diff --git a/src/core/errors/core.error.ts b/src/core/errors/core.error.ts new file mode 100644 index 0000000..29d0086 --- /dev/null +++ b/src/core/errors/core.error.ts @@ -0,0 +1,16 @@ +/* eslint-disable perfectionist/sort-classes */ +import { ErrorCodes } from './error-codes' +export abstract class CoreError extends Error { + abstract readonly code: ErrorCodes + + protected constructor (message: string) { + super(message) + } + + static isError (error: unknown): error is CoreError { + return typeof error === 'object' && + error !== null && + Object.hasOwn(error, 'code') && + Object.hasOwn(error, 'message') + } +} diff --git a/src/core/errors/error-codes.ts b/src/core/errors/error-codes.ts new file mode 100644 index 0000000..2772481 --- /dev/null +++ b/src/core/errors/error-codes.ts @@ -0,0 +1,3 @@ +export enum ErrorCodes { + ProjectNotFound = 'PROJECT_NOT_FOUND', +} diff --git a/src/core/errors/index.ts b/src/core/errors/index.ts new file mode 100644 index 0000000..c337730 --- /dev/null +++ b/src/core/errors/index.ts @@ -0,0 +1,3 @@ +export * from './core.error' +export * from './error-codes' +export * from './project-not-found.error' diff --git a/src/core/errors/project-not-found.error.ts b/src/core/errors/project-not-found.error.ts new file mode 100644 index 0000000..eff9ca8 --- /dev/null +++ b/src/core/errors/project-not-found.error.ts @@ -0,0 +1,11 @@ +import { CoreError } from './core.error' +import { ErrorCodes } from './error-codes' + +export class ProjectNotFoundError extends CoreError { + readonly code = ErrorCodes.ProjectNotFound + + constructor (key: number | string) { + super(`Project "${key}" not found.`) + this.name = 'ProjectNotFoundError' + } +} diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..cba312d --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,8 @@ +export * from './entities' +export * from './errors' +export * from './types' + + +export function isValidId(input: number | string): input is number { + return /^\d+$/.test(String(input)) +} diff --git a/src/core/types/index.ts b/src/core/types/index.ts new file mode 100644 index 0000000..e41f7ef --- /dev/null +++ b/src/core/types/index.ts @@ -0,0 +1 @@ +export * from './nullable' diff --git a/src/core/types/nullable.ts b/src/core/types/nullable.ts new file mode 100644 index 0000000..36fa025 --- /dev/null +++ b/src/core/types/nullable.ts @@ -0,0 +1 @@ +export type Nullable = T | null diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..e32b0b2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export {run} from '@oclif/core' diff --git a/test/application/cases/continue-with-last-time-entry.case.test.ts b/test/application/cases/continue-with-last-time-entry.case.test.ts new file mode 100644 index 0000000..8cb77a8 --- /dev/null +++ b/test/application/cases/continue-with-last-time-entry.case.test.ts @@ -0,0 +1,49 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; + +import {ContinueWithLastTimeEntryUseCase} from "../../../src/application/cases"; +import {TimeEntryRepository} from "../../../src/application/repositories"; +import {TimeEntry, TimeHelper} from "../../../src/core"; +import {Duration} from "../../../src/core/entities/duration"; +import {TimeEntryRepositoryDouble} from "../../doubles"; + + + +describe('ContinueWithLastTimeEntryUseCase', () => { + let mockTimeEntryRepository: sinon.SinonStubbedInstance; + let useCase: ContinueWithLastTimeEntryUseCase; + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + mockTimeEntryRepository = sandbox.createStubInstance(TimeEntryRepositoryDouble); + useCase = new ContinueWithLastTimeEntryUseCase(mockTimeEntryRepository as unknown as TimeEntryRepository, new TimeHelper()); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should continue with last time entry when there is a last entry', async () => { + const lastEntry = new TimeEntry({ description: "Test Description", duration: new Duration(60), id: 1, pid: 456, wid: 123 }); + const newEntry = new TimeEntry({...lastEntry, duration: new Duration(-1)}) + mockTimeEntryRepository.getLastEntry.returns(Promise.resolve(lastEntry)); + mockTimeEntryRepository.createEntry.returns(Promise.resolve(newEntry)); + + const result = await useCase.exec(); + + expect(result).to.equal(newEntry); + sinon.assert.calledOnce(mockTimeEntryRepository.getLastEntry); + sinon.assert.calledOnceWithExactly(mockTimeEntryRepository.createEntry, newEntry, sinon.match.string); + }); + + it('should return null when there is no last entry', async () => { + mockTimeEntryRepository.getLastEntry.returns(Promise.resolve(null)); + + const result = await useCase.exec(); + + expect(result).to.be.null; + sinon.assert.calledOnce(mockTimeEntryRepository.getLastEntry); + sinon.assert.notCalled(mockTimeEntryRepository.createEntry); + }); +}); diff --git a/test/application/cases/get-current-time-entry.case.test.ts b/test/application/cases/get-current-time-entry.case.test.ts new file mode 100644 index 0000000..a638da3 --- /dev/null +++ b/test/application/cases/get-current-time-entry.case.test.ts @@ -0,0 +1,56 @@ +import {expect} from 'chai'; +import sinon from 'sinon'; + +import {GetCurrentTimeEntryUseCase} from "../../../src/application/cases"; +import {Project, ProjectNotFoundError, TimeEntry} from "../../../src/core"; +import {ProjectRepositoryDouble, TimeEntryRepositoryDouble} from "../../doubles"; + +describe('GetCurrentTimeEntryUseCase', () => { + let useCase: GetCurrentTimeEntryUseCase; + let timeEntryRepositoryMock: sinon.SinonStubbedInstance; + let projectRepositoryMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + timeEntryRepositoryMock = sinon.createStubInstance(TimeEntryRepositoryDouble); + projectRepositoryMock = sinon.createStubInstance(ProjectRepositoryDouble); + useCase = new GetCurrentTimeEntryUseCase(timeEntryRepositoryMock, projectRepositoryMock); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should return the current time entry and its project when both are found', async () => { + const currentEntry = new TimeEntry({ description: 'Work', pid: 1, wid: 1 }); + const project = new Project(1, 'Test Project'); + timeEntryRepositoryMock.getCurrentEntry.resolves(currentEntry); + projectRepositoryMock.getProjectById.resolves(project); + + const result = await useCase.exec(); + + expect(result).to.deep.equal([currentEntry, project]); + }); + + it('should return null if there is no current time entry', async () => { + timeEntryRepositoryMock.getCurrentEntry.resolves(null); + + const result = await useCase.exec(); + + expect(result).to.be.null; + }); + + it('should throw ProjectNotFoundError if the project for the current time entry is not found', async () => { + const currentEntry = new TimeEntry({ description: 'Work', pid: 1, wid: 1 }); + timeEntryRepositoryMock.getCurrentEntry.resolves(currentEntry); + projectRepositoryMock.getProjectById.resolves(null); + + try { + await useCase.exec(); + expect.fail('should have thrown ProjectNotFoundError'); + } catch (error) { + expect(error).to.be.instanceOf(ProjectNotFoundError); + } + }); + + +}); diff --git a/test/application/cases/get-current-week-report.case.test.ts b/test/application/cases/get-current-week-report.case.test.ts new file mode 100644 index 0000000..0058778 --- /dev/null +++ b/test/application/cases/get-current-week-report.case.test.ts @@ -0,0 +1,46 @@ +import {expect} from 'chai'; +import sinon from 'sinon'; + +import {GetCurrentWeekReportUseCase} from '../../../src/application/cases' +import {ProjectRepository, TimeEntryRepository} from "../../../src/application/repositories"; +import {ProjectRepositoryDouble, TimeEntryRepositoryDouble} from "../../doubles"; + + +describe('GetCurrentWeekReportUseCase', () => { + let useCase: GetCurrentWeekReportUseCase; + let timeEntryRepositoryMock: sinon.SinonStubbedInstance; + let projectRepositoryMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + timeEntryRepositoryMock = sinon.createStubInstance(TimeEntryRepositoryDouble); + projectRepositoryMock = sinon.createStubInstance(ProjectRepositoryDouble); + useCase = new GetCurrentWeekReportUseCase(timeEntryRepositoryMock, projectRepositoryMock); + }); + + afterEach(() => { + sinon.restore(); + }); + + + it.skip('should do something successfully', async () => { + timeEntryRepositoryMock.createEntry.resolves(); + projectRepositoryMock.getProjectByName.resolves(null); + + await useCase.exec(); + + sinon.assert.calledWith(timeEntryRepositoryMock.createEntry, sinon.match.has('pid', 123)); + }); + + it.skip('should throw an error for any reason', async () => { + projectRepositoryMock.getProjectByName.resolves(null); + + try { + await useCase.exec(); + expect.fail('should have thrown an error'); + } catch (error) { + expect(error).to.be.instanceOf(Error); + } + }); + +}); + diff --git a/test/application/cases/start-time-entry.case.test.ts b/test/application/cases/start-time-entry.case.test.ts new file mode 100644 index 0000000..915f1a8 --- /dev/null +++ b/test/application/cases/start-time-entry.case.test.ts @@ -0,0 +1,61 @@ +import {expect} from 'chai'; +import sinon from 'sinon'; + +import {StartTimeEntryUseCase} from '../../../src/application/cases' +import {ProjectRepository, TimeEntryRepository} from "../../../src/application/repositories"; +import {ProjectNotFoundError, TimeHelper} from '../../../src/core'; +import {ProjectRepositoryDouble, TimeEntryRepositoryDouble} from "../../doubles"; + +describe('StartTimeEntryUseCase', () => { + let useCase: StartTimeEntryUseCase; + let timeEntryRepositoryMock: sinon.SinonStubbedInstance; + let projectRepositoryMock: sinon.SinonStubbedInstance; + let timeHelperMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + timeEntryRepositoryMock = sinon.createStubInstance(TimeEntryRepositoryDouble); + projectRepositoryMock = sinon.createStubInstance(ProjectRepositoryDouble); + timeHelperMock = sinon.createStubInstance(TimeHelper); + useCase = new StartTimeEntryUseCase(timeEntryRepositoryMock, projectRepositoryMock, timeHelperMock); + }); + + afterEach(() => { + sinon.restore(); + }); + + + it('should start a time entry with a valid project ID', async () => { + const input = {description: 'Test Task', project: 123}; + timeEntryRepositoryMock.createEntry.resolves(); + projectRepositoryMock.getProjectByName.resolves(null); // Assuming this is not called in this case + + await useCase.exec(input); + + sinon.assert.calledWith(timeEntryRepositoryMock.createEntry, sinon.match.has('pid', 123)); + }); + + it('should start a time entry with a valid project name', async () => { + const input = {description: 'Test Task', project: 'Test Project'}; + const project = {id: 123, name: 'Test Project'}; + projectRepositoryMock.getProjectByName.resolves(project); + timeEntryRepositoryMock.createEntry.resolves(); + + await useCase.exec(input); + + sinon.assert.calledWith(projectRepositoryMock.getProjectByName, 'Test Project'); + sinon.assert.calledWith(timeEntryRepositoryMock.createEntry, sinon.match.has('pid', 123)); + }); + + it('should throw an error if the project is not found', async () => { + const input = {description: 'Test Task', project: 'Unknown Project'}; + projectRepositoryMock.getProjectByName.resolves(null); + + try { + await useCase.exec(input); + expect.fail('should have thrown an error'); + } catch (error) { + expect(error).to.be.instanceOf(ProjectNotFoundError); + } + }); + +}); diff --git a/test/commands/hello/index.test.ts b/test/commands/hello/index.test.ts new file mode 100644 index 0000000..f4e5ebe --- /dev/null +++ b/test/commands/hello/index.test.ts @@ -0,0 +1,10 @@ +import {expect, test} from '@oclif/test' + +describe('hello', () => { + test + .stdout() + .command(['hello', 'friend', '--from=oclif']) + .it('runs hello cmd', ctx => { + expect(ctx.stdout).to.contain('hello friend from oclif!') + }) +}) diff --git a/test/commands/hello/world.test.ts b/test/commands/hello/world.test.ts new file mode 100644 index 0000000..8096cba --- /dev/null +++ b/test/commands/hello/world.test.ts @@ -0,0 +1,10 @@ +import {expect, test} from '@oclif/test' + +describe('hello world', () => { + test + .stdout() + .command(['hello:world']) + .it('runs hello world cmd', ctx => { + expect(ctx.stdout).to.contain('hello world!') + }) +}) diff --git a/test/core/is-valid-id.test.ts b/test/core/is-valid-id.test.ts new file mode 100644 index 0000000..87ba9bf --- /dev/null +++ b/test/core/is-valid-id.test.ts @@ -0,0 +1,11 @@ +import { expect } from 'chai'; + +import {isValidId} from '../../src/core'; + +describe('Id validator', () => { + it('should validate ids with just digits', () => { + expect(isValidId("123")).to.be.true; + expect(isValidId("abc")).to.be.false; + expect(isValidId("12a")).to.be.false; + }); +}); diff --git a/test/core/report-entry.test.ts b/test/core/report-entry.test.ts new file mode 100644 index 0000000..e19e03d --- /dev/null +++ b/test/core/report-entry.test.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; + +import {Project, ReportEntry, TimeEntry} from "../../src/core"; +import {Duration} from "../../src/core/entities/duration"; + +describe('ReportEntry', () => { + it('should create a report entry with the provided project', () => { + const timeEntry = new TimeEntry({ description: 'Work', duration: new Duration(3728), pid: 1, wid: 1 }); + const project = new Project(1, 'Test Project'); + const reportEntry = new ReportEntry(timeEntry, project); + + expect(reportEntry.toString()).to.equal('01h 02m 08s - Work (Test Project)'); // Adjust based on TimeEntry.toString() implementation + }); + + it('should create a report entry with a default project if none is provided', () => { + const timeEntry = new TimeEntry({ description: 'Work', duration: new Duration(3728), pid: 1, wid: 1 }); + const reportEntry = new ReportEntry(timeEntry); + + expect(reportEntry.toString()).to.equal('01h 02m 08s - Work (Unknown project)'); // Adjust based on TimeEntry.toString() implementation + }); + +}); diff --git a/test/core/report.test.ts b/test/core/report.test.ts new file mode 100644 index 0000000..71770ca --- /dev/null +++ b/test/core/report.test.ts @@ -0,0 +1,20 @@ +import {expect} from 'chai'; +import 'mocha'; + +import {Duration, Project, Report, TimeEntry, TimeEntryList} from "../../src/core"; + +describe('Report', () => { + it('should return a formatted string representation of the report', () => { + const timeEntries = new TimeEntryList([ + new TimeEntry({ description: 'Work', duration: new Duration(3600), pid: 1, wid: 1 }), + new TimeEntry({ description: 'Meeting', duration: new Duration(1683), pid: 2, wid: 1 }) + ]); + const projects = { '1': new Project(1, 'Project A'), '2': new Project(2, 'Project B') }; + const report = new Report(timeEntries, projects); + const reportString = report.toString(); + + expect(reportString).to.be.equal(`01h 28m 03s + - 01h 00m 00s - Work (Project A) + - 00h 28m 03s - Meeting (Project B)`); + }); +}); diff --git a/test/core/time-entry-list.test.ts b/test/core/time-entry-list.test.ts new file mode 100644 index 0000000..a6f5b4e --- /dev/null +++ b/test/core/time-entry-list.test.ts @@ -0,0 +1,91 @@ +import { expect } from 'chai'; + +import {TimeEntry, TimeEntryList} from "../../src/core"; +import {Duration} from "../../src/core/entities/duration"; + +describe('TimeEntryList', () => { + describe('getTotalDuration', () => { + it('should return 0 for an empty list', () => { + const list = new TimeEntryList([]); + expect(list.getTotalDuration().value).to.equal(0); + }); + + it('should return the correct total duration for a single entry', () => { + const entry = new TimeEntry({ description: 'Task 1', duration: new Duration(60), id: 1, pid: 100, wid: 200 }); + const list = new TimeEntryList([entry]); + expect(list.getTotalDuration().value).to.equal(60); + }); + + it('should return the correct total duration for multiple entries', () => { + const entries = [ + new TimeEntry({ description: 'Task 1', duration: new Duration(60), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: 'Task 2', duration: new Duration(150), id: 2, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + expect(list.getTotalDuration().value).to.equal(210); + }); + + it('should handle durations with floating point numbers correctly', () => { + const entries = [ + new TimeEntry({ description: 'Task 1', duration: new Duration(60.5), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: 'Task 2', duration: new Duration(59.5), id: 2, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + expect(list.getTotalDuration().value).to.be.closeTo(120, 0.1); + }); + }); + + describe('groupEntriesByDescription', () => { + it('should handle an empty list', () => { + const list = new TimeEntryList([]); + expect(list.groupEntriesByDescription()).to.deep.equal({}); + }); + + it('should group entries correctly by description', () => { + const entries = [ + new TimeEntry({ description: 'Task', duration: new Duration(60), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: 'Task', duration: new Duration(40), id: 2, pid: 100, wid: 200 }), + new TimeEntry({ description: 'Meeting', duration: new Duration(30), id: 3, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + const grouped = list.groupEntriesByDescription(); + + expect(Object.keys(grouped)).to.have.lengthOf(2); + expect(grouped.Task.duration.value).to.equal(100); + expect(grouped.Meeting.duration.value).to.equal(30); + }); + + it('should handle unique descriptions', () => { + const entries = [ + new TimeEntry({ description: 'Task 1', duration: new Duration(60), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: 'Task 2', duration: new Duration(40), id: 2, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + const grouped = list.groupEntriesByDescription(); + + expect(grouped['Task 1'].duration.value).to.equal(60); + expect(grouped['Task 2'].duration.value).to.equal(40); + }); + + it('should handle entries with empty descriptions', () => { + const entries = [ + new TimeEntry({ description: '', duration: new Duration(60), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: '', duration: new Duration(40), id: 2, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + const grouped = list.groupEntriesByDescription(); + expect(grouped[''].duration.value).to.equal(100); + }); + + it('should treat descriptions with different cases as distinct', () => { + const entries = [ + new TimeEntry({ description: 'Task', duration: new Duration(30), id: 1, pid: 100, wid: 200 }), + new TimeEntry({ description: 'task', duration: new Duration(70), id: 2, pid: 100, wid: 200 }), + ]; + const list = new TimeEntryList(entries); + const grouped = list.groupEntriesByDescription(); + expect(grouped.Task.duration.value).to.equal(30); + expect(grouped.task.duration.value).to.equal(70); + }); + }); +}); diff --git a/test/core/time-entry.test.ts b/test/core/time-entry.test.ts new file mode 100644 index 0000000..8a955cc --- /dev/null +++ b/test/core/time-entry.test.ts @@ -0,0 +1,27 @@ +import {expect} from 'chai'; +import 'mocha'; + +import {TimeEntry} from "../../src/core"; +import {Duration} from "../../src/core/entities/duration"; + +describe('TimeEntry', () => { + it('should correctly initialize a TimeEntry object', () => { + const timeEntry = new TimeEntry({description: "Prueba de descripción", duration: new Duration(3600), id: 1, pid: 100, wid: 200}); + + expect(timeEntry.id).to.equal(1); + expect(timeEntry.pid).to.equal(100); + expect(timeEntry.wid).to.equal(200); + expect(timeEntry.description).to.equal("Prueba de descripción"); + expect(timeEntry.duration.value).to.equal(3600); + }); + + it('should return the correct string representation', () => { + const timeEntry = new TimeEntry({description: "Prueba de descripción", duration: new Duration(3600), id: 1, pid: 100, wid: 200}) + let expectedStr = "01h 00m 00s - Prueba de descripción"; + expect(timeEntry.toString()).to.equal(expectedStr); + + timeEntry.duration.value = (Math.floor(Date.now() / 1000) - 3665) * -1; + expectedStr = "01h 01m 05s - Prueba de descripción"; + expect(timeEntry.toString()).to.equal(expectedStr); + }); +}); diff --git a/test/core/time-helper.test.ts b/test/core/time-helper.test.ts new file mode 100644 index 0000000..24f36f4 --- /dev/null +++ b/test/core/time-helper.test.ts @@ -0,0 +1,42 @@ +import { expect } from 'chai'; + +import {TimeHelper} from "../../src/core"; + +describe('TimeHelper.getWeekDates', () => { + const th = new TimeHelper() + // Define an array of test cases with descriptions + const testCases = [ + { + date: new Date(2023, 3, 24, 12), // April 24, 2023 + description: 'a given Monday', + expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023 + expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023 + }, + { + date: new Date(2023, 3, 26, 12), // April 26, 2023 + description: 'a given Wednesday', + expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023 + expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023 + }, + { + date: new Date(2023, 3, 30, 12), // April 30, 2023 + description: 'a given Sunday', + expectedEnd: new Date(2023, 3, 30, 12), // April 30, 2023 + expectedStart: new Date(2023, 3, 24, 12) // April 24, 2023 + }, + { + date: new Date(2023, 0, 1, 12), // January 1, 2023 + description: 'New Year (January 1st)', + expectedEnd: new Date(2023, 0, 1, 12), // January 1, 2023 + expectedStart: new Date(2022, 11, 26, 12) // December 26, 2022 + } + ]; + + for (const { date, description, expectedEnd, expectedStart } of testCases) { + it(`should return correct start and end weekday dates for ${description}`, () => { + const [start, end] = th.getWeekDates(date); + expect(start).to.deep.equal(expectedStart); + expect(end).to.deep.equal(expectedEnd); + }); + } +}); diff --git a/test/doubles/index.ts b/test/doubles/index.ts new file mode 100644 index 0000000..48419bc --- /dev/null +++ b/test/doubles/index.ts @@ -0,0 +1,2 @@ +export * from "./project.repository.double" +export * from "./time-entry.repository.double" diff --git a/test/doubles/project.repository.double.ts b/test/doubles/project.repository.double.ts new file mode 100644 index 0000000..1c976bb --- /dev/null +++ b/test/doubles/project.repository.double.ts @@ -0,0 +1,19 @@ +import {ProjectRepository} from "../../src/application/repositories"; +import {Nullable, Project} from "../../src/core"; + +export class ProjectRepositoryDouble implements ProjectRepository { + workspaceId = 456 + + async getProjectById(id: number): Promise> { + return new Project(id, "Dummy project"); + } + + async getProjectByName(name: string): Promise> { + return new Project(123, name); + } + + async getProjects(): Promise> { + return {123: new Project(123, "Dummy project")}; + } + +} diff --git a/test/doubles/time-entry.repository.double.ts b/test/doubles/time-entry.repository.double.ts new file mode 100644 index 0000000..cad6748 --- /dev/null +++ b/test/doubles/time-entry.repository.double.ts @@ -0,0 +1,39 @@ +import {TimeEntryRepository} from "../../src/application/repositories"; +import {Nullable, TimeEntry, TimeEntryList} from "../../src/core"; + +export class TimeEntryRepositoryDouble implements TimeEntryRepository { + private currentEntry: Nullable = null + constructor(readonly workspaceId: number = 123) { + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async createEntry(entry: TimeEntry, start: string) { + return entry + } + + async getCurrentEntry() { + return this.currentEntry; + } + + async getCurrentWeekEntries() { + return new TimeEntryList([]); + } + + async getLastEntry() { + return null; + } + + async getTodayEntries() { + return new TimeEntryList([]); + } + + setCurrentEntry(entry: Nullable): TimeEntryRepositoryDouble { + this.currentEntry = entry + return this + } + + async updateEntry(entry: Partial) { + return new TimeEntry({description: "Dumb", id: 0, pid: 0, wid: 0, ...entry}) + } + +} diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 0000000..5d44188 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../tsconfig", + "compilerOptions": { + "noEmit": true, + "rootDir": "..", + "rootDirs": [ + "src", "test" + ], + "esModuleInterop": true + }, + "references": [ + {"path": ".."} + ], + "include": ["src/**/*", "test/**/*"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ce06bdc --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "declaration": true, + "module": "commonjs", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "target": "es2022", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src/**/*"] +}