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

@wc-toolkit/cem-validator

v1.3.0

Published

A tool to validate the content of the Custom Elements Manifest to ensure the CEM and components are properly configured.

Downloads

14,291

Readme

workbench with tools, html, css, javascript, and download icon

WC Toolkit - CEM Validator

This tool validates your Custom Elements Manifest to ensure your web components are properly documented and configured for optimal compatibility with IDEs, documentation tools, and component catalogs.

What Does It Validate?

The validator checks two main areas:

  1. Package.json Configuration - Ensures your package is properly configured with correct entry points, module types, and custom elements manifest references
  2. Custom Elements Manifest - Validates that your manifest has proper schema versions, module paths, type definitions, and exports for each component

Installation

To install the package, use the following command:

npm install -D @wc-toolkit/cem-validator

Usage

This package can be used in two ways:

  1. As a standalone script - Run validation programmatically in your build process
  2. As a CEM Analyzer plugin - Automatically validate during manifest generation

Script Usage

Run the validator as part of your build process or as a standalone validation step:

// validate-manifest.ts

import { validateCem, type CemValidatorOptions } from "@wc-toolkit/cem-validator";
import manifest from "./custom-elements.json" with { type: 'json' };

const options: CemValidatorOptions = {
  packageJsonPath: "./package.json",
  cemFileName: "custom-elements.json",
  logErrors: false, // Set to true to log errors instead of throwing an exception
  exclude: ["MyInternalComponent"], // Skip validation for specific components
  rules: { // Override default severity levels for validation
    packageJson: {
      packageType: "off",
      customElementsProperty: "error",
    },
    manifest: {
      tagName: "error",
      exportTypes: "warning",
    }
  }
};

try {
  validateCem(manifest, options);
  console.log("✅ Manifest validation passed!");
} catch (error) {
  console.error("❌ Manifest validation failed:", error);
  process.exit(1);
}

CEM Analyzer Plugin

Integrate validation directly into your manifest generation workflow:

// custom-elements-manifest.config.js

import { cemValidatorPlugin } from "@wc-toolkit/cem-validator";

export default {
  plugins: [
    cemValidatorPlugin({
      logErrors: true, // Log errors without stopping the build
      exclude: ["BaseComponent", "InternalMixin"], // Skip base classes
      rules: { // Override default severity levels for validation
        packageJson: {
          exports: "off",
          customElementsProperty: "error",
        },
        manifest: {
          schemaVersion: "error",
          tagName: "error",
          modulePath: "error",
        }
      }
    })
  ],
};

Then run the analyzer:

npx @custom-elements-manifest/analyzer analyze

Configuration

Options

packageJsonPath

  • Type: string
  • Default: "./package.json"
  • Description: Path to your package.json file. Used to validate package configuration.
{
  packageJsonPath: "./package.json"
}

cemFileName

  • Type: string
  • Default: "custom-elements.json"
  • Description: Name of your Custom Elements Manifest file. Used to verify the manifest is properly referenced in package.json.
{
  cemFileName: "custom-elements.json"
}

logErrors

  • Type: boolean
  • Default: false
  • Description: When true, validation errors are logged to the console instead of throwing exceptions. Useful for CI/CD pipelines where you want to see all errors without stopping the process.
{
  logErrors: true // Logs errors but doesn't throw
}

exclude

  • Type: string[]
  • Default: []
  • Description: Array of component class names to exclude from validation. Useful for base classes, mixins, or internal components that don't need full validation.
{
  exclude: [
    "MyBaseElement",      // Skip base classes
    "InternalMixin",      // Skip mixins
    "DeprecatedComponent" // Skip deprecated components
  ]
}

Example: If you have a base component that other components extend:

// my-base.ts
export class MyBaseElement extends HTMLElement {
  // Base functionality
}

// my-button.ts
export class MyButton extends MyBaseElement {
  // This will be validated
}
// Validation config
{
  exclude: ["MyBaseElement"] // Only validate MyButton, skip MyBaseElement
}

debug

  • Type: boolean
  • Default: false
  • Description: Enables verbose logging during the validation process. Helpful for troubleshooting validation issues.
{
  debug: true // Logs detailed validation steps
}

skip

  • Type: boolean
  • Default: false
  • Description: Completely disables the validator. Useful for conditional execution in different environments.
{
  skip: process.env.NODE_ENV === "development" // Skip validation in dev
}

rules

  • Type: Rules
  • Description: Configure which validations to run and their severity levels. Each rule can be set to "off", "warning", or "error".

Rules Configuration

Rules are organized into two categories: packageJson and manifest.

Package.json Rules

These rules validate your package.json configuration:

