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 🙏

© 2025 – Pkg Stats / Ryan Hefner

voltage-schema

v2.1.1

Published

Self-documenting & type-safe product analytics tracking.

Readme

Voltage provides type-safe vendor agnostic tracking, an auto-doc of analytics data, and AI ready analytics context.

View Documentation

Features

Instead of providing a feature packed tracker, the tracker provided by voltage acts as a type-safe gate-check for events to pass through before being handed off to another analytics tracker (segment / amplitude / posthog).

  • Type-Safe Analytics

    • Robust analytics schema configuration
    • Type-safe tracking generated from schemas
    • Agnostic of destination (works with any analytics vendor)
  • Documentation & Understanding

    • Auto-generated documentation of all analytics data
    • Rich context for events, properties, and dimensions
    • Generates JSON for providing to APIs & AI agents

Installation

npm install voltage-schema

Schema Usage

Schema files for voltage can be initialized by running npm voltage init.

File Extensions

Voltage supports multiple file extensions for schema files:

  • .yaml or .yml - Standard YAML format
  • .json - JSON format

The voltage.config.js file must use the .js extension.

1. Configure Your Analytics Codegen

Codegen Config

| Field | Type | Required | Description | | --- | --- | --- | --- | | events | string | yes | The path to the events file that types & tracking config will be generated from. | | groups | string[] | no | The path to all of the groups file(s) that exist for the events being tracked. If an event is not tracked with a group, then that event should be a part of a codegen config that does not include the group. | | dimensions | string[] | no | The path to all of the dimension file(s) that exist for the events being tracked. If a dimension is identified by a group, then that group must be included in the codegen config with the dimension. | | output | string | yes | The file path to write the generated types & tracking config to. When this file path ends in .ts, typescript types are generated. When it ends in ".js", no types are generated. | | disableComments | boolean | no | By default, event, property, & group descriptions are added as jsDoc style comments on their generated types & tracking configs. | | eventKeyPropertyName | string | no | The name of the property that will be auto-generated to store the event key. Defaults to 'Event Key' if not specified. This property will be added to all events with a defaultValue set to the event's key. |

Create a voltage.config.js file in your project root:

export default {
  generates: [
    {
      events: "./analytics/events/unauthed-events.volt.yaml",
      output: "/__analytics_generated__/unauthed-analytics.ts"
    },
    {
      events: "./analytics/events/authed-events.volt.yaml",
      groups: [
        "./analytics/groups/user-group.volt.yaml",
        "./analytics/groups/team-group.volt.yaml"
      ],
      dimensions: [
        "./analytics/dimensions/user-role-dimensions.volt.yaml",
        "./analytics/dimensions/team-plan-dimensions.volt.yaml"
      ],
      output: "/__analytics_generated__/authed-analytics.ts"
    }
  ]
}

Note - in this example, we are generating types & config for unauthed vs. authed tracking. This is because authed events are sent with the context of the user & the team that they belong to. Whereas when we track unauthed events, this context is unknown.

2. Define Events

Event

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | The name of the event. | | description | string | no | Describe the context of the event. | | dimensions | { included: string[], excluded: string[] } | no | The dimensions that the event exists in. When dimensions are not set, the event will be auto-associated with each dimension. When included, an event only exists in the supplied dimensions. When excluded, an event exists in all dimensions except for the supplied dimensions. | | passthrough | boolean | no | Allow arbitrary properties to be tracked with the event. | | properties | Property[] | no | The properties to track with the event. All properties are required unless marked as optional. Unlisted properties will be disallowed unless passthrough is enabled. |

Property

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | The name of the property. | | description | string | no | Describe the context of the property. | | type | string, string[], boolean, Boolean[], number, number[], oneOf | yes | The expected typescript type for the property value. | | defaultValue | any | no | The static property value to be tracked with the event. | | optional | boolean | no | Mark the property as optional when tracking the event. Note that properties are required by default. |

Create an events.volt.yaml file to define your events:

events:
  page_view:
    name: Page View
    description: Triggered when a user views a page.
    properties:
      - name: Page Name
        description: The name of the page that was viewed.
        type: string

  add_user:
    name: Add User
    description: Triggered when an admin adds a user to their team. This requires a paid plan.
    properties:
      - name: Role
        description: The role of the user that was added.
        type:
          - admin
          - member

3. Define Groups

Group

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | The name of the group. | | description | string | no | Describe the context of the group. | | identifiedBy | string | no | The property that the group is identified by. | | passthrough | boolean | no | Allow arbitrary properties to be set on the group. | | properties | Property[] | no | The properties to set on the group. All properties are required unless marked as optional. Unlisted properties will be disallowed unless passthrough is enabled. |

Property

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | The name of the property. | | description | string | no | Describe the context of the property. | | type | string, string[], boolean, Boolean[], number, number[], oneOf | yes | The expected typescript type for the property value. | | defaultValue | any | no | The static property value to be tracked with the event. | | optional | boolean | no | Mark the property as optional when tracking the event. Note that properties are required by default. |

