├── .all-contributorsrc ├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── release.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── .yo-rc.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── commitlint.config.js ├── docs ├── example-output-full.png ├── example-output-mutation.png └── example-output.png ├── package.json ├── src ├── __tests__ │ ├── __snapshots__ │ │ └── formatMessage.test.js.snap │ ├── formatMessage.test.js │ └── logging.test.js ├── formatMessage.js ├── index.js └── logging.js ├── wallaby.config.js └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "apollo-link-logger", 3 | "projectOwner": "blackxored", 4 | "files": [ 5 | "README.md" 6 | ], 7 | "imageSize": 100, 8 | "commit": false, 9 | "contributors": [ 10 | { 11 | "login": "blackxored", 12 | "name": "Adrian Perez", 13 | "avatar_url": "https://avatars3.githubusercontent.com/u/133308?v=4", 14 | "profile": "https://adrianperez.codes", 15 | "contributions": [ 16 | "code", 17 | "doc", 18 | "infra", 19 | "test" 20 | ] 21 | }, 22 | { 23 | "login": "adambom", 24 | "name": "Adam Savitzky", 25 | "avatar_url": "https://avatars3.githubusercontent.com/u/294597?s=460&v=4", 26 | "profile": "https://github.com/adambom", 27 | "contributions": [ 28 | "code" 29 | ] 30 | }, 31 | { 32 | "login": "gnerkus", 33 | "name": "Ifeanyi Oraelosi", 34 | "avatar_url": "https://avatars3.githubusercontent.com/u/3065138?v=4", 35 | "profile": "https://github.com/gnerkus", 36 | "contributions": [ 37 | "code" 38 | ] 39 | }, 40 | { 41 | "login": "romarioraffington", 42 | "name": "Romario", 43 | "avatar_url": "https://avatars0.githubusercontent.com/u/7076981?v=4", 44 | "profile": "https://github.com/romarioraffington", 45 | "contributions": [ 46 | "bug", 47 | "ideas" 48 | ] 49 | }, 50 | { 51 | "login": "Horoshiy", 52 | "name": "Yuriy Kornienko", 53 | "avatar_url": "https://avatars0.githubusercontent.com/u/6183943?v=4", 54 | "profile": "http://www.dinamchiki.ru", 55 | "contributions": [ 56 | "code" 57 | ] 58 | }, 59 | { 60 | "login": "dmt0", 61 | "name": "Dmitry Shvedov", 62 | "avatar_url": "https://avatars1.githubusercontent.com/u/2717746?v=4", 63 | "profile": "https://github.com/dmt0", 64 | "contributions": [ 65 | "code" 66 | ] 67 | } 68 | ], 69 | "repoType": "github" 70 | } 71 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": "env", 3 | "env": { 4 | "cjs": { 5 | "plugins": [["transform-es2015-modules-commonjs", { "loose": true }]] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | dist 4 | wallaby.config.js 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['airbnb-base', 'prettier'], 3 | parser: 'babel-eslint', 4 | plugins: ['prettier', 'jest'], 5 | env: { 6 | jest: true, 7 | }, 8 | rules: { 9 | 'arrow-body-style': 0, 10 | 'arrow-parens': 0, // does not work with Flow generic types. 11 | 'global-require': 0, // used by react-native 12 | 'import/first': 0, // we sort by unit/atom 13 | 'import/no-named-as-default': 0, // we export components for testing 14 | 'import/prefer-default-export': 0, // actions can have only one action 15 | 'no-confusing-arrow': 0, // this rule is confusing 16 | 'no-duplicate-imports': 0, // handled by eslint-plugin-import 17 | 'no-underscore-dangle': 0, 18 | 'require-jsdoc': 'warn', 19 | 'valid-jsdoc': 'error', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | * `apollo-link-logger` version: 15 | * `node` version: 16 | * `npm` (or `yarn`) version: 17 | 18 | Relevant code or config 19 | 20 | ```javascript 21 | ``` 22 | 23 | What you did: 24 | 25 | What happened: 26 | 27 | 28 | 29 | Reproduction repository: 30 | 31 | 35 | 36 | Problem description: 37 | 38 | Suggested solution: 39 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | **What**: 20 | 21 | 22 | 23 | **Why**: 24 | 25 | 26 | 27 | **How**: 28 | 29 | 30 | 31 | **Checklist**: 32 | 33 | 34 | 35 | 36 | 37 | * [ ] Documentation 38 | * [ ] Tests 39 | * [ ] Ready to be merged 40 | 41 | * [ ] Added myself to contributors table 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | release: 8 | name: Release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 0 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: "lts/*" 19 | - name: Install dependencies 20 | run: yarn 21 | - name: Release 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 25 | run: npx semantic-release 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node ### 2 | 3 | # Logs 4 | logs 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Optional npm cache directory 10 | .npm 11 | 12 | # Dependency directories 13 | /node_modules 14 | /jspm_packages 15 | /bower_components 16 | 17 | # Yarn Integrity file 18 | .yarn-integrity 19 | 20 | # Optional eslint cache 21 | .eslintcache 22 | 23 | # dotenv environment variables file(s) 24 | .env 25 | .env.* 26 | 27 | #Build generated 28 | dist/ 29 | build/ 30 | es/ 31 | lib/ 32 | coverage/ 33 | 34 | 35 | ### SublimeText ### 36 | # cache files for sublime text 37 | *.tmlanguage.cache 38 | *.tmPreferences.cache 39 | *.stTheme.cache 40 | 41 | # workspace files are user-specific 42 | *.sublime-workspace 43 | 44 | # project files should be checked into the repository, unless a significant 45 | # proportion of contributors will probably not be using SublimeText 46 | # *.sublime-project 47 | 48 | 49 | ### VisualStudioCode ### 50 | .vscode/* 51 | !.vscode/settings.json 52 | !.vscode/tasks.json 53 | !.vscode/launch.json 54 | !.vscode/extensions.json 55 | 56 | ### WebStorm/IntelliJ ### 57 | /.idea 58 | modules.xml 59 | *.ipr 60 | 61 | 62 | ### System Files ### 63 | .DS_Store 64 | 65 | # Windows thumbnail cache files 66 | Thumbs.db 67 | ehthumbs.db 68 | ehthumbs_vista.db 69 | 70 | # Folder config file 71 | Desktop.ini 72 | 73 | # Recycle Bin used on file shares 74 | $RECYCLE.BIN/ 75 | 76 | # Thumbnails 77 | ._* 78 | 79 | # Files that might appear in the root of a volume 80 | .DocumentRevisions-V100 81 | .fseventsd 82 | .Spotlight-V100 83 | .TemporaryItems 84 | .Trashes 85 | .VolumeIcon.icns 86 | ### Node ### 87 | 88 | # Logs 89 | logs 90 | npm-debug.log* 91 | yarn-debug.log* 92 | yarn-error.log* 93 | 94 | # Optional npm cache directory 95 | .npm 96 | 97 | # Dependency directories 98 | /node_modules 99 | /jspm_packages 100 | /bower_components 101 | 102 | # Yarn Integrity file 103 | .yarn-integrity 104 | 105 | # Optional eslint cache 106 | .eslintcache 107 | 108 | # dotenv environment variables file(s) 109 | .env 110 | .env.* 111 | 112 | #Build generated 113 | dist/ 114 | build/ 115 | 116 | 117 | ### SublimeText ### 118 | # cache files for sublime text 119 | *.tmlanguage.cache 120 | *.tmPreferences.cache 121 | *.stTheme.cache 122 | 123 | # workspace files are user-specific 124 | *.sublime-workspace 125 | 126 | # project files should be checked into the repository, unless a significant 127 | # proportion of contributors will probably not be using SublimeText 128 | # *.sublime-project 129 | 130 | 131 | ### VisualStudioCode ### 132 | .vscode/* 133 | !.vscode/settings.json 134 | !.vscode/tasks.json 135 | !.vscode/launch.json 136 | !.vscode/extensions.json 137 | 138 | ### WebStorm/IntelliJ ### 139 | /.idea 140 | modules.xml 141 | *.ipr 142 | 143 | 144 | ### System Files ### 145 | .DS_Store 146 | 147 | # Windows thumbnail cache files 148 | Thumbs.db 149 | ehthumbs.db 150 | ehthumbs_vista.db 151 | 152 | # Folder config file 153 | Desktop.ini 154 | 155 | # Recycle Bin used on file shares 156 | $RECYCLE.BIN/ 157 | 158 | # Thumbnails 159 | ._* 160 | 161 | # Files that might appear in the root of a volume 162 | .DocumentRevisions-V100 163 | .fseventsd 164 | .Spotlight-V100 165 | .TemporaryItems 166 | .Trashes 167 | .VolumeIcon.icns 168 | .com.apple.timemachine.donotpresent 169 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | ./**/__tests__/*.test.js 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - ~/.npm 5 | notifications: 6 | email: false 7 | node_js: 8 | - '10' 9 | - '11' 10 | - '12' 11 | before_install: yarn global add greenkeeper-lockfile@1 12 | before_script: greenkeeper-lockfile-update 13 | after_script: greenkeeper-lockfile-upload 14 | install: yarn install --ignore-engines 15 | after_success: 16 | - npm run travis-deploy-once "npm run semantic-release" 17 | branches: 18 | except: 19 | - /^v\d+\.\d+\.\d+$/ 20 | env: 21 | - GK_LOCK_YARN_OPTS: "--ignore-engines" 22 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-bxd-oss": { 3 | "promptValues": { 4 | "username": "blackxored", 5 | "teamEmail": "adrian@adrianperez.org" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of 9 | experience, nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team leader at [`adrian@adrianperez.org`]. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an 62 | incident. Further details of specific enforcement policies may be posted 63 | separately. 64 | 65 | Project maintainers who do not follow or enforce the Code of Conduct in good 66 | faith may face temporary or permanent repercussions as determined by other 67 | members of the project's leadership. 68 | 69 | ## Attribution 70 | 71 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 72 | version 1.4, available at 73 | https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 74 | 75 | [homepage]: https://www.contributor-covenant.org 76 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for being willing to contribute! 4 | 5 | **Working on your first Pull Request?** You can learn how from this _free_ 6 | series [How to Contribute to an Open Source Project on GitHub][egghead] 7 | 8 | ## Project setup 9 | 10 | 1. Fork and clone the repo 11 | 2. `$ yarn` to install dependencies 12 | 3. `$ yarn test` to validate you've got it working 13 | 4. Create a branch for your PR 14 | 15 | > Tip: Keep your `master` branch pointing at the original repository and make 16 | > pull requests from branches on your fork. To do this, run: 17 | > 18 | > ``` 19 | > git remote add upstream https://github.com/blackxored/apollo-link-logger.git 20 | > git fetch upstream 21 | > git branch --set-upstream-to=upstream/master master 22 | > ``` 23 | > 24 | > This will add the original repository as a "remote" called "upstream," Then 25 | > fetch the git information from that remote, then set your local `master` 26 | > branch to use the upstream master branch whenever you run `git pull`. Then you 27 | > can make all of your pull request branches based on this `master` branch. 28 | > Whenever you want to update your version of `master`, do a regular `git pull`. 29 | 30 | ## Add yourself as a contributor 31 | 32 | This project follows the [all contributors][all-contributors] specification. To 33 | add yourself to the table of contributors on the README.md, please use the 34 | automated script as part of your PR: 35 | 36 | ```console 37 | yarn run contributors:add 38 | ``` 39 | 40 | Follow the prompt and commit `.all-contributorsrc` and `README.md` in the PR. If 41 | you've already added yourself to the list and are making a new type of 42 | contribution, you can run it again and select the added contribution type. 43 | 44 | ## Committing and Pushing changes 45 | 46 | This project uses [`semantic-release`][semantic-release] to do automatic 47 | releases and generate a changelog based on the commit history. So we follow [a 48 | convention][convention] for commit messages. You don't have to follow this 49 | convention if you don't like to, although we've provided hooks to make it easier 50 | for you to adhere to them if you so choose. Just know that when we merge your 51 | commit, we'll probably use "Squash and Merge" so we can change the commit 52 | message :) 53 | 54 | Please make sure to run the tests before you commit your changes. You can run 55 | `npm test -- -u` which will update any snapshots that need updating. Make sure 56 | to include those changes (if they exist) in your commit. 57 | 58 | ## Help needed 59 | 60 | Please checkout the [the open issues][issues] 61 | 62 | Also, please watch the repo and respond to questions/bug reports/feature 63 | requests! Thanks! 64 | 65 | [egghead]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github 66 | [semantic-release]: https://npmjs.com/package/semantic-release 67 | [convention]: https://github.com/conventional-changelog/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md 68 | [all-contributors]: https://github.com/kentcdodds/all-contributors 69 | [issues]: https://github.com/blackxored/apollo-link-logger/issues 70 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2017-present Adrian Perez 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # apollo-link-logger 2 | 3 | > A logger for Apollo Link that resembles redux-logger 4 | 5 | [![Semantically Released][semantic-release-badge]][semantic-release] 6 | [![Build Status][build-badge]][build] 7 | [![Code Coverage][coverage-badge]][coverage] 8 | [![version][version-badge]][package] 9 | [![downloads][downloads-badge]][npmtrends] 10 | [![Styled with Prettier][prettier-badge]][prettier] 11 | [![AirBnB style guide][airbnb-style-badge]][airbnb-style] 12 | 13 | [![MIT License][license-badge]][LICENSE] 14 | [![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors) 15 | [![PRs Welcome][prs-badge]][prs] 16 | [![Commitizen friendly][commitizen-badge]][commitizen] 17 | [![Code of Conduct][coc-badge]][coc] 18 | 19 | [![Watch on GitHub][github-watch-badge]][github-watch] 20 | [![Star on GitHub][github-star-badge]][github-star] 21 | [![Tweet][twitter-badge]][twitter] 22 | 23 | Logger for Apollo Link that uses a similar format to redux-logger. Includes performance information. 24 | 25 | ## Installing / Getting Started 26 | 27 | These instructions will get you a copy of the project up and running on your 28 | local machine for development and testing purposes. 29 | 30 | A quick introduction of the minimal setup you need to get a hello world up & running. 31 | 32 | ```shell 33 | npm install apollo-link-logger 34 | ``` 35 | 36 | ### Prerequisites 37 | 38 | * Apollo Link. 39 | 40 | ### Usage 41 | 42 | ```javascript 43 | import apolloLogger from 'apollo-link-logger'; 44 | 45 | // ... 46 | ApolloLink.from([ 47 | apolloLogger, 48 | // ... 49 | ]); 50 | ``` 51 | 52 | ## Screenshots 53 | 54 | ### Query (expanded): 55 | 56 | ![Query Expanded](https://github.com/blackxored/apollo-link-logger/blob/master/docs/example-output.png) 57 | 58 | ### Mutation (expanded): 59 | 60 | ![Mutation Expanded](https://github.com/blackxored/apollo-link-logger/blob/master/docs/example-output-mutation.png) 61 | 62 | ### Within other logging statements: 63 | 64 | ![Full](https://github.com/blackxored/apollo-link-logger/blob/master/docs/example-output-full.png) 65 | 66 | ## Usage with React Native and other restricted environments 67 | 68 | We include a polyfilled version of `console.groupCollapsed` and `console.groupEnd` that 69 | invokes `console.log` with slightly different prefix to separate output. 70 | 71 | ## Developing 72 | 73 | ### Setting up Dev 74 | 75 | Here's a brief intro about what a developer must do in order to start 76 | developing the project further: 77 | 78 | ```shell 79 | git clone https://github.com/blackxored/apollo-link-logger 80 | cd apollo-link-logger 81 | yarn 82 | ``` 83 | 84 | ## Versioning 85 | 86 | We use [SemVer][semver] for versioning. In addition, it's automatic via 87 | [semantic-release][semantic-release], and our [commit convention][commit-convention]. 88 | 89 | For the versions available, see the [Releases][releases] on this repository. 90 | 91 | ## Style guide 92 | 93 | We base our code style on [AirBnB's style guide][airbnb-style] and we check with 94 | [ESLint][eslint] and automatically format our code with [Prettier][prettier]. 95 | 96 | ## License 97 | 98 | This project is licensed under the MIT License - see the 99 | [license] file for details. 100 | 101 | ## Contributing 102 | 103 | If you're interested in contributing to this project in any form, please read 104 | our [Contribution Guidelines][contributing]. 105 | 106 | ### Code of Conduct 107 | 108 | We've adopted a Code of Conduct that we expect project participants to adhere to. 109 | Please read the [full text][coc] so that you can understand what actions 110 | will and will not be tolerated. 111 | 112 | ### Contributors 113 | 114 | Thanks goes to these people ([emoji key][emojis]): 115 | 116 | 117 | 118 | | [
Adrian Perez](https://adrianperez.codes)
[💻](https://github.com/blackxored/apollo-link-logger/commits?author=blackxored "Code") [📖](https://github.com/blackxored/apollo-link-logger/commits?author=blackxored "Documentation") [🚇](#infra-blackxored "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/blackxored/apollo-link-logger/commits?author=blackxored "Tests") | [
Adam Savitzky](https://github.com/adambom)
[💻](https://github.com/blackxored/apollo-link-logger/commits?author=adambom "Code") | [
Ifeanyi Oraelosi](https://github.com/gnerkus)
[💻](https://github.com/blackxored/apollo-link-logger/commits?author=gnerkus "Code") | [
Romario](https://github.com/romarioraffington)
[🐛](https://github.com/blackxored/apollo-link-logger/issues?q=author%3Aromarioraffington "Bug reports") [🤔](#ideas-romarioraffington "Ideas, Planning, & Feedback") | [
Yuriy Kornienko](http://www.dinamchiki.ru)
[💻](https://github.com/blackxored/apollo-link-logger/commits?author=Horoshiy "Code") | [
Dmitry Shvedov](https://github.com/dmt0)
[💻](https://github.com/blackxored/apollo-link-logger/commits?author=dmt0 "Code") | 119 | | :---: | :---: | :---: | :---: | :---: | :---: | 120 | 121 | 122 | This project follows the [all-contributors][all-contributors] specification. 123 | Contributions of any kind welcome! 124 | 125 | 126 | [npm]: https://www.npmjs.com/ 127 | [node]: https://nodejs.org 128 | [build-badge]: https://img.shields.io/travis/blackxored/apollo-link-logger.svg?style=flat-square 129 | [build]: https://travis-ci.org/blackxored/apollo-link-logger 130 | [coverage-badge]: https://img.shields.io/codecov/c/github/blackxored/apollo-link-logger.svg?style=flat-square 131 | [coverage]: https://codecov.io/github/blackxored/apollo-link-logger 132 | [version-badge]: https://img.shields.io/npm/v/apollo-link-logger.svg?style=flat-square 133 | [package]: https://www.npmjs.com/package/apollo-link-logger 134 | [downloads-badge]: https://img.shields.io/npm/dm/apollo-link-logger.svg?style=flat-square 135 | [npmtrends]: http://www.npmtrends.com/apollo-link-logger 136 | [license-badge]: https://img.shields.io/npm/l/apollo-link-logger.svg?style=flat-square 137 | [license]: https://github.com/blackxored/apollo-link-logger/blob/master/LICENSE.md 138 | [semantic-release]: https://github.com/semantic-release/semantic-release 139 | [semantic-release-badge]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square 140 | [commitizen-badge]: https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square 141 | [commitizen]: http://commitizen.github.io/cz-cli/ 142 | [prettier-badge]: https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square 143 | [prettier]: https://github.com/prettier/prettier 144 | [airbnb-style-badge]: https://img.shields.io/badge/code%20style-airbnb-green.svg?style=flat-square 145 | [airbnb-style]: https://github.com/airbnb/javascript 146 | [eslint]: http://eslint.org 147 | [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square 148 | [prs]: http://makeapullrequest.com 149 | [donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square 150 | [contributing]: https://github.com/blackxored/apollo-link-logger/blob/master/CONTRIBUTING.md 151 | [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square 152 | [coc]: https://github.com/blackxored/apollo-link-logger/blob/master/CODE_OF_CONDUCT.md 153 | [github-watch-badge]: https://img.shields.io/github/watchers/blackxored/apollo-link-logger.svg?style=social 154 | [github-watch]: https://github.com/blackxored/apollo-link-logger/watchers 155 | [github-star-badge]: https://img.shields.io/github/stars/blackxored/apollo-link-logger.svg?style=social 156 | [github-star]: https://github.com/blackxored/apollo-link-logger/stargazers 157 | [twitter]: https://twitter.com/intent/tweet?text=Check%20out%20apollo-link-logger%20by%20%40blackxored%20https%3A%2F%2Fgithub.com%2Fblackxored%2Fapollo-link-logger%20%F0%9F%91%8D 158 | [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/blackxored/apollo-link-logger.svg?style=social 159 | [emojis]: https://github.com/kentcdodds/all-contributors#emoji-key 160 | [all-contributors]: https://github.com/kentcdodds/all-contributors 161 | [semver]: http://semver.org/ 162 | [releases]: https://github.com/blackxored/apollo-link-logger/releases 163 | [commit-convention]: https://www.npmjs.com/package/@commitlint/config-conventional 164 | 165 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/example-output-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackxored/apollo-link-logger/933156ae67088fc24b472a4967efd9042bd5de0f/docs/example-output-full.png -------------------------------------------------------------------------------- /docs/example-output-mutation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackxored/apollo-link-logger/933156ae67088fc24b472a4967efd9042bd5de0f/docs/example-output-mutation.png -------------------------------------------------------------------------------- /docs/example-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackxored/apollo-link-logger/933156ae67088fc24b472a4967efd9042bd5de0f/docs/example-output.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "apollo-link-logger", 3 | "version": "0.0.0-development", 4 | "description": "Logger for Apollo Link that uses a similar format to redux-logger. Includes performance information.", 5 | "author": "Adrian Perez adrian@adrianperez.org", 6 | "license": "MIT", 7 | "module": "es/index.js", 8 | "main": "lib/index.js", 9 | "engines": { 10 | "node": ">= 10", 11 | "npm": "> 3" 12 | }, 13 | "files": [ 14 | "es", 15 | "dist", 16 | "lib" 17 | ], 18 | "scripts": { 19 | "start": "webpack", 20 | "commit": "commit", 21 | "precommit": "lint-staged", 22 | "commitmsg": "commitlint -e $GIT_PARAMS", 23 | "clean": "rimraf es/* src/* dist/* coverage/*", 24 | "lint": "eslint src", 25 | "add-contributor": "all-contributors add", 26 | "generate-contributors": "all-contributors generate", 27 | "build:es": "cross-env BABEL_ENV=es babel src -q -d es", 28 | "build:cjs": "cross-env BABEL_ENV=cjs babel src -q -d lib", 29 | "build": "npm run build:es && npm run build:cjs", 30 | "test": "jest", 31 | "prettier:js": "prettier --write --trailing-comma all --tab-width 2 --single-quote --print-width 80 \"src/**/*.js\" \"!**/dist/**\"", 32 | "prepare": "npm run build", 33 | "semantic-release": "semantic-release", 34 | "travis-deploy-once": "travis-deploy-once" 35 | }, 36 | "lint-staged": { 37 | "*.js": [ 38 | "prettier --write --trailing-comma all --tab-width 2 --single-quote --print-width 80", 39 | "git add", 40 | "jest --bail --findRelatedTests" 41 | ] 42 | }, 43 | "config": { 44 | "commitzen": { 45 | "path": "@commitlint/prompt" 46 | } 47 | }, 48 | "jest": { 49 | "testMatch": [ 50 | "/src/**/*.test.js" 51 | ], 52 | "collectCoverageFrom": [ 53 | "src/**/*.js", 54 | "!**/node_modules/**", 55 | "!**/vendor/**" 56 | ], 57 | "testURL": "http://localhost" 58 | }, 59 | "quokka": { 60 | "babel": true 61 | }, 62 | "devDependencies": { 63 | "@commitlint/cli": "^6.1.3", 64 | "@commitlint/config-conventional": "^7.0.0", 65 | "all-contributors-cli": "^5.3.0", 66 | "babel-cli": "^6.0.0", 67 | "babel-core": "^6.0.0", 68 | "babel-eslint": "^8.2.3", 69 | "babel-jest": "23.0.1", 70 | "babel-preset-env": "^1.6.0", 71 | "commitizen": "^2.9.6", 72 | "cross-env": "^5.1.4", 73 | "eslint": "^5.0.0", 74 | "eslint-config-airbnb-base": "^13.0.0", 75 | "eslint-config-prettier": "^2.4.0", 76 | "eslint-plugin-fp": "^2.3.0", 77 | "eslint-plugin-import": "^2.7.0", 78 | "eslint-plugin-jest": "^21.0.0", 79 | "eslint-plugin-prettier": "^2.2.0", 80 | "husky": "^0.14.3", 81 | "jest": "^22.4.3", 82 | "lint-staged": "^7.0.4", 83 | "prettier": "^1.8.1", 84 | "rimraf": "~2.6.2", 85 | "semantic-release": "^15.9.3", 86 | "travis-deploy-once": "^5.0.1" 87 | }, 88 | "peerDependencies": { 89 | "@apollo/client": "^3.0.0" 90 | }, 91 | "repository": { 92 | "type": "git", 93 | "url": "https://github.com/blackxored/apollo-link-logger.git" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/formatMessage.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`formatMessage does not include performance information for subscriptions 1`] = ` 4 | Array [ 5 | "%c apollo %csubscription %cMessagesSubscription", 6 | "color: gray; font-weight: lighter", 7 | "color: red;", 8 | "color: inherit;", 9 | ] 10 | `; 11 | 12 | exports[`formatMessage returns a list of strings suitable for console logging 1`] = ` 13 | Array [ 14 | "%c apollo %cquery %cFormatMessageQuery %c(in 1000 ms)", 15 | "color: gray; font-weight: lighter", 16 | "color: #03A9F4;", 17 | "color: inherit;", 18 | "color: gray; font-weight: lighter;", 19 | ] 20 | `; 21 | 22 | exports[`formatMessage returns a list of strings suitable for console logging 2`] = ` 23 | Array [ 24 | "%c apollo %cmutation %cFormatMessageMutation %c(in 500 ms)", 25 | "color: gray; font-weight: lighter", 26 | "color: red;", 27 | "color: inherit;", 28 | "color: gray; font-weight: lighter;", 29 | ] 30 | `; 31 | -------------------------------------------------------------------------------- /src/__tests__/formatMessage.test.js: -------------------------------------------------------------------------------- 1 | import formatMessage from '../formatMessage'; 2 | 3 | describe('formatMessage', () => { 4 | it('returns a list of strings suitable for console logging', () => { 5 | expect( 6 | formatMessage('query', { operationName: 'FormatMessageQuery' }, 1000), 7 | ).toMatchSnapshot(); 8 | 9 | expect( 10 | formatMessage( 11 | 'mutation', 12 | { operationName: 'FormatMessageMutation' }, 13 | 500, 14 | ), 15 | ).toMatchSnapshot(); 16 | }); 17 | 18 | it('does not include performance information for subscriptions', () => { 19 | expect( 20 | formatMessage( 21 | 'subscription', 22 | { operationName: 'MessagesSubscription' }, 23 | 500, 24 | ), 25 | ).toMatchSnapshot(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/__tests__/logging.test.js: -------------------------------------------------------------------------------- 1 | import logging from '../logging'; 2 | 3 | const logSpy = jest.spyOn(global.console, 'log'); 4 | 5 | describe('logging', () => { 6 | describe('console.groupCollapsed', () => { 7 | it('should not use custom `groupCollapsed` if `console.groupCollapsed` exists', () => { 8 | logging.groupCollapsed(); 9 | expect(logSpy).not.toHaveBeenCalled(); 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/formatMessage.js: -------------------------------------------------------------------------------- 1 | const formatMessage = (operationType, operation, ellapsed) => { 2 | const headerCss = [ 3 | 'color: gray; font-weight: lighter', // title 4 | `color: ${operationType === 'query' ? '#03A9F4' : 'red'};`, // operationType 5 | 'color: inherit;', // operationName 6 | ]; 7 | 8 | const parts = [ 9 | '%c apollo', 10 | `%c${operationType}`, 11 | `%c${operation.operationName}`, 12 | ]; 13 | 14 | if (operationType !== 'subscription') { 15 | parts.push(`%c(in ${ellapsed} ms)`); 16 | headerCss.push('color: gray; font-weight: lighter;'); // time 17 | } 18 | 19 | return [parts.join(' '), ...headerCss]; 20 | }; 21 | 22 | export default formatMessage; 23 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved,import/extensions */ 2 | import { ApolloLink } from '@apollo/client/core'; 3 | import formatMessage from './formatMessage'; 4 | import logging from './logging'; 5 | 6 | const loggerLink = new ApolloLink((operation, forward) => { 7 | const startTime = new Date().getTime(); 8 | 9 | return forward(operation).map(result => { 10 | const operationType = operation.query.definitions[0].operation; 11 | const ellapsed = new Date().getTime() - startTime; 12 | 13 | const group = formatMessage(operationType, operation, ellapsed); 14 | 15 | logging.groupCollapsed(...group); 16 | 17 | logging.log('INIT', operation); 18 | logging.log('RESULT', result); 19 | 20 | logging.groupEnd(...group); 21 | return result; 22 | }); 23 | }); 24 | 25 | export default loggerLink; 26 | -------------------------------------------------------------------------------- /src/logging.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const bindToConsole = (consoleMethod, polyfill) => { 3 | return consoleMethod ? consoleMethod.bind(console) : polyfill; 4 | }; 5 | 6 | const logging = (() => { 7 | let prefix = ''; 8 | 9 | const consoleLog = (...args) => { 10 | console.log(prefix, ...args); 11 | }; 12 | 13 | const consoleError = (...args) => { 14 | console.error(prefix, ...args); 15 | }; 16 | 17 | const consoleGroup = (...args) => { 18 | consoleLog(...args); 19 | prefix += '> '; 20 | }; 21 | 22 | const consoleGroupEnd = () => { 23 | prefix = prefix.slice(0, -2); 24 | }; 25 | 26 | return { 27 | log: consoleLog, 28 | error: consoleError, 29 | group: bindToConsole(console.group, consoleGroup), 30 | groupCollapsed: bindToConsole(console.groupCollapsed, consoleGroup), 31 | groupEnd: bindToConsole(console.groupEnd, consoleGroupEnd), 32 | }; 33 | })(); 34 | 35 | export default logging; 36 | -------------------------------------------------------------------------------- /wallaby.config.js: -------------------------------------------------------------------------------- 1 | process.env.BABEL_ENV = 'test'; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = function(wallaby) { 6 | return { 7 | files: [ 8 | 'src/**/*.js', 9 | '**/*.json', 10 | '**/*.snap', 11 | 'package.json', 12 | '!**/__tests__/*.js', 13 | '!**/*.test.js', 14 | ], 15 | tests: ['**/__tests__/*.js', '**/*.test.js', '!**/node_modules/**'], 16 | env: { 17 | type: 'node', 18 | runner: 'node', 19 | }, 20 | 21 | compilers: { 22 | '**/*.js': wallaby.compilers.babel(), 23 | }, 24 | 25 | testFramework: 'jest', 26 | 27 | setup: wallaby => { 28 | wallaby.testFramework.configure(require('./package.json').jest); 29 | }, 30 | }; 31 | }; 32 | --------------------------------------------------------------------------------