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

@kopexa/krn

v1.0.1

Published

Kopexa Resource Names (KRN) - TypeScript implementation

Readme

@kopexa/krn - Kopexa Resource Names

npm version CI License

A TypeScript package for working with Kopexa Resource Names (KRN), following Google's Resource Name Design.

Installation

npm install @kopexa/krn
# or
pnpm add @kopexa/krn
# or
yarn add @kopexa/krn

KRN Specification

Format

//kopexa.com/{collection}/{resource-id}[/{collection}/{resource-id}][@{version}]
//{service}.kopexa.com/{collection}/{resource-id}[/{collection}/{resource-id}][@{version}]

Components

| Component | Description | Example | |-----------|-------------|---------| | Service | Optional service subdomain | catalog, isms, policy | | Domain | Always kopexa.com | kopexa.com | | Collection | Resource type (plural) | frameworks, controls, tenants | | Resource ID | Unique identifier | iso27001, 5.1.1, acme-corp | | Version | Optional version tag | @v1, @v1.2.3, @latest, @draft |

Examples

//kopexa.com/frameworks/iso27001
//kopexa.com/frameworks/iso27001/controls/5.1.1
//catalog.kopexa.com/frameworks/iso27001
//catalog.kopexa.com/frameworks/iso27001/controls/5.1.1@v2
//isms.kopexa.com/tenants/acme-corp/workspaces/main

Usage

Parsing KRNs

import { KRN } from "@kopexa/krn";

// Parse a KRN string
const k = KRN.parse("//kopexa.com/frameworks/iso27001");

// Parse without throwing (returns null on error)
const k2 = KRN.tryParse("//kopexa.com/frameworks/iso27001");
if (k2) {
  console.log(k2.basename());
}

// Check if a string is a valid KRN
if (KRN.isValid(s)) {
  // ...
}

Building KRNs

import { krn } from "@kopexa/krn";

// Build a simple KRN
const k = krn()
  .resource("frameworks", "iso27001")
  .build();
// Result: //kopexa.com/frameworks/iso27001

// Build a nested KRN with version
const k2 = krn()
  .resource("frameworks", "iso27001")
  .resource("controls", "a-5-1")
  .version("v2")
  .build();
// Result: //kopexa.com/frameworks/iso27001/controls/a-5-1@v2

// Build a KRN with service
const k3 = krn()
  .service("catalog")
  .resource("frameworks", "iso27001")
  .build();
// Result: //catalog.kopexa.com/frameworks/iso27001

// Build without throwing (returns null on error)
const k4 = krn().resource("frameworks", "iso27001").tryBuild();

Creating Child KRNs

const parent = KRN.parse("//kopexa.com/frameworks/iso27001");

// Create a child KRN
const child = parent.child("controls", "a-5-1");
// Result: //kopexa.com/frameworks/iso27001/controls/a-5-1

Extracting Information

const k = KRN.parse("//catalog.kopexa.com/frameworks/iso27001/controls/5.1.1@v1");

k.service;              // "catalog"
k.hasService();         // true
k.fullDomain();         // "catalog.kopexa.com"
k.path();               // "frameworks/iso27001/controls/5.1.1"
k.version;              // "v1"
k.hasVersion();         // true
k.basename();           // "5.1.1"
k.basenameCollection(); // "controls"
k.depth();              // 2

// Get resource ID by collection
const frameworkId = k.resourceId("frameworks"); // "iso27001"
const controlId = k.tryResourceId("controls");  // "5.1.1" or null

// Check if a collection exists
k.hasResource("frameworks"); // true
k.hasResource("policies");   // false

// Get all segments
for (const seg of k.segments()) {
  console.log(`${seg.collection}: ${seg.resourceId}`);
}

Working with Parents

const k = KRN.parse("//kopexa.com/frameworks/iso27001/controls/a-5-1");

const parent = k.parent();
// Result: //kopexa.com/frameworks/iso27001

// Root resources return null
const root = KRN.parse("//kopexa.com/frameworks/iso27001");
root.parent(); // null

Version Manipulation

const k = KRN.parse("//kopexa.com/frameworks/iso27001");

// Add version
const versioned = k.withVersion("v1.2.3");
// Result: //kopexa.com/frameworks/[email protected]