Create a groups.volt.yaml file to define your groups:

groups:
  - name: User
    description: The user that triggered the event.
    identifiedBy: UserID
    properties:
      - name: UserID
        description: The ID of the user that triggered the event.
        type: number
      - name: Role
        description: The role of the user that triggered the event.
        type:
          - admin
          - member

  - name: Team
    description: The team of the user that triggered the event.
    identifiedBy: TeamID
    properties:
      - name: TeamID
        description: The ID of the team of the user that triggered the event.
        type: number
      - name: Plan
        description: The plan of the team of the user that triggered the event.
        type:
          - FREE
          - TRIAL
          - PAID

4. Dimensions

Dimension

| Field | Type | Required | Description | | --- | --- | --- | --- | | name | string | yes | The name of the dimension. | | description | string | no | Describe the context of the dimension. | | identifiers | DimensionIdentifier[] | yes | The property filters used to identify which users belong in the dimension. |

Dimension Identifier

| Field | Type | Required | Description | | --- | --- | --- | --- | | property | string | yes | The group property to target for identifying the dimension. | | group | string | yes | The group to read the property from for identifying the dimension. | | equals | string, number, boolean | no | Filter for groups where the property matches the given value. | | not | string, number, boolean | no | Filter for groups where the property does not match the given value. | | contains | string | no | Filter for groups where the property contains a string value. | | in | string[], number[], boolean[] | no | Filter for groups where the property is one of the values in the list. | | notIn | string[], number[], boolean[] | no | Filter for groups where the property is not one of the values in the list. | | startsWith | string | no | Filter for groups where the property starts with a given string. | | endsWith | string | no | Filter for groups where the property ends with a given string. | | lt | number | no | Filter for groups where the numeric property value is less than a given numeric value. | | lte | number | no | Filter for groups where the numeric property value is less than or equal to a given numeric value. | | gt | number | no | Filter for groups where the numeric property value is greater than a given numeric value. | | gte | number | no | Filter for groups where the numeric property value is greater than or equal to a given numeric value. |

Create a dimensions.volt.yaml file to define your dimensions:

dimensions:
  - name: Free
    description: Teams without a paid plan.
    identifiers:
      OR:
        - property: Plan
          group: Team
          equals: FREE
        - property: Plan
          group: Team
          equals: TRIAL

  - name: Paid
    description: Teams with a paid plan.
    identifiers:
      AND:
        - property: Plan
          group: Team
          not: FREE
        - property: Plan
          group: Team
          not: TRIAL

Using the tracker

import { AnalyticsSchema, trackingConfig } from './__analytics_generated__/analytics';
import { createAnalyticsTracker } from 'voltage-schema';

// Create a tracker instance
const tracker = createAnalyticsTracker<AnalyticsSchema>(trackingConfig, {
  // Required callback to send events
  onEventTracked: (eventName, eventProperties, groupProperties) => {
    // Send the event to your analytics service
  },
  onGroupUpdated: (groupName, properties) => {
    // Send the group traits to your analytics service
  },
});

// Set group properties
tracker.setProperties('User', {
  UserId: 123,
  Role: 'admin'
});

// Track when a user views a page
tracker.track('page_view', {
  "Page Name": 'Home',
});

5. CLI Commands

# Initialize a new analytics schema
npm voltage init
npm voltage init -- --reset

# Validate your analytics configuration
npm voltage validate

# Generate TypeScript types & tracking config from your codegen config
npm voltage generate

# Concatenate voltage.lock files in a monorepo (run from monorepo root)
npm voltage concat-lock

# List all events and their properties
npm voltage events
npm voltage events -- --include-groups
npm voltage events -- --include-dimensions
npm voltage events -- --verbose

# List all properties and their events
npm voltage properties
npm voltage properties -- --verbose

# List all dimensions and their events
npm voltage dimensions
npm voltage dimensions -- --include-event-details
npm voltage dimensions -- --verbose

Lock Files

Voltage automatically generates a voltage.lock file when you run npm voltage generate. This file contains:

  • Deterministic Versioning: Uses semantic versioning (major.minor) that only increments when schema changes are detected
  • Content Hashing: Ensures reproducible builds by tracking exact schema file contents
  • Source Tracking: Records all schema files, their data, and their relationships
  • Generation Metadata: Stores configuration and output paths for each generation target

The lock file ensures that your generated types and tracking configurations remain consistent across environments and team members.

Monorepo Support

For monorepos with multiple packages containing voltage.lock files, use the concat-lock command:

# Run from your monorepo root
npm voltage concat-lock

This command:

  • Scans all packages for voltage.lock files
  • Validates each package has a corresponding package.json
  • Concatenates all lock files into a single monorepo voltage.lock
  • Uses deterministic versioning that only changes when underlying package lock files change
  • Outputs to the monorepo root for easy integration with CI/CD and external tools

License

MIT