{"id":19196982,"url":"https://github.com/jitesoft/yolog","last_synced_at":"2025-08-02T20:32:58.973Z","repository":{"id":34694695,"uuid":"182048279","full_name":"jitesoft/yolog","owner":"jitesoft","description":"Environment agnostic pluggable JavaScript logger.","archived":false,"fork":false,"pushed_at":"2025-03-15T18:24:32.000Z","size":1997,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-17T19:44:37.520Z","etag":null,"topics":["async","hacktoberfest","javascript","js","logger","logging","logging-library","nodejs","web"],"latest_commit_sha":null,"homepage":"https://yolog.js.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jitesoft.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-04-18T08:29:39.000Z","updated_at":"2023-10-24T19:40:48.000Z","dependencies_parsed_at":"2025-04-20T10:52:12.399Z","dependency_job_id":null,"html_url":"https://github.com/jitesoft/yolog","commit_stats":{"total_commits":238,"total_committers":7,"mean_commits":34.0,"dds":0.2184873949579832,"last_synced_commit":"24229e4bbd2bdacf3b7bbee8bd1b708e561641cf"},"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"purl":"pkg:github/jitesoft/yolog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitesoft%2Fyolog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitesoft%2Fyolog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitesoft%2Fyolog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitesoft%2Fyolog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jitesoft","download_url":"https://codeload.github.com/jitesoft/yolog/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jitesoft%2Fyolog/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268448362,"owners_count":24252019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","hacktoberfest","javascript","js","logger","logging","logging-library","nodejs","web"],"created_at":"2024-11-09T12:15:03.947Z","updated_at":"2025-08-02T20:32:58.899Z","avatar_url":"https://github.com/jitesoft.png","language":"JavaScript","funding_links":["https://opencollective.com/jitesoft-open-source"],"categories":[],"sub_categories":[],"readme":"# Yolog\r\n\r\n[![npm (scoped)](https://img.shields.io/npm/v/@jitesoft/yolog)](https://www.npmjs.com/package/@jitesoft/yolog)\r\n[![Known Vulnerabilities](https://dev.snyk.io/test/npm/@jitesoft/yolog/badge.svg)](https://dev.snyk.io/test/npm/@jitesoft/yolog)\r\n[![pipeline status](https://gitlab.com/jitesoft/open-source/javascript/yolog/badges/master/pipeline.svg)](https://gitlab.com/jitesoft/open-source/javascript/yolog/commits/master)\r\n[![coverage report](https://gitlab.com/jitesoft/open-source/javascript/yolog/badges/master/coverage.svg)](https://gitlab.com/jitesoft/open-source/javascript/yolog/commits/master)\r\n[![npm](https://img.shields.io/npm/dt/@jitesoft/yolog)](https://www.npmjs.com/package/@jitesoft/yolog)\r\n[![Back project](https://img.shields.io/badge/Open%20Collective-Tip%20the%20devs!-blue.svg)](https://opencollective.com/jitesoft-open-source)\r\n[![DeepScan grade](https://deepscan.io/api/teams/5978/projects/7842/branches/85543/badge/grade.svg)](https://deepscan.io/dashboard#view=project\u0026tid=5978\u0026pid=7842\u0026bid=85543)\r\n\r\nSimple pluggable async logger for node and browser alike.  \r\n\r\nEver wanted a logger with a simple API that you could easily write a minimal plugin for? A logger which would work in both\r\nyour browser and in your node environment?\r\n\r\nWell, then Yolog might be something for you.\r\n\r\n## Installation\r\n\r\nSimply use your favorite package manager that can pull packages from the npm repository!\r\n\r\n```bash\r\nnpm i --save @jitesoft/yolog\r\nyarn add @jitesoft/yolog\r\nsomeothermanager --save-package-to-json-file @jitesoft/yolog\r\n```\r\n\r\n## Usage\r\n\r\nYolog have three base files which you can make use of when it is compiled:\r\n\r\n* index.js\r\n* node.js\r\n* browser.js\r\n\r\nThe `index.js` is only the API (contains the `Yolog` and `YologPlugin` interfaces and such) and could possibly be useful\r\nif you wish to create your own plugin but don't care about the other stuff.\r\n\r\nThe `browser.js` file contains the same code as the `index.js` and an extra `ConsolePlugin` which is pre-initialized if \r\nusing the `default` value from the package.\r\n\r\nThe `node.js` file contains the same code as the `index.js` and an extra `ConsolePlugin` which is pre-initialized if \r\nusing the `default` value from the package.\r\n\r\nWhen including the script, there will be a global `Yolog` object containing `logger` (which is an instance of yolog\r\nready to use with the console plugin), `Yolog` which is the logger itself, if you wish to create a new instance yourself.\r\n`ConsolePlugin`, which is a plugin that produces output to the console and the `YologPlugin` class (which is used to create new plugins)\r\n\r\nSimply put:\r\n\r\n```html\r\n\u003cscript src=\"yolog/browser.js\"\u003e\u003c/script\u003e\r\n\u003cscript\u003e\r\n    const logger = Yolog.logger;\r\n    logger.debug('Weee!');\r\n\u003c/script\u003e\r\n```\r\n\r\n```javascript\r\nimport { logger } from '@jitesoft/yolog';\r\nimport { logger } from '@jitesoft/yolog/browser'; // Browser specific\r\nimport { logger } from '@jitesoft/yolog/node';    // Node specific\r\nlogger.debug('Weee!')\r\n```\r\n\r\n```javascript\r\nconst logger = require('@jitesoft/yolog').logger;\r\nconst logger = require('@jitesoft/yolog/browser').logger; // Browser specific\r\nconst logger = require('@jitesoft/yolog/node').logger;    // Node specific\r\nlogger.debug('Weee!')\r\n```\r\n\r\n### Log tags\r\n\r\nThe Yolog class have a set of pre-defined tags which are used to output different type of logs with. It is possible to turn a \r\ntag on and off via code, both in a plugin or in the Yolog instance itself.  \r\nThe pre-defined tags are (name and default value):\r\n\r\n```json\r\n{\r\n  \"debug\": { \"enabled\":  true, \"error\": true },\r\n  \"info\": { \"enabled\":  true, \"error\": true },\r\n  \"warning\": { \"enabled\":  true, \"error\": true },\r\n  \"error\": { \"enabled\":  true, \"error\": true },\r\n  \"critical\": { \"enabled\":  true, \"error\": true },\r\n  \"alert\": { \"enabled\":  true, \"error\": true },\r\n  \"emergency\": { \"enabled\":  true, \"error\": true }\r\n}\r\n```\r\n\r\nWhen using the constructor, Yolog will accept the key-value pairs as `string : bool`, \r\ndefaulting `error` to true and setting `enabled` to the boolean value.\r\n\r\nThe `error` key is used to allow yolog to know if it should pass the first error it encounters in the argument list as the error parameter when calling\r\nits plugins. This allows the user to pass errors which could be printed out with a nice looking stack trace in the plugins.\r\n\r\n_Yolog uses the [@jitesoft/sprinf](https://www.npmjs.com/package/@jitesoft/sprintf) package to enable message and argument \r\nbuilding. This due to not wanting to use a node-specific method as `util.format` when building for cross env support.\r\nBe sure to check out supported parameter types if you wish to do some more advanced parameterization!_\r\n\r\nTurning a tag on or off is done by calling the `set(tag, state = null)` method on either the Yolog instance (if you wish that no output\r\nshould be done for that tag at all) or by the `set(tag, state = null)` method of the plugin that you wish to specifically not get logs for\r\nthe tag from.\r\n\r\nIf no state is passed with the `set` method, it will toggle the state.\r\n\r\nIf you wish to add a new tag to yolog and a plugin, the `set` method can also be used. Just pass the tag that you wish\r\nto create as the tag, and it will be set to the value that you pass as second argument.\r\n\r\nYou can also check the state of a given tag by using the `get(tag)` method on either the Yolog instance or the plugin.\r\n\r\n### As event handler\r\n\r\nThe Yolog instance have a built-in event handler which can be used to listen to given tags instead of logging them\r\nwith a plugin.\r\n  \r\n_The events will not use the same priority queue as the normal callbacks, and will be async emitted, so do not\r\nbuild your logic around that expectation.  \r\nEach event should either return nothing or boolean value. If return value is `false` it will not bubble to the next\r\nqueued priority batch, else they will run in batches depending on priority.  \r\nThis also means that the callback could be async without the logger having any issues with it._\r\n\r\nThere are `on`, `off` and `once` methods available and they work basically as any normal event handler should.\r\n\r\nThe events emitted looks like the following:\r\n\r\n```js\r\nconst event = {\r\n  data: {\r\n    message: \"message\" /* Message passed to the logger. */,\r\n    arguments: [ /* argument list passed to the logger. */ ],\r\n    timestamp: 123 /* Unix-timestamp (ms) when the logger was invoked. */, \r\n    tag: \"tag\" /* The tag that was invoked. */,\r\n    errorObject: new Error() /* An error object created in the yolog #log method. */\r\n  }\r\n};\r\n\r\n// That is...\r\nconsole.log(event.data.message); // Will give you the message property.\r\n```\r\n\r\n_The package that Yolog uses can be found [here (@jitesoft/events)](https://www.npmjs.com/package/@jitesoft/events) if you wish to \r\ncheck out more specific details._\r\n\r\n## Plugins\r\n\r\nPlugins are minimal classes which can be used to extend the logger to use other type of outputs!   \r\nWhen writing a new plugin, the `Plugin` class in the base lib is used as a base class (if using es6 inheritance),\r\nthe only method that really have to be implemented is the `log` method, the base class takes care of the rest!\r\n\r\n```js\r\nimport { YologPlugin } from '@jitesoft/yolog';\r\n\r\nexport default class MyPlugin extends YologPlugin {  \r\n  /**\r\n   * Method called when a log message is intercepted and the plugin is listening to the given tag.\r\n   *\r\n   * @param {String} tag       Tag which was used when logging the message.\r\n   * @param {Number} timestamp Timestamp (in ms) when the log was intercepted by the Yolog instance.\r\n   * @param {String} message   Message that is passed to the plugin.\r\n   * @param {Error} error      Error generated in the logger to be possible to use for call stack or for other reasons.\r\n   * @return Promise\u003cvoid\u003e\r\n   */\r\n  async log (tag, timestamp, message, error) {\r\n    // Do your magic here! (return a promise or use the async/await keywords!)\r\n    return await something.something(message);\r\n  }  \r\n}\r\n```\r\n\r\nPlugin interface:\r\n\r\n```typescript\r\ninterface YologPluginInterface {\r\n  log (tag: string, timestamp: number, message: string, error): Promise\u003cvoid\u003e; /*Abstract, only method required to be implemented. */\r\n  set (tag: string, state: boolean|null): void;\r\n  get (tag: string): boolean|undefined;\r\n  /*get*/ active (): Array\u003cstring\u003e;\r\n  enableError(...tag: Array\u003cstring\u003e): this;\r\n  disableError(...tag: Array\u003cstring\u003e): this;\r\n}\r\n```\r\n\r\nTo add a new plugin to the Yolog instance, call the `addPlugin(plugin)` method, removal can be done with `removePlugin(plugin)`.\r\n\r\n### Official plugins\r\n\r\nThe following list are plugins maintained and supported by Jitesoft.\r\n\r\n* [`@jitesoft/yolog-file-plugin`](https://www.npmjs.com/package/@jitesoft/yolog-file-plugin)\r\n* [`@jitesoft/yolog-sentry-plugin`](https://www.npmjs.com/package/@jitesoft/yolog-sentry-plugin)\r\n* [`@jitesoft/yolog-slack-plugin`](https://www.npmjs.com/package/@jitesoft/yolog-slack-plugin)\r\n* [`@jitesoft/yolog-email-plugin`](https://www.npmjs.com/package/@jitesoft/yolog-email-plugin)\r\n* [`@jitesoft/yolog-json-plugin`](https://www.npmjs.com/package/@jitesoft/yolog-json-plugin)\r\n\r\n_More are under development._\r\n\r\n### Community developed plugins\r\n\r\n_Create a pull request for the readme file to include your plugin here (after a general audit)!_\r\n\r\n**Observe:**  \r\nCommunity developed plugins listed here are not under the control of Jitesoft and any damages they may or may not cause\r\nis nothing that Jitesoft can be held liable for. As with everything, you should always audit the code you use before\r\nusing it in production!\r\n\r\n## More docs!\r\n\r\n### Yolog\r\n\r\nThe Yolog base API is quite simple, there are a few methods to customize the logger, while most of the configurations should\r\nbe done in plugins.  \r\n\r\n**Events**\r\n\r\nAs mentioned above, the Yolog instance can be used as an event handler, the methods connected to this features\r\nare the following:\r\n\r\n```typescript\r\ninterface Yolog {\r\n  on(tag: string, handler: Function, priority: number): number;\r\n  off(tag: string, handler: number | Function): boolean;\r\n  once(tag: string, handler: Function, priority?: number): number;\r\n}\r\n```\r\n\r\nThe methods pretty much speak for themselves. On and Once both returns a number, the number\r\nis the handle of the specific handler function. If the handler is to be removed, the handle \r\nor the function itself can be passed to yolog through the `off` method, removing it from the list of handlers.\r\n\r\nPriority is a batch priority, that is, if multiple handlers have the same priority, they will be called\r\nasync at the same time. If either of them returns false, the event will not bubble to the next batch.  \r\nThere is currently no built in way to not allow other handlers with the same priority to stop each other.\r\n\r\nEvents start their emit before the plugins are invoked, but yolog will not wait for them to finnish before starting\r\nto run the plugins. That way, you can not be sure that the plugins are invoked before the plugins, or the other way around.\r\n\r\n**Plugins**\r\n\r\nAdding and removing plugins is if possible more easy than using the events. The following methods are\r\nused for this:\r\n\r\n```typescript\r\ninterface Yolog {\r\n  addPlugin(plugin: YologPlugin): Yolog;\r\n  removePlugin(plugin: YologPlugin): Yolog;\r\n  readonly plugins: YologPlugin[];\r\n}\r\n```\r\n\r\nPlugins are all called in batch when a log command is done, they have no priority over each other and \r\nthe promise of the log method called will resolve when all are done.\r\n\r\nThe getter `plugins` will return all the plugins that are loaded in the instance.\r\n\r\n**Tags**\r\n\r\nTags is quite an important thing in yolog (and most logging...), there are a few pre-defined tags and methods\r\nthat are used to invoke those. The predefined tags are:\r\n\r\n```javascript\r\nconst tags = [\r\n  'debug',\r\n  'info',\r\n  'warning',\r\n  'error',\r\n  'critical',\r\n  'alert',\r\n  'emergency'\r\n];\r\n```\r\n\r\nYou may call a specific log tag via the `tagName(message: string, ...args): Promise\u003cvoid\u003e` methods, and if you wish to use\r\na custom tag, the `custom(tag: string, message: string, ...args): Promise\u003cvoid\u003e` method is available.  \r\nJust make sure that the tag exists in the logger by adding it in the `set` method!\r\n\r\n```typescript\r\ninterface Yolog {\r\n  set(tag: string, state?: boolean): Yolog;\r\n  get(tag: string): boolean;\r\n}\r\n```\r\n\r\nThe `set` method adds a tag or updates existing tags states, if it's set to `true` the tag will be available in yolog, if false, it will not\r\nthis way you can globally configure some tags to be on or off, if they are off, no event nor plugin will be invoked when the\r\nmethod is used.  \r\n`get` will return `true` or `false` depending on the state of the tag.\r\n\r\nAn example of where this can be a useful feature is when you wish to use environment specific tags:\r\n\r\n```javascript\r\nif (process.env.NODE_ENV === 'production') {\r\n  yolog.set('debug', false);\r\n  yolog.set('emergency', true);\r\n}\r\n```\r\n\r\n**Active and available**\r\n\r\nThere are two getters which can be used to get information about active and available tags, they both return\r\nlists of strings (the name of the tag) and are readonly:\r\n\r\n```typescript\r\ninterface Yolog {\r\n  readonly available: string[];\r\n  readonly active: string[];\r\n}\r\n```\r\n\r\nThe `available` getter will return the names of all tags that are set in yolog, this includes all custom tags you have created.\r\nThe `active` getter will return the names of all the tags that have state set to `true`.\r\n\r\n**Error**\r\n\r\n```typescript\r\ninterface Yolog {\r\n  enableError(...tag: Array\u003cstring\u003e): this;\r\n  disableError(...tag: Array\u003cstring\u003e): this;\r\n}\r\n```\r\n\r\nThe enable and disable error methods toggles the Yolog instance to create and send a error to the plugins (and events). \r\nEach plugin have their own controll of this too, while this is on a higher level. Tags passed will be toggled on or off, while\r\ncalling the functions without any argument will set errors to on or off for all the tags instead of a single tag.\r\n\r\n### Plugin\r\n\r\nJust as with the base API, the plugins have their own `tags` to turn off and on! This is to make it possible to have specific \r\nloggin types on for some tags while others are not. For example: you might want to output `debug` to console and \r\nyou wish to use an email plugin for the `critical` logs.  \r\nIf it was not possible to turn off most tags for the email plugin, you would receive a new email for each debug log made. \r\n\r\n**Active and available**\r\n\r\nThe `available` and `active` getters works as with the yolog class, the first returns all tags that are available in the plugin,\r\nthe `active` returns which are turned on.\r\n\r\n```typescript\r\ninterface YologPlugin {\r\n  readonly available: string[];\r\n  readonly active: string[];\r\n}\r\n```\r\n\r\n**Set and Get**\r\n\r\nThe set and get methods are - just as with the Yolog class - used to turn tags on and off and to check if a given tag is on or off.   \r\nCalling `set` will create a new tag if none exist, else update it.  \r\n\r\n**log**\r\n\r\nThe log method is the most important function of the Plugins. It is basically the only method that is required to be implemented to create a new plugin.\r\n`log` is an async method which takes a tag, timestamp, message and error. The message is the formatted message that Yolog passes\r\nto all plugins. The tag is the tag that was used when the log call was made. Timestamp is intended to be a Unix timestamp, which\r\ncan be used inside the plugin to format a nice time string for output.  \r\n\r\nSince v `2.6.0` a new `Error` argument is passed as the last argument of the log method. It can be used to output the callstack or similar\r\ninformation.  \r\n\r\nSince v `3.0.0` the `Error` argument depends on the input from the user due to the fact that stack traces in javascript is not working\r\nas one expect them to work.  \r\nIn future versions, if a better fix is found, this might change.\r\n\r\n**Error**\r\n\r\n```typescript\r\ninterface YologPlugin {\r\n  enableError(...tag: Array\u003cstring\u003e): this;\r\n  disableError(...tag: Array\u003cstring\u003e): this;\r\n}\r\n```\r\n\r\nThe methods allow the user to toggle each plugin errors on or off (that is, passing of the `Error` object through the log parameter at all). \r\nEach plugin is responsible to make sure the error object is not `null` before doing anything with its properties.\r\nCalling the functions without any argument will set errors to on or off for all the tags instead of a single tag.\r\n\r\n## Notes\r\n\r\nAny undocumented features are either in development or working as intended but not yet fully tested or documented. Use with care.\r\n\r\n### Versioning.\r\n\r\nYolog follows the [Semantic Versioning 2.0.0](http://semver.org/)  \r\nThis basically means that no API breaking changes will occur without a new major version release, features might be added\r\nduring a minor release and patches are only fixes.\r\n\r\n### Source code\r\n\r\nThe source can be found at [GitHub](https://github.com/jitesoft/yolog) and [GitLab](https://gitlab.com/jitesoft/open-source/javascript/yolog).\r\n\r\n### Tiny bit of history, cause why not?\r\n\r\nFirst release of `yolog` (back then under the name of `node-yolog`) was back in 2014, so quite a while ago... It was developed as a tiny in-house\r\nlogger - by Johannes at Talkative Labs - just to add colours to console logs. So nothing great nor special, although it did make the console look better!  \r\nAfter the initial release, the work on the package went stale for quite a while, like... years!  \r\nIt was finally picked up again in 2018 and rebuilt and re-branded as `yolog` under the `@jitesoft` org. The new version was not only for colourful\r\nconsole outputs, but rather a small plugin system for logging with a basic API which was easy to use and extend.  \r\n\r\n### Development \u0026 Contributions\r\n\r\nContributions in any form are very welcome!   \r\nIssues (bugs, feature requests, questions etc etc) can be posted in the [GitHub issue tracker](https://github.com/jitesoft/yolog/issues).  \r\nPull requests will be reviewed and should contain tests and follow the code style.\r\n\r\nIf you wish to contribute by monetary means, feel free to click the `sponsor` button on GitHub or head on over to our [OpenCollective](https://opencollective.com/jitesoft-open-source) page!\r\n\r\n#### License\r\n\r\n```text\r\nThe MIT License (MIT)\r\n\r\nCopyright (c) 2014 - 2020 Johannes Tegnér / Jitesoft\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjitesoft%2Fyolog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjitesoft%2Fyolog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjitesoft%2Fyolog/lists"}