packageType
  • Default: "error"
  • Description: Ensures the type field is set to "module" for ESM packages.
{
  rules: {
    packageJson: {
      packageType: "error" // Requires "type": "module" in package.json
    }
  }
}
main
  • Default: "error"
  • Description: Validates the main field points to a valid entry point file.
{
  rules: {
    packageJson: {
      main: "error" // Requires valid "main": "./dist/index.js"
    }
  }
}
module
  • Default: "error"
  • Description: Validates the module field points to a valid ESM entry point.
{
  rules: {
    packageJson: {
      module: "error" // Requires valid "module": "./dist/index.js"
    }
  }
}
types
  • Default: "error"
  • Description: Validates the types field points to a valid TypeScript declaration file.
{
  rules: {
    packageJson: {
      types: "error" // Requires valid "types": "./dist/index.d.ts"
    }
  }
}
exports
  • Default: "error"
  • Description: Validates the package has an exports field properly configured for modern package resolution.
{
  rules: {
    packageJson: {
      exports: "error" // Requires "exports" field in package.json
    }
  }
}
customElementsProperty
  • Default: "error"
  • Description: Validates the customElements field in package.json points to your manifest file.
{
  rules: {
    packageJson: {
      customElementsProperty: "error" // Requires "customElements": "./custom-elements.json"
    }
  }
}
publishedCem
  • Default: "error"
  • Description: Validates that the Custom Elements Manifest is included in the published package (not excluded by .npmignore or files field).
{
  rules: {
    packageJson: {
      publishedCem: "error" // Ensures manifest is published with package
    }
  }
}

Manifest Rules

These rules validate your Custom Elements Manifest:

schemaVersion
  • Default: "error"
  • Description: Validates the manifest uses the latest schema version.
{
  rules: {
    manifest: {
      schemaVersion: "error" // Ensures latest schema version
    }
  }
}
modulePath
  • Default: "error"
  • Description: Validates each component has a valid module path that exists.
{
  rules: {
    manifest: {
      modulePath: "error" // Ensures "./src/my-button.ts" exists
    }
  }
}
definitionPath
  • Default: "error"
  • Description: Validates each component has a valid path to its definition/implementation.
{
  rules: {
    manifest: {
      definitionPath: "error" // Ensures component definition is valid
    }
  }
}
typeDefinitionPath
  • Default: "error"
  • Description: Validates each component has a valid TypeScript declaration file path.
{
  rules: {
    manifest: {
      typeDefinitionPath: "error" // Ensures "./dist/my-button.d.ts" exists
    }
  }
}
exportTypes
  • Default: "error"
  • Description: Validates that all necessary types are exported from the module.
{
  rules: {
    manifest: {
      exportTypes: "warning" // Warns if types aren't exported
    }
  }
}
tagName
  • Default: "error"
  • Description: Validates each custom element has a tag name defined.
{
  rules: {
    manifest: {
      tagName: "error" // Requires <my-button> tag name
    }
  }
}

Complete Configuration Example

Here's a comprehensive example showing all options:

import { validateCem, type CemValidatorOptions } from "@wc-toolkit/cem-validator";
import manifest from "./custom-elements.json" with { type: 'json' };

const options: CemValidatorOptions = {
  // File paths
  packageJsonPath: "./package.json",
  cemFileName: "custom-elements.json",
  
  // Behavior
  logErrors: false,
  debug: false,
  skip: false,
  
  // Exclude specific components
  exclude: [
    "BaseElement",
    "InternalMixin"
  ],
  
  // Rule configuration
  rules: {
    packageJson: {
      packageType: "error",
      main: "error",
      module: "error",
      types: "error",
      exports: "error",
      customElementsProperty: "error",
      publishedCem: "error"
    },
    manifest: {
      schemaVersion: "error",
      modulePath: "error",
      definitionPath: "error",
      typeDefinitionPath: "error",
      exportTypes: "warning",
      tagName: "error"
    }
  }
};

validateCem(manifest, options);

Severity Levels

Each rule supports three severity levels:

  • "off" - Disables the rule completely
  • "warning" - Logs a warning but doesn't fail validation
  • "error" - Fails validation and throws an error (or logs if logErrors: true)
{
  rules: {
    manifest: {
      tagName: "error",        // Fails validation
      exportTypes: "warning",  // Shows warning only
      modulePath: "off"        // Skips this check
    }
  }
}

Type Definitions

type CemValidatorOptions = {
  /** The path to the `package.json` file */
  packageJsonPath?: string;
  /** Custom Elements Manifest file name */
  cemFileName?: string;
  /** This will log errors rather throw an exception */
  logErrors?: boolean;
  /** List of classes to exclude from validation */
  exclude?: string[];
  /** Enables logging during the component loading process */
  debug?: boolean;
  /** Prevents plugin from executing */
  skip?: boolean;
  /** Rule configurations */
  rules?: Rules;
};

/** The severity level for each rule */
type Severity = "off" | "warning" | "error";

type Rules = {
  /** Checks if the package.json file is appropriately configured */
  packageJson?: {
    /** Is `type` property set to "module" */
    packageType?: Severity;
    /** Is `main` property set with a valid file path */
    main?: Severity;
    /** Is `module` property set with a valid file path */
    module?: Severity;
    /** Is `types` property set with a valid file path */
    types?: Severity;
    /** Does the package have a `exports` property configured */
    exports?: Severity;
    /** Is the `customElements` property properly configured */
    customElementsProperty?: Severity;
    /** Is the Custom Elements Manifest included in the published package */
    publishedCem?: Severity;
  };
  /** Checks if the `customElementsManifest` is valid */
  manifest?: {
    /** Is the manifest using the latest schema version */
    schemaVersion?: Severity;
    /** Does the component have a valid module path */
    modulePath?: Severity;
    /** Does the component have a valid definition path */
    definitionPath?: Severity;
    /** Does the element have a valid type definition path */
    typeDefinitionPath?: Severity;
    /** Does the component export all necessary types */
    exportTypes?: Severity;
    /** Does the component have a tag name defined */
    tagName?: Severity;
  };
};

Check out the documentation to see how to configure this to meet your project's needs.