CLICLItypeA command you run, rather than a dependency you import.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

hana-linter

A command line that checks the names of the native SAP HANA artifact files in a CAP project, and the identifiers inside them, against regex rules the project keeps in a config file.

Lints the .hdb* files under a CAP project's rootDir against naming rules the project keeps in .hana-linter.json: regex patterns grouped per file extension, as groups.all where every rule must match or groups.any where one is enough, plus an optional folderName that fixes which folder matching files sit in. Content rules reach inside the files for identifiers a parser extracts, such as the columns of a .hdbtable or the input parameters of a .hdbprocedure, read out by Chevrotain lexers for the SQL DDL formats and by fast-xml-parser for the XML of .hdbcalculationview. It either scans rootDir recursively or validates only the file paths it is given, which is the mode the README wires to lint-staged and a husky pre-commit hook, and it exits 1 when it finds violations. Naming is the whole of it: every rule is a regex over a name, and the README marks the project as work in progress, with configuration options and supported artifact types able to change between releases.

Facts

Latestv1.4.0ReleasedLast pushLicenceMIT

Where it sits

Lives in
Provides
LintingCAPLintingcapabilityCatching in the editor what would otherwise be caught at deploy time, or not at all — problems in source code and models and in the project's configuration, found by rules rather than by review.
Flavors
Node.jsJavafrom its runtime

Who is behind it

Robin van het HofRobin van het HofPersonMaintains this
In the atlas: maintains 6, contributes to 3
@qualiture
maintainer

Before choosing this

Conditions

PracticalFunctional boundary

Everything it checks is a name: a file name under rootDir, or an identifier a parser extracted from a file, so a convention that cannot be written as a regex over one name has no rule shape here. Content rules targeting .hdbanalyticalprivilege or .hdbconstraint return no results, which the README states as not yet implemented, so conventions centred on those two artifact types go unchecked.

What it declares

Every artifact

Type
CLI
Origin
Independently maintained
Runtime
build time

As a CLI

Distributed through
does not say

Connections1

Install

npm add hana-linter

Derived from the package name. No recipe recorded; the README has the configuration.

README

