{"id":31392830,"url":"https://github.com/formidablelabs/envelop-network-viewer","last_synced_at":"2025-10-20T08:01:49.126Z","repository":{"id":54749658,"uuid":"520969566","full_name":"FormidableLabs/envelop-network-viewer","owner":"FormidableLabs","description":"This plugin is designed to provide visibility into how many/what network requests are made by your GraphQL Operations. ","archived":false,"fork":false,"pushed_at":"2023-05-16T19:18:00.000Z","size":1079,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":29,"default_branch":"main","last_synced_at":"2025-09-21T02:35:46.392Z","etag":null,"topics":["envelop","graphql","node"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/FormidableLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-03T17:16:53.000Z","updated_at":"2023-08-23T16:00:55.000Z","dependencies_parsed_at":"2023-02-02T22:45:16.687Z","dependency_job_id":null,"html_url":"https://github.com/FormidableLabs/envelop-network-viewer","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/FormidableLabs/envelop-network-viewer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Fenvelop-network-viewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Fenvelop-network-viewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Fenvelop-network-viewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Fenvelop-network-viewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FormidableLabs","download_url":"https://codeload.github.com/FormidableLabs/envelop-network-viewer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Fenvelop-network-viewer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277467479,"owners_count":25822917,"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-09-29T02:00:09.175Z","response_time":84,"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":["envelop","graphql","node"],"created_at":"2025-09-29T04:47:34.367Z","updated_at":"2025-09-29T04:47:37.885Z","avatar_url":"https://github.com/FormidableLabs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![envelop-network-viewer — Formidable, We build the modern web](https://raw.githubusercontent.com/FormidableLabs/envelop-network-viewer/main/envelop-network-viewer-Hero.png)](https://formidable.com/open-source/)\n\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=FormidableLabs_envelop-network-viewer\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=FormidableLabs_envelop-network-viewer)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=FormidableLabs_envelop-network-viewer\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=FormidableLabs_envelop-network-viewer)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=FormidableLabs_envelop-network-viewer\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=FormidableLabs_envelop-network-viewer)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=FormidableLabs_envelop-network-viewer\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=FormidableLabs_envelop-network-viewer)\n\nThis plugin is designed to provide visibility into how many/what network requests are made by your GraphQL Operations. \nThis tool is primarily targeted for existing graphql projects that have grown large and complex with integrations and \ndevelopers want some insight into how heavy specific GraphQL operations are in order to identify cache or optimization \ncandidates. Below is an example of possible log output of the plugin:\n\n```\nuseNetworkViewer {\"operationName\":\"test\",\"document\":\"query test {\\n  test\\n}\",\"observations\":[{\"label\":\"HTTP/HTTPS\",\"data\":{\"calls\":1,\"hosts\":[\"localhost\"],\"requests\":[{\"time\":1659986144633,\"method\":\"GET\",\"host\":\"localhost\",\"port\":\"8883\",\"headers\":{},\"response\":{\"time\":1659986144636,\"httpVersion\":\"1.1\",\"statusCode\":200,\"headers\":{\"server\":\"stubby/5.1.0 node/v14.19.3 (darwin arm64)\",\"x-stubby-resource-id\":\"1\",\"date\":\"Mon, 08 Aug 2022 19:15:44 GMT\",\"connection\":\"close\",\"transfer-encoding\":\"chunked\"},\"statusMessage\":\"OK\"},\"duration_ms\":3}]}}]}\n```\n\nPrettified output:\n```JSON\n{\n  \"operationName\": \"test\",\n  \"document\": \"query test {\\n  test\\n}\",\n  \"observations\": [\n    {\n      \"label\": \"HTTP/HTTPS\",\n      \"data\": {\n        \"calls\": 1,\n        \"hosts\": [\n          \"localhost\"\n        ],\n        \"requests\": [\n          {\n            \"time\": 1659986144633,\n            \"method\": \"GET\",\n            \"host\": \"localhost\",\n            \"port\": \"8883\",\n            \"headers\": {},\n            \"response\": {\n              \"time\": 1659986144636,\n              \"httpVersion\": \"1.1\",\n              \"statusCode\": 200,\n              \"headers\": {\n                \"server\": \"stubby/5.1.0 node/v14.19.3 (darwin arm64)\",\n                \"x-stubby-resource-id\": \"1\",\n                \"date\": \"Mon, 08 Aug 2022 19:15:44 GMT\",\n                \"connection\": \"close\",\n                \"transfer-encoding\": \"chunked\"\n              },\n              \"statusMessage\": \"OK\"\n            },\n            \"duration_ms\": 3\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\n\nKeep in mind, that this is an investigative tool that can have a heavy impact on your logs. It should only be turned on \nfor explicit data collection activities.\n\n### Concurrency Caveat\nSupporting concurrent requests relies on using Continuation-local storage, which has a performance cost, and so it isn't enabled by default.\nIf your use case is not lambda like (node process serves one request at a time), then you will need to enable concurrency support for the plugin.\n\nUse the `enableConcurrencySupport` configuration option to enable concurrency support. \n\n## Usage\nAdd the useNetworkViewer plugin to your envelop configuration. Note the constructor takes two parameters:\n1. The first parameter is a boolean determining if the plugin is enabled. You must explicitly enable the plugin (recommended w/ an env variable)\n2. The second parameter is the configuration for the plugin\n\n```javascript\nconst useNetworkViewerConfig = {\n    // plugin options\n};\n\nconst getEnveloped = envelop({\n  plugins: [\n    // all enabled plugins\n    useNetworkViewer(boolean(process.env.USE_NETWORK_VIEWER), useNetworkViewerConfig)\n  ]\n})\n```\n\n### Config\nBelow is a list of configuration properties and what they do\n\n| property | default | description |\n| --- | --- | --- |\n| additionalObservers | empty array | Only the http/https observer is included by default. You must specify other observers that are use case specific (knex, redis, mysql, etc) |\n| logFunction | console.log | Specify what function is used to log network viewer info. You can specify your own logger (myLogger.debug for instance) |\n| logGraphQlDocument | false | Set to true to include the graphql operation in the log message |\n| enableConcurrencySupport | false | Support concurrent requests |\n\n\n## Additional Observers\nThese additional observers aren't included by default. They are purpose specific observers that will only be applicable to some app stacks.\n\n### Prisma Observer\nIf your application uses Prisma, you'll want to include the `PrismaObserver` in your configuration of the plugin. \nThe prisma client observer provides observations for your database interactions using the prisma client.\n\n#### Usage\nYou'll need to initialize the prisma client and pass it as a parameter when instantiating the `PrismaObserver`. \nThen pass the `PrismaObserver` instance in the `additionalObservers` configuration.   \n\n```typescript\nconst prisma = new PrismaClient()\n\nconst useNetworkViewerConfig = {\n  additionalObservers: [new PrismaObserver(prisma)]\n};\n\nconst getEnveloped = envelop({\n  plugins: [\n    useNetworkViewer(true, useNetworkViewerConfig)\n  ]\n})\n```\n\n### Sequelize Observer\nIf your application uses Sequelize, you'll want to include the `SequelizeObserver` in your configuration of the plugin. \nThe sequelize observer provides observations for your database interactions using the sequelize client.\n\n#### Usage\nYou'll need to initialize the sequelize client and pass it as a parameter when instantiating the `SequelizeObserver`. \nThen pass the `SequelizeObserver` instance in the `additionalObservers` configuration.   \n\n```typescript\nconst sequelize = new Sequelize('sqlite::memory:');\n\nconst useNetworkViewerConfig = {\n  additionalObservers: [new SequelizeObserver(sequelize)]\n};\n\nconst getEnveloped = envelop({\n  plugins: [\n    useNetworkViewer(true, useNetworkViewerConfig)\n  ]\n})\n```\n\n### Knex.js Observer\nIf your application uses Knex.js, you'll want to include the `KnexObserver` in your configuration of the plugin. \nThe Knex observer provides observations for your database interactions using the Knex client.\n\n#### Usage\nYou'll need to initialize the Knex client and pass it as a parameter when instantiating the `KnexObserver`. \nThen pass the `KnexObserver` instance in the `additionalObservers` configuration.   \n\n```typescript\nconst knex = Knex({\n  client: 'sqlite3',\n  connection: {\n    filename: ':memory:',\n  },\n});\n\nconst useNetworkViewerConfig = {\n  additionalObservers: [new KnexObserver(knex)]\n};\n\nconst getEnveloped = envelop({\n  plugins: [\n    useNetworkViewer(true, useNetworkViewerConfig)\n  ]\n})\n```\n\n### TypeORM Observer\nIf your application uses TypeORM, you'll want to include the `TypeORMObserver` in your configuration of the plugin. \nThe TypeORM observer provides observations for your database interactions using the TypeORM datasource.\n\n#### Usage\nYou'll need to initialize the TypeORM datasource with `options.logger` set to an instance of `TypeORMObserverLogger`.\nThen pass the instance of the `TypeORMObserverLogger` when instantiating the `TypeORMObserver`. \nFinally, pass the `TypeORMObserver` instance in the `additionalObservers` configuration.   \n\n```typescript\nconst typeOrmObserverLogger = new TypeOrmObserverLogger();\n\nconst datasource = new DataSource({\n  type: 'sqlite',\n  database: ':memory:',\n  logger: typeOrmObserverLogger,\n  logging: ['error'], // still respected\n});\n\nconst useNetworkViewerConfig = {\n  additionalObservers: [new TypeORMObserver(typeOrmObserverLogger)]\n};\n\nconst getEnveloped = envelop({\n  plugins: [\n    useNetworkViewer(true, useNetworkViewerConfig)\n  ]\n})\n```\n\nIf you've already configured your datasource with `logger` and `logging` value, you can provide those to `TypeORMObserverLogger` instead. \nThe `TypeORMObserverLogger` will pass all logging to the provided logger.\n\nExample, to use one the built-in file logger to log query errors then you would use the following\nto initialize the `TypeORMObserverLogger`\n\n```typescript \nconst typeOrmObserverLogger = new TypeOrmObserverLogger(\n  \"file\", /* or any valid DataSourceOptions.logger value */ \n  ['error'] /* or any valid DataSourceOptions.logging value */)\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fformidablelabs%2Fenvelop-network-viewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fformidablelabs%2Fenvelop-network-viewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fformidablelabs%2Fenvelop-network-viewer/lists"}