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

hana-linter

v1.1.0

Published

Linter for SAP HANA artifacts in an SAP CAP project

Readme

hana-linter

npm version CI License: MIT Node >=14

Naming-convention lint for SAP HANA artifacts in CAP projects.

⚠️ Work in progress. This project is under active development. APIs, configuration options, and supported artifact types may change between releases. See Parser Status for the current state of content extraction support.

NPM packageReport issueReleases

Lint SAP HANA artifact file names and content identifiers in CAP projects using configurable regex-based naming rules.

Why

Teams often rely on naming conventions for HANA artifacts such as tables and views. When these conventions are enforced manually, drift is common and code reviews become noisy.

hana-linter helps you:

  • enforce naming standards consistently
  • catch violations early in local development and CI
  • apply different rules per file extension
  • keep naming policy in version control via a single config file

How It Works

hana-linter reads a .hana-linter.json file and validates artifact file names against rules grouped by extension.

It supports two lint modes:

  • Full scan mode: no file arguments, recursively scans rootDir
  • File-list mode: pass file paths, only those files are validated

Rule groups per extension:

  • groups.all: every rule must match (AND)
  • groups.any: at least one rule must match (OR)

You can define extension: "*" as a shared rule set. Its rules are applied to every file extension and are merged with any extension-specific rule set.

Content-based linting uses Chevrotain-powered lexers and CST parsers to reliably extract identifiers from HANA artifact files. This approach correctly handles block and line comments, multi-line definitions, quoted identifiers, and HANA-specific DDL constructs — without the false positives and false negatives that ad-hoc regex scanning produces.

Parser Status

Work in progress. Not all artifact types have been migrated to the Chevrotain-based parsing infrastructure yet.

| Artifact extension | Content extractor | Status | | ------------------------- | ---------------------- | ---------------------- | | .hdbtable | Chevrotain lexer + CST | ✅ Migrated | | .hdbview | Chevrotain lexer + CST | ✅ Migrated | | .hdbprocedure | Chevrotain lexer + CST | ✅ Migrated | | .hdbfunction | Chevrotain lexer + CST | ✅ Migrated | | .hdbtabletype | — | ❌ Not yet implemented | | .hdbcalculationview | — | ❌ Not yet implemented | | .hdbanalyticalprivilege | — | ❌ Not yet implemented | | .hdbrole | — | ❌ Not yet implemented | | .hdbsequence | — | ❌ Not yet implemented | | .hdbconstraint | — | ❌ Not yet implemented | | .hdbschedulerjob | — | ❌ Not yet implemented | | .hdbindex | — | ❌ Not yet implemented | | .hdbtrigger | — | ❌ Not yet implemented |

  • Not implemented: contentRuleSets targeting these extensions will silently return no results — no identifiers are extracted and no content issues are raised.

Install

Local (recommended for projects)

npm install --save-dev hana-linter

Run with:

npx hana-linter

Global

npm install -g hana-linter

Quick Start

  1. Generate a default config in your project root:
hana-linter init
  1. Run the linter:
hana-linter
  1. If needed, regenerate and overwrite config:
hana-linter init --force

Commands

hana-linter

Run lint using .hana-linter.json from the current working directory.

hana-linter

Lint specific files only:

hana-linter db/src/T_CUSTOMER.hdbtable db/src/V_ACTIVE_USERS.hdbview

Use a custom config path:

hana-linter --config ./config/.hana-linter.json

hana-linter init

Create .hana-linter.json in the current working directory from the bundled default template.

hana-linter init

Overwrite existing config:

hana-linter init --force

Configuration

Create a .hana-linter.json file in your project root.

Configuration Fields

  • rootDir (string): directory to scan in full scan mode
  • ignoredDirectories (string[]): folder names ignored during recursive traversal
  • extensionRuleSets (array): rule definitions grouped by file extension
  • contentRuleSets (optional array): naming rules for identifiers extracted from file contents (for example table fields and procedure/function parameters)

Each extensionRuleSets item contains:

  • extension (string): target extension, for example .hdbtable; use * to target all extensions
  • folderName (optional string): enforce that matching files are located in a folder with this name (at any depth under rootDir)
  • groups.all (optional array): all rules must match
  • groups.any (optional array): at least one rule must match

Each rule contains:

  • description (string): readable rule label for output
  • pattern (string): regex source (without / delimiters)
  • flags (optional string): regex flags, for example i, u, iu

At least one of groups.all or groups.any must be present for each extension.

When folderName is omitted, no folder-location enforcement is applied.

Each contentRuleSets item contains:

  • extension (string): target extension, for example .hdbtable; use * to target all extensions
  • target (string): extracted identifier type to validate; one of field, inputParameter, outputParameter
  • groups.all (optional array): all rules must match
  • groups.any (optional array): at least one rule must match

Supported extractors in this version:

| target | Supported extensions | Extracted identifiers | | ----------------- | -------------------- | ---------------------------------------------- | | field | .hdbtable | Column names | | field | .hdbview | Column aliases (explicit list or AS aliases) | | inputParameter | .hdbprocedure | IN and INOUT parameters | | inputParameter | .hdbfunction | IN parameters (functions accept IN only) | | outputParameter | .hdbprocedure | OUT and INOUT parameters |

Default Config Example

{
    "rootDir": "db",
    "ignoredDirectories": ["node_modules", ".git", "gen"],
    "extensionRuleSets": [
        {
            "extension": "*",
            "groups": {
                "all": [
                    {
                        "description": "Upper snake case only",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    },
                    {
                        "description": "Max length 30",
                        "pattern": "^.{1,30}$",
                        "flags": "u"
                    }
                ]
            }
        },
        {
            "extension": ".hdbtable",
            "folderName": "tables",
            "groups": {
                "any": [
                    {
                        "description": "Prefix T_",
                        "pattern": "^T_.+"
                    },
                    {
                        "description": "Prefix TX_",
                        "pattern": "^TX_.+"
                    }
                ]
            }
        },
        {
            "extension": ".hdbview",
            "groups": {
                "all": [
                    {
                        "description": "Starts with V_",
                        "pattern": "^V_.+"
                    }
                ]
            }
        }
    ],
    "contentRuleSets": [
        {
            "extension": ".hdbtable",
            "target": "field",
            "groups": {
                "all": [
                    {
                        "description": "Field names in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbprocedure",
            "target": "inputParameter",
            "groups": {
                "all": [
                    {
                        "description": "Input parameters prefixed with IP_",
                        "pattern": "^IP_[A-Z0-9_]+$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbprocedure",
            "target": "outputParameter",
            "groups": {
                "all": [
                    {
                        "description": "Output parameters prefixed with OP_",
                        "pattern": "^OP_[A-Z0-9_]+$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbview",
            "target": "field",
            "groups": {
                "all": [
                    {
                        "description": "View column aliases in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        }
    ]
}

Exit Codes

  • 0: lint passed or init completed successfully
  • 1: lint violations found or command failed

This makes the CLI suitable for CI pipelines.

CI Example

name: lint-hana-names
on: [push, pull_request]

jobs:
	hana-lint:
		runs-on: ubuntu-latest
		steps:
			- uses: actions/checkout@v4
			- uses: actions/setup-node@v4
				with:
					node-version: 20
			- run: npm ci
			- run: npx hana-linter

Requirements

  • Node.js >= 14
  • npm >= 7

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

License

MIT