{"_id":"@22hbg/sentinel-node","_rev":"5-d92e69a5f61844c78c2aef59fc180970","name":"@22hbg/sentinel-node","dist-tags":{"latest":"0.4.2"},"versions":{"0.1.0":{"name":"@22hbg/sentinel-node","version":"0.1.0","keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"license":"MIT","_id":"@22hbg/sentinel-node@0.1.0","maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"dist":{"shasum":"55b58910d542eda27ce525c7bb962cd66f955183","tarball":"https://registry.npmjs.org/@22hbg/sentinel-node/-/sentinel-node-0.1.0.tgz","fileCount":42,"integrity":"sha512-z6jobwnR0cXbOFF0jIQUByk1u/UoWE92PeeMGGROLJn83U1nQm4LNFVhSY/CXF0lX7yoxWSMF9NdwvkRyqUSBA==","signatures":[{"sig":"MEYCIQDOqCpzED32mtWsQLU5mBiSb9ZTDaBN1vmL+pdttHBiWQIhAI2qmRpkB1KRr4UlI121iTIJbAlOlX1XAno7Q6KvFZsK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48564},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./register":{"types":"./dist/register.d.ts","import":"./dist/register.js"}},"gitHead":"09077f980985791e872eaf241406e4010e1a65aa","private":false,"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"22hbgsrl","email":"services@22hbg.it"},"_npmVersion":"10.8.2","description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@opentelemetry/api":"^1.9.1","import-in-the-middle":"^3.3.1","@opentelemetry/api-logs":"^0.220.0","@opentelemetry/sdk-logs":"^0.220.0","@opentelemetry/sdk-node":"^0.220.0","@opentelemetry/resources":"^2.9.0","@opentelemetry/instrumentation-http":"^0.220.0","@opentelemetry/semantic-conventions":"^1.42.0","@opentelemetry/exporter-logs-otlp-http":"^0.220.0","@opentelemetry/exporter-trace-otlp-http":"^0.220.0","@opentelemetry/auto-instrumentations-node":"^0.78.0","@opentelemetry/exporter-metrics-otlp-http":"^0.220.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.2","@types/node":"^22.7.4"},"_npmOperationalInternal":{"tmp":"tmp/sentinel-node_0.1.0_1783587622490_0.2597682135831476","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@22hbg/sentinel-node","version":"0.2.0","keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"license":"MIT","_id":"@22hbg/sentinel-node@0.2.0","maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"dist":{"shasum":"e12acf395fc69e00cd8c2315eb6581be42c4388f","tarball":"https://registry.npmjs.org/@22hbg/sentinel-node/-/sentinel-node-0.2.0.tgz","fileCount":42,"integrity":"sha512-0WHQY2zW/nKVkgZZFQ258Dwsur4ixUCYQ2EyVKb6nsQPUJqmr5Vrfw5z3A1uO+BFsMyESty8ckeAVM7jrPokYg==","signatures":[{"sig":"MEUCIQDYOryh4w9IphE5WJd2QUeioUlKWR2qlMSbgBb9fxpyFAIgAe5cs1HA2ujLMDCAM/14kYexogCPkLed0RdnYWCfGQk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55170},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./register":{"types":"./dist/register.d.ts","import":"./dist/register.js"}},"gitHead":"e400505db408d9f24ec449ed3ebdfafa298eb69a","private":false,"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"22hbgsrl","email":"services@22hbg.it"},"_npmVersion":"10.8.2","description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@opentelemetry/api":"^1.9.1","import-in-the-middle":"^3.3.1","@opentelemetry/api-logs":"^0.220.0","@opentelemetry/sdk-logs":"^0.220.0","@opentelemetry/sdk-node":"^0.220.0","@opentelemetry/resources":"^2.9.0","@opentelemetry/instrumentation-http":"^0.220.0","@opentelemetry/semantic-conventions":"^1.42.0","@opentelemetry/exporter-logs-otlp-http":"^0.220.0","@opentelemetry/exporter-trace-otlp-http":"^0.220.0","@opentelemetry/auto-instrumentations-node":"^0.78.0","@opentelemetry/exporter-metrics-otlp-http":"^0.220.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.2","@types/node":"^22.7.4"},"_npmOperationalInternal":{"tmp":"tmp/sentinel-node_0.2.0_1783608953534_0.12346392274706508","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@22hbg/sentinel-node","version":"0.3.0","keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"license":"MIT","_id":"@22hbg/sentinel-node@0.3.0","maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"dist":{"shasum":"65ecad01edc49c70c3633b4566f99f6da01e4d4a","tarball":"https://registry.npmjs.org/@22hbg/sentinel-node/-/sentinel-node-0.3.0.tgz","fileCount":11,"integrity":"sha512-iq4F/Eg6UtXHL7L4eRbAtlAF62xRhYFf2byC4ezHtXdGcoJxLLBhjQGjwgFYzelLnEoKh9MMkH2A7Hmf6EHd/A==","signatures":[{"sig":"MEUCIGNQVX+tgCFUDILP1ZzV/M6op6xu0ohF0e12TLKMZtr7AiEAw7UdfWcG4TsESDiYRtleDsVD5q8OUFgjmNOgiGqzzXY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":138233},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/register.d.ts","default":"./dist/register.js"}}},"gitHead":"5b569e762d3fdea979bcf4ed182d6e921f43fcaf","private":false,"scripts":{"build":"tsup","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"22hbgsrl","email":"services@22hbg.it"},"_npmVersion":"10.8.2","description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@opentelemetry/api":"^1.9.1","import-in-the-middle":"^3.3.1","@opentelemetry/api-logs":"^0.220.0","@opentelemetry/sdk-logs":"^0.220.0","@opentelemetry/sdk-node":"^0.220.0","@opentelemetry/resources":"^2.9.0","@opentelemetry/instrumentation-http":"^0.220.0","@opentelemetry/semantic-conventions":"^1.42.0","@opentelemetry/exporter-logs-otlp-http":"^0.220.0","@opentelemetry/exporter-trace-otlp-http":"^0.220.0","@opentelemetry/auto-instrumentations-node":"^0.78.0","@opentelemetry/exporter-metrics-otlp-http":"^0.220.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","typescript":"^5.6.2","@types/node":"^22.7.4"},"_npmOperationalInternal":{"tmp":"tmp/sentinel-node_0.3.0_1783610325967_0.07970200408153261","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@22hbg/sentinel-node","version":"0.4.0","keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"license":"MIT","_id":"@22hbg/sentinel-node@0.4.0","maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"dist":{"shasum":"45d51f846688a3371e1cd0b6f13c4a2070d88392","tarball":"https://registry.npmjs.org/@22hbg/sentinel-node/-/sentinel-node-0.4.0.tgz","fileCount":11,"integrity":"sha512-JSlKK5wzU/qR6npf8aQndj9LhGM2V/TtoesaMVgTF5wRUTr9IGyG/8WSwBw0N9UIazwqrc9kMOVYfMIQEUdhMQ==","signatures":[{"sig":"MEYCIQDjgF6jEjypfEit14PmheSkc7bqNsPiEfyNirfpS4RdXgIhAJLFjJg5E3+9HLZQR8DBkCp3mWqwZLEKZq6yOUF2w6VN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":141756},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/register.d.ts","default":"./dist/register.js"}}},"gitHead":"5f7b5e4daea4b6a06ebc8681a8770b88a8968724","private":false,"scripts":{"build":"tsup","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"22hbgsrl","email":"services@22hbg.it"},"_npmVersion":"10.8.2","description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@opentelemetry/api":"^1.9.1","import-in-the-middle":"^3.3.1","@opentelemetry/api-logs":"^0.220.0","@opentelemetry/sdk-logs":"^0.220.0","@opentelemetry/sdk-node":"^0.220.0","@opentelemetry/resources":"^2.9.0","@opentelemetry/instrumentation-http":"^0.220.0","@opentelemetry/semantic-conventions":"^1.42.0","@opentelemetry/exporter-logs-otlp-http":"^0.220.0","@opentelemetry/exporter-trace-otlp-http":"^0.220.0","@opentelemetry/auto-instrumentations-node":"^0.78.0","@opentelemetry/exporter-metrics-otlp-http":"^0.220.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","typescript":"^5.6.2","@types/node":"^22.7.4"},"_npmOperationalInternal":{"tmp":"tmp/sentinel-node_0.4.0_1783692061240_0.8522509962438996","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@22hbg/sentinel-node","version":"0.4.2","description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","license":"MIT","private":false,"publishConfig":{"access":"public"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./register":{"import":{"types":"./dist/register.d.ts","default":"./dist/register.js"}}},"keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"engines":{"node":">=20"},"scripts":{"build":"tsup","typecheck":"tsc -p tsconfig.json --noEmit"},"devDependencies":{"@types/node":"^22.7.4","tsup":"^8.3.0","typescript":"^5.6.2"},"dependencies":{"@opentelemetry/api":"^1.9.1","@opentelemetry/api-logs":"^0.220.0","@opentelemetry/auto-instrumentations-node":"^0.78.0","@opentelemetry/exporter-logs-otlp-http":"^0.220.0","@opentelemetry/exporter-metrics-otlp-http":"^0.220.0","@opentelemetry/exporter-trace-otlp-http":"^0.220.0","@opentelemetry/instrumentation-http":"^0.220.0","@opentelemetry/resources":"^2.9.0","@opentelemetry/sdk-logs":"^0.220.0","@opentelemetry/sdk-node":"^0.220.0","@opentelemetry/semantic-conventions":"^1.42.0","import-in-the-middle":"^3.3.1"},"gitHead":"a1e860d9960db13a060382fc5917fe5847261237","_id":"@22hbg/sentinel-node@0.4.2","_nodeVersion":"20.20.2","_npmVersion":"11.19.1","dist":{"integrity":"sha512-mKwv9Fmu4yoJP22wZ4DZkrOR3zUUDsJJ1+xuYI63bz3wAfTWG4YcluyMw22qEqQVTua+5vT97/zu8OMgr/NSJw==","shasum":"f5f1daccd38ff0701e1b9b935b50cce67b270e38","tarball":"https://registry.npmjs.org/@22hbg/sentinel-node/-/sentinel-node-0.4.2.tgz","fileCount":11,"unpackedSize":141756,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD9VrF3UY/40KmLmHYK52Suo0Gftgi+GpRPTHyw6avkFwIhAJSDDpTqWKKLAtlMnlJG0WTsej3UofJBuQ6Ym7LfiJI2"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b11f5e66-e599-4413-b167-c83f8c9ff45d"}},"directories":{},"maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sentinel-node_0.4.2_1788425466893_0.8615557361712656"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-09T09:00:22.383Z","modified":"2026-09-03T08:51:07.226Z","0.1.0":"2026-07-09T09:00:22.639Z","0.2.0":"2026-07-09T14:55:53.675Z","0.3.0":"2026-07-09T15:18:46.104Z","0.4.0":"2026-07-10T14:01:01.396Z","0.4.2":"2026-09-03T08:51:07.028Z"},"license":"MIT","keywords":["sentinel","observability","opentelemetry","otlp","tracing","metrics","logs","apm"],"description":"Sentinel observability SDK for Node.js — traces, metrics and logs over OTLP/HTTP, powered by OpenTelemetry.","maintainers":[{"name":"22hbgsrl","email":"services@22hbg.it"}],"readme":"# @22hbg/sentinel-node\n\nSentinel observability SDK for Node.js — a thin, opinionated wrapper over the\n[OpenTelemetry](https://opentelemetry.io) Node SDK that ships **traces,\nmetrics and logs** to a Sentinel server over OTLP/HTTP.\n\n- One-line setup, sensible defaults, zero-code `--import` mode\n- Automatic instrumentation (HTTP, Express, pg, Redis, …) with the noisy ones off\n- Structured logger with automatic trace correlation\n- `captureException`, custom spans, metric helpers\n- Never crashes your app: init/telemetry failures degrade to a warning + no-op\n\nRequires Node.js >= 20. ESM-only.\n\n## Install\n\n```sh\nnpm install @22hbg/sentinel-node        # or: pnpm add @22hbg/sentinel-node\n```\n\nInside this monorepo:\n\n```sh\npnpm add @22hbg/sentinel-node --filter <your-app>   # resolves via workspace:*\n```\n\n## Quickstart\n\n```ts\nimport { startSentinel, logger, withSpan, metrics } from \"@22hbg/sentinel-node\";\n\nstartSentinel({\n  token: \"sat_...\",                          // or env SENTINEL_TOKEN\n  endpoint: \"https://sentinel.example.com\",  // or env SENTINEL_ENDPOINT\n  service: \"checkout-api\",                   // or env SENTINEL_SERVICE\n  environment: \"production\",                 // optional\n  version: \"1.4.2\",                          // optional\n});\n\nlogger.info(\"order placed\", { orderId: 42 });\n```\n\nCall `startSentinel()` as early as possible (before importing the frameworks\nyou want auto-instrumented) — or use the zero-code form below.\n\n### CommonJS\n\nThe package is dual (ESM **and** CommonJS), so `require()` works too:\n\n```js\nconst { startSentinel, logger } = require(\"@22hbg/sentinel-node\");\nstartSentinel({ service: \"checkout-api\" }); // reads SENTINEL_TOKEN / SENTINEL_ENDPOINT\nlogger.info(\"order placed\", { orderId: 42 });\n```\n\nThe one exception is the zero-code preload `@22hbg/sentinel-node/register`,\nwhich is **ESM-only** (it uses an ESM loader hook). It still works for a\nCommonJS app — the preload runs in ESM and your CJS code `require()`s the\n`logger` normally; both share the same provider:\n\n```sh\nSENTINEL_TOKEN=sat_… SENTINEL_ENDPOINT=https://sentinel.example.com \\\nSENTINEL_SERVICE=checkout-api node --import @22hbg/sentinel-node/register app.cjs\n```\n\n## Zero-code setup\n\nNo source changes required — bootstrap via Node's `--import` flag:\n\n```sh\nSENTINEL_TOKEN=sat_... \\\nSENTINEL_ENDPOINT=https://sentinel.example.com \\\nSENTINEL_SERVICE=checkout-api \\\nnode --import @22hbg/sentinel-node/register app.js\n```\n\n## Configuration\n\nPrecedence: explicit `startSentinel()` options > `SENTINEL_*` env vars >\nstandard `OTEL_*` env vars > defaults.\n\n| Env var | Option | Default | Description |\n| --- | --- | --- | --- |\n| `SENTINEL_TOKEN` | `token` | — | Agent token (`sat_...`). Optional when exporting to a local host agent; otherwise a warning is logged if missing. |\n| `SENTINEL_ENDPOINT` | `endpoint` | `http://localhost:4318` | Base URL of the Sentinel server or host agent. The SDK appends `/v1/traces`, `/v1/metrics`, `/v1/logs`. Falls back to `OTEL_EXPORTER_OTLP_ENDPOINT`. |\n| `SENTINEL_SERVICE` | `service` | `unknown_service:node` | Service name (`service.name`). Falls back to `OTEL_SERVICE_NAME`. |\n| `SENTINEL_ENVIRONMENT` | `environment` | — | Deployment environment (`deployment.environment`), e.g. `production`. |\n| `SENTINEL_VERSION` | `version` | — | Service version (`service.version`). |\n| — | `instrumentations` | `\"auto\"` | `\"auto\"` (full auto-instrumentation, fs/dns/net disabled), `\"http-only\"`, or an array of your own instrumentations (`[]` disables). |\n| `SENTINEL_STARTUP_LOG` | `startupLog` | `true` | Emit an INFO log the moment the SDK connects (flushed immediately) so the service's monitor shows activity right away. Set to `false` to disable. |\n| `SENTINEL_DEBUG` | `debug` | `false` | Verbose SDK diagnostics on the console. Export **errors** (e.g. a rejected token → `401 Invalid or unauthorized agent token`) are printed regardless, so you can tell whether telemetry reaches the API. |\n\nMetrics are exported every 15 seconds; traces and logs are batched.\n\n> **Just connected but the monitor shows no logs?** That's expected until your\n> app calls `logger.*` — auto-instrumentation only produces **traces**. On\n> startup the SDK emits one `Sentinel SDK connected …` log so you can confirm\n> the pipeline immediately; if you don't even see that, check the console for a\n> `[sentinel] …` line and any `401`/export error (usually a wrong token or endpoint).\n\n## Logs\n\n```ts\nimport { logger } from \"@22hbg/sentinel-node\";\n\nlogger.debug(\"cache miss\", { key: \"user:42\" });\nlogger.info(\"order placed\", { orderId: 42 });\nlogger.warn(\"retrying payment\", { attempt: 2 });\nlogger.error(\"checkout failed\", { err });   // Error values are expanded to\n                                            // err.message / err.stack attributes\n```\n\nLog records emitted inside a span are automatically correlated with the\nactive trace (trace/span IDs are attached).\n\n## Exceptions\n\n```ts\nimport { captureException } from \"@22hbg/sentinel-node\";\n\ntry {\n  await chargeCard(order);\n} catch (err) {\n  captureException(err, { orderId: order.id });\n  throw err;\n}\n```\n\nEmits an ERROR log with `exception.type` / `exception.message` /\n`exception.stacktrace`, and — when inside an active span — records the\nexception on the span and marks it as errored.\n\n## Custom spans\n\n```ts\nimport { withSpan } from \"@22hbg/sentinel-node\";\n\nconst receipt = await withSpan(\"charge-card\", async (span) => {\n  span.setAttribute(\"payment.provider\", \"stripe\");\n  return chargeCard(order);\n}, { orderId: order.id });\n```\n\nThe span is ended automatically; thrown errors are recorded and re-thrown\nwith the span status set to ERROR. Works with sync and async functions.\n\n## Metrics\n\n```ts\nimport { metrics } from \"@22hbg/sentinel-node\";\n\nconst orders = metrics.counter(\"orders_placed\");\norders.add(1, { plan: \"pro\" });\n\nconst latency = metrics.histogram(\"checkout_duration_ms\", { unit: \"ms\" });\nlatency.record(183);\n\nconst queue = metrics.gauge(\"queue_depth\");\nqueue.record(7);\n```\n\nThe helpers return standard OpenTelemetry instruments. Create them after\n`startSentinel()` so they bind to the initialized meter provider.\n\n## Shutdown\n\n```ts\nimport { shutdownSentinel } from \"@22hbg/sentinel-node\";\n\nawait shutdownSentinel(); // flush all pending telemetry\n```\n\nThe SDK also hooks `SIGTERM` / `SIGINT` / `beforeExit` to flush automatically\n(it never calls `process.exit` itself). Call `shutdownSentinel()` manually\nbefore an explicit `process.exit()`.\n\n## Where to point it\n\n**Through the Sentinel host agent (recommended on monitored hosts).** The\nagent runs a local OTLP receiver — no token needed:\n\n```sh\nSENTINEL_ENDPOINT=http://localhost:4318 node --import @22hbg/sentinel-node/register app.js\n```\n\n**Directly to the Sentinel server.** Use your Sentinel URL and an agent token\n(Sentinel UI → Infrastructure → *host* → **Agent token**):\n\n```sh\nSENTINEL_ENDPOINT=https://sentinel.example.com \\\nSENTINEL_TOKEN=sat_... \\\nnode --import @22hbg/sentinel-node/register app.js\n```\n\n## Example\n\nSee [`examples/basic.mjs`](./examples/basic.mjs):\n\n```sh\npnpm --filter @22hbg/sentinel-node build\nSENTINEL_ENDPOINT=http://localhost:4318 node clients/sdk-node/examples/basic.mjs\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}