// Remove version
const k2 = KRN.parse("//kopexa.com/frameworks/iso27001@v1");
const unversioned = k2.withoutVersion();
// Result: //kopexa.com/frameworks/iso27001

Service Manipulation

const k = KRN.parse("//kopexa.com/frameworks/iso27001");

// Add service
const withService = k.withService("catalog");
// Result: //catalog.kopexa.com/frameworks/iso27001

// Remove service
const k2 = KRN.parse("//catalog.kopexa.com/frameworks/iso27001");
const withoutService = k2.withoutService();
// Result: //kopexa.com/frameworks/iso27001

Comparison

const k1 = KRN.parse("//kopexa.com/frameworks/iso27001");
const k2 = KRN.parse("//kopexa.com/frameworks/iso27001");

k1.equals(k2);                                       // true
k1.equalsString("//kopexa.com/frameworks/iso27001"); // true

Framework Versioning

Compliance frameworks often have different editions (e.g., ISO 27001:2013 vs ISO 27001:2022). Include the edition year or version number in the framework resource ID:

// ISO 27001:2022
const k1 = KRN.parse("//catalog.kopexa.com/frameworks/iso27001-2022/controls/5.1.1");

// NIST CSF 2.0
const k2 = KRN.parse("//catalog.kopexa.com/frameworks/nist-csf-2.0/controls/GV.OC-01");

// CIS AWS Benchmark v1.4.0
const k3 = KRN.parse("//catalog.kopexa.com/frameworks/cis-aws-1.4.0/controls/1.1.1");

Naming conventions:

  • Use lowercase with hyphens: iso27001-2022, nist-csf-2.0
  • Include the year or version: iso27001-2022, cis-aws-1.4.0
  • Keep it readable: pci-dss-4.0 not pcidssv4.0

Note: The @version suffix (e.g., @v1, @draft) is for versioning the KRN content itself (like draft vs published mappings), not for framework editions.

Utility Functions

import {
  getResource,
  isValidResourceId,
  isValidVersion,
  isValidService,
  safeResourceId
} from "@kopexa/krn";

// Quick resource extraction from string
const id = getResource("//kopexa.com/frameworks/iso27001", "frameworks");
// Result: "iso27001"

// Validate resource IDs
isValidResourceId("valid-id");   // true
isValidResourceId("-invalid");   // false

// Validate versions
isValidVersion("v1.2.3");  // true
isValidVersion("latest");  // true
isValidVersion("invalid"); // false

// Validate service names
isValidService("catalog"); // true
isValidService("Catalog"); // false (must be lowercase)
isValidService("1svc");    // false (can't start with number)

// Convert strings to valid resource IDs
safeResourceId("Hello World!"); // "Hello-World"

Service Name Rules

Service names must follow DNS label rules:

  • Length: 1-63 characters
  • Allowed characters: a-z, 0-9, -
  • Must start with a letter
  • Cannot end with -

Resource ID Rules

Resource IDs must follow these rules:

  • Length: 1-200 characters
  • Allowed characters: a-z, A-Z, 0-9, -, _, .
  • Cannot start or end with - or .

Version Formats

Supported version formats:

  • Semantic: v1, v1.2, v1.2.3
  • Keywords: latest, draft

Error Handling

The package exports a KRNError class with error codes:

import { KRN, KRNError, KRNErrorCode } from "@kopexa/krn";

try {
  const k = KRN.parse(input);
} catch (err) {
  if (err instanceof KRNError) {
    switch (err.code) {
      case KRNErrorCode.EMPTY_KRN:
        // Handle empty input
        break;
      case KRNErrorCode.INVALID_KRN:
        // Handle invalid format
        break;
      case KRNErrorCode.INVALID_DOMAIN:
        // Handle wrong domain
        break;
      case KRNErrorCode.INVALID_RESOURCE_ID:
        // Handle invalid resource ID
        break;
      case KRNErrorCode.INVALID_VERSION:
        // Handle invalid version format
        break;
      case KRNErrorCode.RESOURCE_NOT_FOUND:
        // Handle missing resource
        break;
    }
  }
}

Related Packages

License

Copyright (c) Kopexa GRC

Licensed under the Apache License, Version 2.0. See LICENSE for details.