npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@exellix/narrix-adapter-records

v2.0.0

Published

Records adapter: structured records to CNI v1.1

Readme

@exellix/narrix-adapter-records

Convert structured JSON records (assets, vulnerabilities, tickets, events, etc.) into CNI v1.1. This is the “native” NARRIX adapter: records are normalized into the same CNI shape as text/chat/docs so the pipeline has one canonical input contract.

Installation

npm install @exellix/narrix-adapter-records

Peer / runtime: @exellix/narrix-adapters-core, @exellix/narrix-cni.

Usage

Recommended: use roleMap (and schemaToRoleMap when you have a RecordFieldSchema from e.g. getRecordSchema):

import { recordAdapter, schemaToRoleMap } from "@exellix/narrix-adapter-records";
import type { RecordAdapterInput } from "@exellix/narrix-adapter-records";

const schema = {
  idField: "assetId",
  displayNameField: "hostname",
  factFields: [
    { path: "hostname", factKey: "hostname" },
    { path: "ip", factKey: "ipAddress" },
  ],
  textFields: ["description"],
  refFields: [],
};

const input: RecordAdapterInput = {
  record: {
    assetId: "host-01",
    hostname: "web-01.prod",
    ip: "10.0.1.50",
    description: "Primary web server. See CVE-2023-4567.",
  },
  recordType: "asset",
  roleMap: schemaToRoleMap(schema),
};

const { cni, diagnostics } = recordAdapter.toCni(input);
// cni.subject.id === "host-01"
// cni.facts: hostname, ipAddress (path evidence)
// cni.content: one text item from description (entity extraction)
// cni.references: CVE, IPs, etc. (span + path evidence)

You can still pass schema directly on input (deprecated); it is converted to a role map internally.

Adapter identity

  • adapterId: narrix.adapter.record.v1
  • version: 1.0.0

Input type

| Field | Type | Description | |----------------|-----------------------------|-------------| | record | Record<string, unknown> | Raw JSON record (non-null object). | | recordType | string | e.g. "asset", "vulnerability", "ticket". | | recordId? | string | Stable identifier; used as subject.id when provided. | | roleMap? | RoleMap | Explicit role map (preferred). Use schemaToRoleMap(schema) when you have a RecordFieldSchema. | | collectionId?| string | Used for registry lookup when roleMap is not provided. | | schema? | RecordFieldSchema | Deprecated. Use roleMap: schemaToRoleMap(schema) instead. Still supported. |

Role map / schema shape:

  • idField — dot-path to ID (e.g. "assetId" or "asset.id").
  • displayNameField — dot-path to a human-friendly name.
  • factFields{ path, factKey, required? }[] for facts with path evidence.
  • textFields — dot-paths to free-text fields (normalized, chunked, entity extraction).
  • timestampField — dot-path to a timestamp (ms epoch or ISO string → meta.source.meta.ingestedAt).
  • refFields{ path, kind }[] for cross-references → subject.keys[kind].

Without roleMap (and without a registry or deprecated schema), the adapter auto-extracts top-level primitives as facts (strings > 100 chars are skipped and treated as content) and auto-detects long string fields (up to 3 levels, max 10) as text content.

Options

toCni(input, options?) accepts standard AdapterOptions from @exellix/narrix-adapters-core:

  • chunking — e.g. { maxChunkChars: 4000, overlapChars: 200, strategy: "hard" } for long text fields.
  • limitsmaxInputChars, maxChunks, maxEntities for content and entity extraction.
  • normalization — applied to text fields before chunking and entity extraction.
  • entities — enable/disable and kinds for entity extraction (CVE, IP, hostname, URL, etc.).
  • determinismsortDiagnostics, sortEntities for stable output.

Output

  • CNI v1.1: subject, facts, content, references (extracted entities), signals: [], meta.
  • Subject: type = recordType, id from recordId / role map id / hash, displayName and keys (refs) when a role map is provided.
  • Facts: Path evidence; confidence: 1, meta.source: "record".
  • Content: From role map text (or legacy textFields) or auto-detected long strings; chunked when over maxChunkChars.
  • References: Entities from text (span evidence) and from a full record string scan (path evidence); deduplicated by (kind, value) with merged evidence.

Warning codes

| Code | Meaning | |------|--------| | RECORD_NO_ID | No recordId or idField; subject id is hash of record. | | RECORD_MISSING_REQUIRED_FACT | A required fact path did not resolve. | | RECORD_AUTO_FACT_LIMIT | More than 50 top-level primitives; only first 50 used. | | RECORD_AUTO_TEXT_FIELDS | No textFields; long strings auto-detected (paths in details). | | RECORD_INVALID_TIMESTAMP | timestampField value could not be parsed. | | RECORD_CIRCULAR_REFERENCE | Record has circular references; cannot hash. | | RECORD_TEXT_TRUNCATED | Text exceeded maxInputChars and was truncated. | | RECORD_ENTITY_SCAN_LIMIT | Record entity scan hit depth or string count limit. |

Exports

  • recordAdapterNarrixAdapter<RecordAdapterInput> with toCni(input, options?).
  • schemaToRoleMap(schema) — Convert a RecordFieldSchema to a RoleMap for use as input.roleMap (e.g. when you have a schema from getRecordSchema).
  • getPath(obj, path) — Dot-path resolver (e.g. "a.b[0].c") for use outside the adapter.
  • Types: RecordAdapterInput, RecordAdapterOptions, RecordFieldSchema, FactFieldMapping, RefFieldMapping, RoleMap.
  • Constants: RECORD_ADAPTER_ID, RECORD_ADAPTER_VERSION, AUTO_FACT_MAX_STRING_LENGTH, MAX_AUTO_FACTS, MAX_AUTO_TEXT_FIELDS, and the warning code constants above.

Scripts

  • npm run build — Compile TypeScript to dist/.
  • npm test — Build and run Node test runner (dist/test/adapter.test.js).
  • npm run generate-expected — Build and run R1 fixture through the adapter; prints CNI JSON to stdout.

License

UNLICENSED (see repository).