quoted from qualiture/hana-linter under MIT, read
qualiture/hana-linter/README.mdOn GitHub

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 package • Report issue

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 purpose-built parsers to reliably extract identifiers from HANA artifact files. SQL DDL artifact types (.hdbtable, .hdbview, .hdbprocedure, .hdbfunction, .hdbtabletype, .hdbrole, .hdbsequence, .hdbindex, .hdbtrigger) use Chevrotain-powered lexers and CST parsers that correctly handle block and line comments, multi-line definitions, quoted identifiers, and HANA-specific DDL constructs. The JSON-like .hdbschedulerjob format is also parsed with Chevrotain, tolerating C-style comments (// and /* … */) and trailing commas that standard JSON.parse() rejects. The XML-based .hdbcalculationview format uses fast-xml-parser to navigate the logical model tree — 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 extensionContent extractorStatus
.hdbtableChevrotain lexer + CST✅ Migrated
.hdbviewChevrotain lexer + CST✅ Migrated
.hdbprocedureChevrotain lexer + CST✅ Migrated
.hdbfunctionChevrotain lexer + CST✅ Migrated
.hdbtabletypeChevrotain lexer + CST✅ Migrated
.hdbroleChevrotain lexer + CST✅ Migrated
.hdbcalculationviewfast-xml-parser (XML)✅ Migrated
.hdbanalyticalprivilege—❌ Not yet implemented
.hdbsequenceChevrotain lexer + CST✅ Migrated
.hdbconstraint—❌ Not yet implemented
.hdbschedulerjobChevrotain lexer + CST✅ Migrated
.hdbindexChevrotain lexer + CST✅ Migrated
.hdbtriggerChevrotain lexer + CST✅ Migrated
  • The regex file name validations for all of the above listed extensions are implemented.
  • Not implemented: contentRuleSets targeting .hdbanalyticalprivilege or .hdbconstraint will silently return no results — no identifiers are extracted and no content issues are raised.

Install

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, roleName, grantedRoleName, sequenceName, jobAction, indexName, triggerName
  • groups.all (optional array): all rules must match
  • groups.any (optional array): at least one rule must match

Supported extractors in this version:

targetSupported extensionsExtracted identifiers
field.hdbtableColumn names
field.hdbviewColumn aliases (explicit list or AS aliases)
field.hdbtabletypeColumn names
inputParameter.hdbprocedureIN and INOUT parameters
inputParameter.hdbfunctionIN parameters (functions accept IN only)
outputParameter.hdbprocedureOUT and INOUT parameters
roleName.hdbroleThe role name defined in the file
grantedRoleName.hdbroleEach role listed in extends roles { ... }
field.hdbcalculationviewOutput attributes, calculated attributes, base/calculated/restricted measures
inputParameter.hdbcalculationviewInput parameters (variable[@parameter="true"])
sequenceName.hdbsequenceThe sequence name declared in the file
jobAction.hdbschedulerjobThe procedure/function reference in the action field
indexName.hdbindexThe index name declared in the file
triggerName.hdbtriggerThe trigger name declared in the file
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]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbfunction",
            "target": "inputParameter",
            "groups": {
                "all": [
                    {
                        "description": "Input parameters prefixed with IP_",
                        "pattern": "^IP_[A-Z0-9_]+$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbtabletype",
            "target": "field",
            "groups": {
                "all": [
                    {
                        "description": "Field names in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbrole",
            "target": "roleName",
            "groups": {
                "all": [
                    {
                        "description": "Role names prefixed with R_",
                        "pattern": "^R_.+"
                    }
                ]
            }
        },
        {
            "extension": ".hdbcalculationview",
            "target": "field",
            "groups": {
                "all": [
                    {
                        "description": "Output column IDs in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbcalculationview",
            "target": "inputParameter",
            "groups": {
                "all": [
                    {
                        "description": "Input parameters prefixed with IP_",
                        "pattern": "^IP_[A-Z0-9_]+$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbsequence",
            "target": "sequenceName",
            "groups": {
                "all": [
                    {
                        "description": "Sequence names in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbschedulerjob",
            "target": "jobAction",
            "groups": {
                "all": [
                    {
                        "description": "Job action must reference a package-qualified procedure (contains ::)",
                        "pattern": "::"
                    }
                ]
            }
        },
        {
            "extension": ".hdbindex",
            "target": "indexName",
            "groups": {
                "all": [
                    {
                        "description": "Index names in uppercase snake case",
                        "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
                    }
                ]
            }
        },
        {
            "extension": ".hdbtrigger",
            "target": "triggerName",
            "groups": {
                "all": [
                    {
                        "description": "Trigger names 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

Pre-commit Hook (husky + lint-staged)

hana-linter's file-list mode (passing files as arguments) integrates cleanly with lint-staged: lint-staged appends each staged file that matches the glob to the command, so only the files you are about to commit are linted.

1. Install the tools

npm install --save-dev husky lint-staged
npx husky init

2. Configure lint-staged

Add a lint-staged key to package.json:

{
    "lint-staged": {
        "*.hdb*": "hana-linter"
    }
}

lint-staged turns this into hana-linter <file1> <file2> … for every staged file that matches the glob, which is exactly the file-list mode hana-linter supports.

3. Wire the pre-commit hook

Replace the contents of .husky/pre-commit with:

npx lint-staged

Now, every git commit will automatically run hana-linter against the staged HANA artifact files. If any naming violations are found, the commit is blocked and the issues are reported in the terminal.

Tip: Add hana-linter to dependencies (not devDependencies) if the linter also runs in production CI, so it is available after a plain npm ci --production install. For pre-commit-only use, devDependencies is fine.

Requirements

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

Contributing

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

License

MIT

MIT, read

History

Latest
4downloads per week, npm
Weekly downloads for hana-linter26 complete calendar weeks from 2026-04-27 to 2026-10-25; the latest total is 4.27 Apr – 3 May: 04 May – 10 May: 011 May – 17 May: 018 May – 24 May: 025 May – 31 May: 01 Jun – 7 Jun: 08 Jun – 14 Jun: 015 Jun – 21 Jun: 1,34322 Jun – 28 Jun: 23029 Jun – 5 Jul: 516 Jul – 12 Jul: 5013 Jul – 19 Jul: 2520 Jul – 26 Jul: 2527 Jul – 2 Aug: 63 Aug – 9 Aug: 2010 Aug – 16 Aug: 5017 Aug – 23 Aug: 1124 Aug – 30 Aug: 1431 Aug – 6 Sept: 117 Sept – 13 Sept: 2514 Sept – 20 Sept: 2521 Sept – 27 Sept: 14928 Sept – 4 Oct: 345 Oct – 11 Oct: 4612 Oct – 18 Oct: 1819 Oct – 25 Oct: 4
Linting
  1. @cbs-consulting/cds-eslintESLint plugin with one consultancy's rules for CDS filesfrom CAP
  2. @cbs-consulting/toolsShared ESLint configuration for SAPUI5 and CAP projectsfrom CAP
  3. ui5plugin-linterCommand-line linter for UI5 classes, XML views and i18n filesfrom UI5
  4. ui5pluginSAPUI5 extension for Visual Studio Codefrom UI5
  5. eslint-plugin-better-cap-configESLint rules flagging deprecated CAP configurationfrom CAP
  6. @sap/eslint-plugin-cdsSAP's ESLint plugin for CDSfrom CAP
  7. @sap-ux/eslint-plugin-fiori-toolsESLint rules for projects the Fiori tools generators producefrom CAP
  8. vscode-ui5-language-assistantVS Code extension for SAPUI5 and OpenUI5 XML views and manifestfrom UI5
  9. @satiroglu/kaevRule-based checker for SAPUI5 and OpenUI5 projectsfrom UI5
  10. @ui5/linterStatic analysis tool for UI5 projectsfrom UI5

Details

Sources4
npm registrydiscovered herechecked
npm registry, hana-linterversion, releases, installschecked
github.com/git+https://github.com/qualiture/hana-linter.gittree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
runtimesbuild-time
latestv1.4.0
first release
releases and cadence11, ~0d median
discovered vianpm registry
first seen in the atlas
ecosystem and domaincap, developer-experience
History in the atlas1
  1. First seen.
For your agent
Ref
artifact:qualiture-hana-linter
JSON
/artifacts/qualiture-hana-linter.json
MCP
Connecting an agent