{"_id":"@codensity/node","_rev":"4-11bca14c1c182eb0f9e9d7f737a9bd6d","name":"@codensity/node","dist-tags":{"latest":"0.5.0"},"versions":{"0.4.0":{"name":"@codensity/node","version":"0.4.0","keywords":["codensity","sustainability","resource-usage","telemetry","observability"],"license":"MIT","_id":"@codensity/node@0.4.0","maintainers":[{"name":"princeappiah","email":"pappiah00@gmail.com"}],"homepage":"https://github.com/prince-appiah/codensity-node#readme","bugs":{"url":"https://github.com/prince-appiah/codensity-node/issues"},"dist":{"shasum":"a9e7bd4cbc606403dc84d509e9baacadbb344cd3","tarball":"https://registry.npmjs.org/@codensity/node/-/node-0.4.0.tgz","fileCount":20,"integrity":"sha512-CiQFpwtgv1mzOjP+WORxG4j/ShdB7dzprQG1Owc8lbo/7wJMolUfRbKVS4yJPh6eqpuv4Bc6/QOMTaK988GU7Q==","signatures":[{"sig":"MEQCIDk/rARAaZRkY3AJDw3DAOgPKWx0JUfHd0WHs/PcqMB8AiBq8C5zgk5lwFE6KmbR/j8XKfPSJTRoil3RkYjAa3Vg8A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":146290},"main":"./dist/index.js","pnpm":{"overrides":{"vite":"7.3.5"},"onlyBuiltDependencies":["esbuild"]},"type":"commonjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./nestjs":{"import":{"types":"./dist/nestjs/index.d.mts","default":"./dist/nestjs/index.mjs"},"require":{"types":"./dist/nestjs/index.d.ts","default":"./dist/nestjs/index.js"}},"./middleware":{"import":{"types":"./dist/middleware/index.d.mts","default":"./dist/middleware/index.mjs"},"require":{"types":"./dist/middleware/index.d.ts","default":"./dist/middleware/index.js"}}},"gitHead":"fecf1f831f02a32b0cd43746f6b07d33809c1c56","scripts":{"ci":"pnpm install --frozen-lockfile && pnpm test && pnpm typecheck","dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","lint:package":"publint","pack:inspect":"node scripts/pack-inspect.mjs","prepublishOnly":"pnpm build","publish:dry-run":"pnpm build && npm publish --dry-run","clean-room-smoke":"node scripts/clean-room-smoke.mjs"},"_npmUser":{"name":"princeappiah","email":"pappiah00@gmail.com"},"deprecated":"Reports sdkVersion 0.3.0 in ingest payloads. Use 0.4.1 or later.","repository":{"url":"git+https://github.com/prince-appiah/codensity-node.git","type":"git"},"_npmVersion":"11.6.2","description":"Official Node.js SDK for Codensity resource usage and sustainability tracking","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.0","tsup":"^8.0.0","vitest":"^3.2.6","publint":"^0.3.12","typescript":"^5.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.1.19","reflect-metadata":"^0.2.0"},"peerDependencies":{"rxjs":">=7.0.0","@nestjs/core":">=9.0.0","@nestjs/common":">=9.0.0"},"peerDependenciesMeta":{"rxjs":{"optional":true},"@nestjs/core":{"optional":true},"@nestjs/common":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/node_0.4.0_1787999875795_0.6945397492316052","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@codensity/node","version":"0.4.1","keywords":["codensity","sustainability","resource-usage","telemetry","observability"],"license":"MIT","_id":"@codensity/node@0.4.1","maintainers":[{"name":"princeappiah","email":"pappiah00@gmail.com"}],"homepage":"https://github.com/prince-appiah/codensity-node#readme","bugs":{"url":"https://github.com/prince-appiah/codensity-node/issues"},"dist":{"shasum":"8a2292355f0074a5ddb8725eea6946a6f212a48d","tarball":"https://registry.npmjs.org/@codensity/node/-/node-0.4.1.tgz","fileCount":20,"integrity":"sha512-Y/lWGHfuJPjiFwKrVBOW3L9FIJGLZ/FddA9T6H1LD/z42CpPYAF9zibfZZo66/RtugblgfCYxgZCkxsdducMIA==","signatures":[{"sig":"MEYCIQDKToZRu4sbkjjbunLvhDnAYpfAeGIEJ4tyLTKsE1sW3wIhANomeFpl1y4tZ8ofdNz0v7jiE5kxJe1ZL+olhFFS6xk1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":146303},"main":"./dist/index.js","pnpm":{"overrides":{"vite":"7.3.5"},"onlyBuiltDependencies":["esbuild"]},"type":"commonjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./nestjs":{"import":{"types":"./dist/nestjs/index.d.mts","default":"./dist/nestjs/index.mjs"},"require":{"types":"./dist/nestjs/index.d.ts","default":"./dist/nestjs/index.js"}},"./middleware":{"import":{"types":"./dist/middleware/index.d.mts","default":"./dist/middleware/index.mjs"},"require":{"types":"./dist/middleware/index.d.ts","default":"./dist/middleware/index.js"}}},"gitHead":"179538f24344742f35624014a59ae91be2ca59a4","scripts":{"ci":"pnpm install --frozen-lockfile && pnpm test && pnpm typecheck","dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","lint:package":"publint","pack:inspect":"node scripts/pack-inspect.mjs","prepublishOnly":"pnpm test && pnpm build","publish:dry-run":"pnpm build && npm publish --dry-run","clean-room-smoke":"node scripts/clean-room-smoke.mjs"},"_npmUser":{"name":"princeappiah","email":"pappiah00@gmail.com"},"repository":{"url":"git+https://github.com/prince-appiah/codensity-node.git","type":"git"},"_npmVersion":"11.6.2","description":"Official Node.js SDK for Codensity resource usage and sustainability tracking","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.0","tsup":"^8.0.0","vitest":"^3.2.6","publint":"^0.3.12","typescript":"^5.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.1.19","reflect-metadata":"^0.2.0"},"peerDependencies":{"rxjs":">=7.0.0","@nestjs/core":">=9.0.0","@nestjs/common":">=9.0.0"},"peerDependenciesMeta":{"rxjs":{"optional":true},"@nestjs/core":{"optional":true},"@nestjs/common":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/node_0.4.1_1788000617217_0.7009972220901755","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@codensity/node","version":"0.5.0","description":"Official Node.js SDK for Codensity resource usage and sustainability tracking","keywords":["codensity","sustainability","resource-usage","telemetry","observability"],"license":"MIT","type":"commonjs","repository":{"type":"git","url":"git+https://github.com/prince-appiah/codensity-node.git"},"bugs":{"url":"https://github.com/prince-appiah/codensity-node/issues"},"homepage":"https://github.com/prince-appiah/codensity-node#readme","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./middleware":{"import":{"types":"./dist/middleware/index.d.mts","default":"./dist/middleware/index.mjs"},"require":{"types":"./dist/middleware/index.d.ts","default":"./dist/middleware/index.js"}},"./nestjs":{"import":{"types":"./dist/nestjs/index.d.mts","default":"./dist/nestjs/index.mjs"},"require":{"types":"./dist/nestjs/index.d.ts","default":"./dist/nestjs/index.js"}}},"publishConfig":{"access":"public"},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","prepublishOnly":"pnpm test && pnpm build","lint:package":"publint","pack:inspect":"node scripts/pack-inspect.mjs","publish:dry-run":"pnpm build && npm publish --dry-run","clean-room-smoke":"node scripts/clean-room-smoke.mjs","ci":"pnpm install --frozen-lockfile && pnpm test && pnpm typecheck"},"pnpm":{"onlyBuiltDependencies":["esbuild"],"overrides":{"vite":"7.3.5"}},"devDependencies":{"@nestjs/common":"^11.1.19","@nestjs/core":"^11.0.0","@types/node":"^22.0.0","reflect-metadata":"^0.2.0","rxjs":"^7.8.0","publint":"^0.3.12","tsup":"^8.0.0","typescript":"^5.0.0","vitest":"^3.2.6"},"peerDependencies":{"@nestjs/common":">=9.0.0","@nestjs/core":">=9.0.0","rxjs":">=7.0.0"},"peerDependenciesMeta":{"@nestjs/common":{"optional":true},"@nestjs/core":{"optional":true},"rxjs":{"optional":true}},"engines":{"node":">=18.0.0"},"gitHead":"1e013f1a315dda462a3608cb19155da161575bb7","_id":"@codensity/node@0.5.0","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-5vRVyo0edkibqrcwkI5+fqFlcr3iWiLDzt7j0rsyOits0kwYwZrxOtpTfYNkc/5wpCMPs3urlmBGNm/At2aUNg==","shasum":"4dae3ad9dbfd5b83d12a8951f73d52eb1324c088","tarball":"https://registry.npmjs.org/@codensity/node/-/node-0.5.0.tgz","fileCount":20,"unpackedSize":148379,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCXgTnAwPfyRHy07wU03ji0/NDIoq9t+sN8jl83mB8qbwIgfBINCivsp4csompT9X/UZgAbfcCrkHxyfLjp64Cog0U="}]},"_npmUser":{"name":"princeappiah","email":"pappiah00@gmail.com"},"directories":{},"maintainers":[{"name":"princeappiah","email":"pappiah00@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/node_0.5.0_1788950582056_0.3070589189731603"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-29T10:37:55.569Z","modified":"2026-09-09T10:43:02.397Z","0.4.0":"2026-08-29T10:37:55.938Z","0.4.1":"2026-08-29T10:50:17.357Z","0.5.0":"2026-09-09T10:43:02.198Z"},"bugs":{"url":"https://github.com/prince-appiah/codensity-node/issues"},"license":"MIT","homepage":"https://github.com/prince-appiah/codensity-node#readme","keywords":["codensity","sustainability","resource-usage","telemetry","observability"],"repository":{"type":"git","url":"git+https://github.com/prince-appiah/codensity-node.git"},"description":"Official Node.js SDK for Codensity resource usage and sustainability tracking","maintainers":[{"name":"princeappiah","email":"pappiah00@gmail.com"}],"readme":"# @codensity/node\n\nOfficial Node.js SDK for Codensity resource usage and sustainability tracking.\n\n## Install\n\n```bash\nnpm install @codensity/node\n```\n\n```bash\npnpm add @codensity/node\n```\n\n```bash\nyarn add @codensity/node\n```\n\n## Quick start\n\n```ts\nimport { CodensityClient } from \"@codensity/node\";\n\nconst codensity = new CodensityClient({\n  key: process.env.CODENSITY_KEY!,\n  environment: \"production\",\n});\n\nconst result = await codensity.track(\"checkout-flow\", () =>\n  processCheckout(data),\n);\n```\n\nCredentials include both the SDK secret and its destination:\n\n```text\ncds_live_<32-character-random>@api.getcodensity.com\ncds_test_<32-character-random>@localhost:3000\n```\n\nThe client sends only the portion before `@` in the `x-api-key` header. Bare\nhosts use HTTPS. `localhost` and `127.0.0.1`, with an optional port, use HTTP.\nAn explicit `http://` or `https://` scheme is honored.\n\nFor a plain SDK secret without `@`, set the API destination separately:\n\n```bash\nCODENSITY_BASE_URL=https://api.getcodensity.com\n```\n\nThere is no compiled default API URL. Constructing a client with a plain secret\nand no `CODENSITY_BASE_URL` throws an error.\n\n## Client options\n\n```ts\nconst codensity = new CodensityClient({\n  key: process.env.CODENSITY_KEY!,\n  environment: \"production\",\n  appVersion: \"2.1.0\",\n  flushInterval: 5_000,\n  maxBatchSize: 50,\n  maxBufferSize: 1_000,\n  maxRetries: 2,\n  onError: (error) => console.error(\"[codensity]\", error),\n});\n```\n\n| Option | Required | Default | Description |\n| --- | --- | --- | --- |\n| `key` | Yes | None | Composite credential or plain SDK secret |\n| `environment` | Yes | None | Default environment label for recorded events |\n| `appVersion` | No | None | Application version attached to batches |\n| `flushInterval` | No | `5000` | Milliseconds between automatic flushes |\n| `maxBatchSize` | No | `50` | Events that trigger an immediate flush |\n| `maxBufferSize` | No | `1000` | Maximum buffered events while ingestion is unavailable |\n| `maxRetries` | No | `2` | Retries for network errors, HTTP 429, and HTTP 5xx |\n| `onError` | No | None | Receives ingestion and buffer errors |\n\n## Track async work\n\n`track` measures execution time and memory usage, records the event, and returns\nthe wrapped function result.\n\n```ts\nconst user = await codensity.track(\"get-user\", () =>\n  db.users.findById(userId),\n);\n```\n\nFailed functions are still measured and recorded before the original error is\nre-thrown.\n\n## Record measured work\n\n```ts\ncodensity.record({\n  featureKey: \"checkout-flow\",\n  executionTimeMs: 145,\n  memoryBytes: 1024,\n  metadata: { region: \"eu-north-1\" },\n});\n```\n\nEvery event receives a stable client-generated `eventId`. Retries reuse that\nidentifier so the server can deduplicate deliveries.\n\n## Flush pending events\n\n```ts\nawait codensity.flush();\n```\n\nCall `flush` before process shutdown, at the end of serverless invocations, or\nafter short-lived scripts finish their work. NestJS applications get this\nautomatically, see [Shutdown](#shutdown).\n\n## Express\n\nGlobal request tracking uses the request path as the feature key:\n\n```ts\nimport { CodensityClient } from \"@codensity/node\";\nimport express from \"express\";\n\nconst app = express();\nconst codensity = new CodensityClient({\n  key: process.env.CODENSITY_KEY!,\n  environment: \"production\",\n});\n\napp.use(codensity.use());\n```\n\nPer-route tracking uses an explicit feature key:\n\n```ts\napp.post(\n  \"/checkout\",\n  codensity.trackFlow(\"checkout-flow\"),\n  checkoutHandler,\n);\n```\n\n## NestJS\n\n### Synchronous setup\n\n```ts\nimport { Module } from \"@nestjs/common\";\nimport { CodensityModule } from \"@codensity/node/nestjs\";\n\n@Module({\n  imports: [\n    CodensityModule.forRoot({\n      key: process.env.CODENSITY_KEY!,\n      environment: \"production\",\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Asynchronous setup\n\n```ts\nimport { Module } from \"@nestjs/common\";\nimport { ConfigModule, ConfigService } from \"@nestjs/config\";\nimport { CodensityModule } from \"@codensity/node/nestjs\";\n\n@Module({\n  imports: [\n    ConfigModule.forRoot(),\n    CodensityModule.forRootAsync({\n      imports: [ConfigModule],\n      inject: [ConfigService],\n      useFactory: (config: ConfigService) => ({\n        key: config.getOrThrow<string>(\"CODENSITY_KEY\"),\n        environment: \"production\",\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Global interceptor\n\n```ts\nimport type { CodensityClient } from \"@codensity/node\";\nimport {\n  CODENSITY_CLIENT,\n  CodensityInterceptor,\n} from \"@codensity/node/nestjs\";\nimport { Reflector } from \"@nestjs/core\";\n\nconst client = app.get<CodensityClient>(CODENSITY_CLIENT);\nconst reflector = app.get(Reflector);\napp.useGlobalInterceptors(new CodensityInterceptor(client, reflector));\n```\n\n### Track decorator\n\n```ts\nimport { Track } from \"@codensity/node/nestjs\";\n\n@Track(\"checkout-flow\")\nasync checkout() {\n  return this.checkoutService.process();\n}\n```\n\n### Inject the client\n\n```ts\nimport type { CodensityClient } from \"@codensity/node\";\nimport { CODENSITY_CLIENT } from \"@codensity/node/nestjs\";\nimport { Inject, Injectable } from \"@nestjs/common\";\n\n@Injectable()\nexport class ReportsService {\n  constructor(\n    @Inject(CODENSITY_CLIENT)\n    private readonly codensity: CodensityClient,\n  ) {}\n\n  generate() {\n    return this.codensity.track(\"analytics-report\", () =>\n      this.buildReport(),\n    );\n  }\n}\n```\n\n### Shutdown\n\n`CodensityModule` flushes buffered events for you. It registers a\n`beforeApplicationShutdown` hook, which Nest runs before connections are closed,\nso pending events are delivered while the process is still fully alive.\n\nNest runs that hook whenever `app.close()` is called. Choose one of these in your\napplication, not both:\n\n```ts\napp.enableShutdownHooks();\n```\n\nThis attaches Nest's own `SIGTERM` and `SIGINT` listeners, which call\n`app.close()` for you. Use it when the framework owns termination.\n\n```ts\nprocess.on(\"SIGTERM\", async () => {\n  await app.close();\n  process.exit(0);\n});\n```\n\nUse your own handler instead when you need something Nest does not do, such as\nan explicit `process.exit` because other resources keep the event loop alive.\n`app.close()` runs the shutdown hooks either way, so the flush still happens.\nCalling `enableShutdownHooks()` as well leaves two sets of listeners racing on\nthe same signal.\n\nFlush manually only when the process ends without `app.close()` ever running,\nsuch as a bare `process.exit()`, a serverless handler returning, or a script\nthat finishes its work:\n\n```ts\nimport type { CodensityClient } from \"@codensity/node\";\nimport { CODENSITY_CLIENT } from \"@codensity/node/nestjs\";\n\nconst codensity = app.get<CodensityClient>(CODENSITY_CLIENT);\nawait codensity.flush();\n```\n\nOutside NestJS there is no lifecycle to hook into, so `flush` before exit is\nalways the caller's responsibility.\n\n## Requirements\n\n- Node.js 18 or later\n- NestJS 9 or later for the optional NestJS integration\n\n## License\n\nMIT\n","readmeFilename":"README.md"}