hana-linter 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +173 -18
  3. package/dist/assets/.hana-linter.json +120 -0
  4. package/dist/cli.d.ts +17 -0
  5. package/dist/config.d.ts +16 -0
  6. package/dist/content-lint.d.ts +10 -0
  7. package/dist/content-lint.js +28 -0
  8. package/dist/files.d.ts +12 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/lib.d.ts +13 -0
  11. package/dist/lib.js +17 -0
  12. package/dist/lint.d.ts +10 -0
  13. package/dist/parsers/hdbcalculationview/__tests__/extractCalculationViewOutputs.test.d.ts +1 -0
  14. package/dist/parsers/hdbcalculationview/__tests__/extractCalculationViewOutputs.test.js +305 -0
  15. package/dist/parsers/hdbcalculationview/extractor.d.ts +14 -0
  16. package/dist/parsers/hdbcalculationview/extractor.js +105 -0
  17. package/dist/parsers/hdbcalculationview/index.d.ts +20 -0
  18. package/dist/parsers/hdbcalculationview/index.js +25 -0
  19. package/dist/parsers/hdbfunction/__tests__/extractFunctionParameters.test.d.ts +1 -0
  20. package/dist/parsers/hdbfunction/index.d.ts +23 -0
  21. package/dist/parsers/hdbfunction/lexer.d.ts +58 -0
  22. package/dist/parsers/hdbfunction/parser.d.ts +58 -0
  23. package/dist/parsers/hdbfunction/visitor.d.ts +37 -0
  24. package/dist/parsers/hdbindex/__tests__/extractIndexName.test.d.ts +1 -0
  25. package/dist/parsers/hdbindex/__tests__/extractIndexName.test.js +207 -0
  26. package/dist/parsers/hdbindex/index.d.ts +25 -0
  27. package/dist/parsers/hdbindex/index.js +44 -0
  28. package/dist/parsers/hdbindex/lexer.d.ts +29 -0
  29. package/dist/parsers/hdbindex/lexer.js +109 -0
  30. package/dist/parsers/hdbindex/parser.d.ts +32 -0
  31. package/dist/parsers/hdbindex/parser.js +129 -0
  32. package/dist/parsers/hdbindex/visitor.d.ts +31 -0
  33. package/dist/parsers/hdbindex/visitor.js +58 -0
  34. package/dist/parsers/hdbprocedure/__tests__/extractProcedureParameters.test.d.ts +1 -0
  35. package/dist/parsers/hdbprocedure/index.d.ts +21 -0
  36. package/dist/parsers/hdbprocedure/lexer.d.ts +62 -0
  37. package/dist/parsers/hdbprocedure/parser.d.ts +51 -0
  38. package/dist/parsers/hdbprocedure/visitor.d.ts +33 -0
  39. package/dist/parsers/hdbrole/__tests__/extractRoleNames.test.d.ts +1 -0
  40. package/dist/parsers/hdbrole/__tests__/extractRoleNames.test.js +336 -0
  41. package/dist/parsers/hdbrole/index.d.ts +19 -0
  42. package/dist/parsers/hdbrole/index.js +38 -0
  43. package/dist/parsers/hdbrole/lexer.d.ts +44 -0
  44. package/dist/parsers/hdbrole/lexer.js +151 -0
  45. package/dist/parsers/hdbrole/parser.d.ts +37 -0
  46. package/dist/parsers/hdbrole/parser.js +252 -0
  47. package/dist/parsers/hdbrole/visitor.d.ts +39 -0
  48. package/dist/parsers/hdbrole/visitor.js +143 -0
  49. package/dist/parsers/hdbschedulerjob/__tests__/extractSchedulerJobAction.test.d.ts +1 -0
  50. package/dist/parsers/hdbschedulerjob/__tests__/extractSchedulerJobAction.test.js +243 -0
  51. package/dist/parsers/hdbschedulerjob/index.d.ts +22 -0
  52. package/dist/parsers/hdbschedulerjob/index.js +43 -0
  53. package/dist/parsers/hdbschedulerjob/lexer.d.ts +24 -0
  54. package/dist/parsers/hdbschedulerjob/lexer.js +102 -0
  55. package/dist/parsers/hdbschedulerjob/parser.d.ts +41 -0
  56. package/dist/parsers/hdbschedulerjob/parser.js +129 -0
  57. package/dist/parsers/hdbschedulerjob/visitor.d.ts +35 -0
  58. package/dist/parsers/hdbschedulerjob/visitor.js +53 -0
  59. package/dist/parsers/hdbsequence/__tests__/extractSequenceName.test.d.ts +1 -0
  60. package/dist/parsers/hdbsequence/__tests__/extractSequenceName.test.js +236 -0
  61. package/dist/parsers/hdbsequence/index.d.ts +27 -0
  62. package/dist/parsers/hdbsequence/index.js +46 -0
  63. package/dist/parsers/hdbsequence/lexer.d.ts +60 -0
  64. package/dist/parsers/hdbsequence/lexer.js +203 -0
  65. package/dist/parsers/hdbsequence/parser.d.ts +39 -0
  66. package/dist/parsers/hdbsequence/parser.js +258 -0
  67. package/dist/parsers/hdbsequence/visitor.d.ts +39 -0
  68. package/dist/parsers/hdbsequence/visitor.js +70 -0
  69. package/dist/parsers/hdbtable/__tests__/extractTableColumns.test.d.ts +1 -0
  70. package/dist/parsers/hdbtable/index.d.ts +14 -0
  71. package/dist/parsers/hdbtable/lexer.d.ts +71 -0
  72. package/dist/parsers/hdbtable/parser.d.ts +51 -0
  73. package/dist/parsers/hdbtable/visitor.d.ts +26 -0
  74. package/dist/parsers/hdbtabletype/__tests__/extractTableTypeColumns.test.d.ts +1 -0
  75. package/dist/parsers/hdbtabletype/__tests__/extractTableTypeColumns.test.js +235 -0
  76. package/dist/parsers/hdbtabletype/index.d.ts +18 -0
  77. package/dist/parsers/hdbtabletype/index.js +37 -0
  78. package/dist/parsers/hdbtabletype/lexer.d.ts +39 -0
  79. package/dist/parsers/hdbtabletype/lexer.js +149 -0
  80. package/dist/parsers/hdbtabletype/parser.d.ts +30 -0
  81. package/dist/parsers/hdbtabletype/parser.js +138 -0
  82. package/dist/parsers/hdbtabletype/visitor.d.ts +35 -0
  83. package/dist/parsers/hdbtabletype/visitor.js +66 -0
  84. package/dist/parsers/hdbtrigger/__tests__/extractTriggerName.test.d.ts +1 -0
  85. package/dist/parsers/hdbtrigger/__tests__/extractTriggerName.test.js +344 -0
  86. package/dist/parsers/hdbtrigger/index.d.ts +28 -0
  87. package/dist/parsers/hdbtrigger/index.js +47 -0
  88. package/dist/parsers/hdbtrigger/lexer.d.ts +41 -0
  89. package/dist/parsers/hdbtrigger/lexer.js +145 -0
  90. package/dist/parsers/hdbtrigger/parser.d.ts +51 -0
  91. package/dist/parsers/hdbtrigger/parser.js +298 -0
  92. package/dist/parsers/hdbtrigger/visitor.d.ts +58 -0
  93. package/dist/parsers/hdbtrigger/visitor.js +90 -0
  94. package/dist/parsers/hdbview/__tests__/extractViewColumns.test.d.ts +1 -0
  95. package/dist/parsers/hdbview/index.d.ts +16 -0
  96. package/dist/parsers/hdbview/lexer.d.ts +76 -0
  97. package/dist/parsers/hdbview/parser.d.ts +67 -0
  98. package/dist/parsers/hdbview/visitor.d.ts +39 -0
  99. package/dist/report.d.ts +9 -0
  100. package/dist/types/cli.d.ts +20 -0
  101. package/dist/types/config.d.ts +19 -0
  102. package/dist/types/issues.d.ts +16 -0
  103. package/dist/types/rules.d.ts +131 -0
  104. package/docs/chevrotain-hdbcalculationview-parser/prd.md +323 -0
  105. package/docs/chevrotain-hdbcalculationview-parser/spec.md +770 -0
  106. package/docs/chevrotain-hdbindex-parser/prd.md +321 -0
  107. package/docs/chevrotain-hdbindex-parser/spec.md +840 -0
  108. package/docs/chevrotain-hdbrole-parser/prd.md +271 -0
  109. package/docs/chevrotain-hdbrole-parser/spec.md +897 -0
  110. package/docs/chevrotain-hdbschedulerjob-parser/prd.md +366 -0
  111. package/docs/chevrotain-hdbschedulerjob-parser/spec.md +830 -0
  112. package/docs/chevrotain-hdbsequence-parser/prd.md +251 -0
  113. package/docs/chevrotain-hdbsequence-parser/spec.md +868 -0
  114. package/docs/chevrotain-hdbtabletype-parser/prd.md +219 -0
  115. package/docs/chevrotain-hdbtabletype-parser/spec.md +764 -0
  116. package/docs/chevrotain-hdbtrigger-parser/prd.md +271 -0
  117. package/docs/chevrotain-hdbtrigger-parser/spec.md +1164 -0
  118. package/package.json +5 -3
  119. package/src/assets/.hana-linter.json +120 -0
  120. package/src/content-lint.ts +35 -0
  121. package/src/lib.ts +15 -0
  122. package/src/parsers/hdbcalculationview/__tests__/extractCalculationViewOutputs.test.ts +348 -0
  123. package/src/parsers/hdbcalculationview/extractor.ts +160 -0
  124. package/src/parsers/hdbcalculationview/index.ts +24 -0
  125. package/src/parsers/hdbindex/__tests__/extractIndexName.test.ts +248 -0
  126. package/src/parsers/hdbindex/index.ts +46 -0
  127. package/src/parsers/hdbindex/lexer.ts +122 -0
  128. package/src/parsers/hdbindex/parser.ts +162 -0
  129. package/src/parsers/hdbindex/visitor.ts +66 -0
  130. package/src/parsers/hdbrole/__tests__/extractRoleNames.test.ts +387 -0
  131. package/src/parsers/hdbrole/index.ts +40 -0
  132. package/src/parsers/hdbrole/lexer.ts +166 -0
  133. package/src/parsers/hdbrole/parser.ts +312 -0
  134. package/src/parsers/hdbrole/visitor.ts +161 -0
  135. package/src/parsers/hdbschedulerjob/__tests__/extractSchedulerJobAction.test.ts +278 -0
  136. package/src/parsers/hdbschedulerjob/index.ts +46 -0
  137. package/src/parsers/hdbschedulerjob/lexer.ts +116 -0
  138. package/src/parsers/hdbschedulerjob/parser.ts +139 -0
  139. package/src/parsers/hdbschedulerjob/visitor.ts +57 -0
  140. package/src/parsers/hdbsequence/__tests__/extractSequenceName.test.ts +274 -0
  141. package/src/parsers/hdbsequence/index.ts +48 -0
  142. package/src/parsers/hdbsequence/lexer.ts +219 -0
  143. package/src/parsers/hdbsequence/parser.ts +340 -0
  144. package/src/parsers/hdbsequence/visitor.ts +79 -0
  145. package/src/parsers/hdbtabletype/__tests__/extractTableTypeColumns.test.ts +266 -0
  146. package/src/parsers/hdbtabletype/index.ts +39 -0
  147. package/src/parsers/hdbtabletype/lexer.ts +165 -0
  148. package/src/parsers/hdbtabletype/parser.ts +186 -0
  149. package/src/parsers/hdbtabletype/visitor.ts +74 -0
  150. package/src/parsers/hdbtrigger/__tests__/extractTriggerName.test.ts +408 -0
  151. package/src/parsers/hdbtrigger/index.ts +49 -0
  152. package/src/parsers/hdbtrigger/lexer.ts +159 -0
  153. package/src/parsers/hdbtrigger/parser.ts +361 -0
  154. package/src/parsers/hdbtrigger/visitor.ts +100 -0
  155. package/src/types/issues.ts +11 -1
  156. package/src/types/rules.ts +10 -1
  157. package/tsconfig.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ### 1.3.0
8
+
9
+ - Added Chevrotain-based `.hdbtrigger` parser; content-linting of trigger names is now fully supported
10
+ - The `.hdbtrigger` parser extracts the trigger name from `CREATE TRIGGER … ON …` DDL, handling all HANA timing/event variants (`BEFORE`, `AFTER`, `INSTEAD OF`), `INSERT`, `UPDATE [OF …]`, and `DELETE` events, `REFERENCING` clauses, `FOR EACH ROW|STATEMENT`, `WHEN (…)` clauses, and nested `BEGIN … END` bodies — all without false-positive extractions from body content
11
+ - Trigger names may be schema-qualified (`schema.triggerName`); the parser correctly extracts only the unqualified name
12
+ - Added `triggerName` as a valid `target` in content rule sets (configuration key: `triggerName`)
13
+ - Default config (`.hana-linter.json`) now includes a `triggerName` rule set enforcing uppercase snake case for `.hdbtrigger` files
14
+
15
+ ---
16
+
7
17
  ### 1.1.0
8
18
 
9
19
  - Console output is now grouped by file, then by failed rule, reducing noise when multiple violations exist in the same file
package/README.md CHANGED
@@ -9,7 +9,7 @@ Naming-convention lint for SAP HANA artifacts in CAP projects.
9
9
 
10
10
  > **⚠️ Work in progress.** This project is under active development. APIs, configuration options, and supported artifact types may change between releases. See [Parser Status](#parser-status) for the current state of content extraction support.
11
11
 
12
- [NPM package](https://www.npmjs.com/package/hana-linter) • [Report issue](https://github.com/qualiture/hana-linter/issues) • [Releases](https://github.com/qualiture/hana-linter/releases)
12
+ [NPM package](https://www.npmjs.com/package/hana-linter) • [Report issue](https://github.com/qualiture/hana-linter/issues)
13
13
 
14
14
  Lint SAP HANA artifact file names and content identifiers in CAP projects using configurable regex-based naming rules.
15
15
 
@@ -40,7 +40,7 @@ Rule groups per extension:
40
40
 
41
41
  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.
42
42
 
43
- Content-based linting uses [Chevrotain](https://chevrotain.io)-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.
43
+ 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](https://chevrotain.io)-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](https://github.com/NaturalIntelligence/fast-xml-parser) to navigate the logical model tree — without the false positives and false negatives that ad-hoc regex scanning produces.
44
44
 
45
45
  ## Parser Status
46
46
 
@@ -52,17 +52,18 @@ Content-based linting uses [Chevrotain](https://chevrotain.io)-powered lexers an
52
52
  | `.hdbview` | Chevrotain lexer + CST | ✅ Migrated |
53
53
  | `.hdbprocedure` | Chevrotain lexer + CST | ✅ Migrated |
54
54
  | `.hdbfunction` | Chevrotain lexer + CST | ✅ Migrated |
55
- | `.hdbtabletype` | — | Not yet implemented |
56
- | `.hdbcalculationview` | — | Not yet implemented |
55
+ | `.hdbtabletype` | Chevrotain lexer + CST | ✅ Migrated |
56
+ | `.hdbrole` | Chevrotain lexer + CST | ✅ Migrated |
57
+ | `.hdbcalculationview` | fast-xml-parser (XML) | ✅ Migrated |
57
58
  | `.hdbanalyticalprivilege` | — | ❌ Not yet implemented |
58
- | `.hdbrole` | — | Not yet implemented |
59
- | `.hdbsequence` | — | ❌ Not yet implemented |
59
+ | `.hdbsequence` | Chevrotain lexer + CST | ✅ Migrated |
60
60
  | `.hdbconstraint` | — | ❌ Not yet implemented |
61
- | `.hdbschedulerjob` | — | Not yet implemented |
62
- | `.hdbindex` | — | Not yet implemented |
63
- | `.hdbtrigger` | — | Not yet implemented |
61
+ | `.hdbschedulerjob` | Chevrotain lexer + CST | ✅ Migrated |
62
+ | `.hdbindex` | Chevrotain lexer + CST | ✅ Migrated |
63
+ | `.hdbtrigger` | Chevrotain lexer + CST | ✅ Migrated |
64
64
 
65
- - **Not implemented**: `contentRuleSets` targeting these extensions will silently return no results no identifiers are extracted and no content issues are raised.
65
+ - The regex **file name** validations for all of the above listed extensions **are implemented**.
66
+ - **Not implemented**: `contentRuleSets` targeting `.hdbanalyticalprivilege` or `.hdbconstraint` will silently return no results — no identifiers are extracted and no content issues are raised.
66
67
 
67
68
  ## Install
68
69
 
@@ -171,19 +172,28 @@ When `folderName` is omitted, no folder-location enforcement is applied.
171
172
  Each `contentRuleSets` item contains:
172
173
 
173
174
  - `extension` (string): target extension, for example `.hdbtable`; use `*` to target all extensions
174
- - `target` (string): extracted identifier type to validate; one of `field`, `inputParameter`, `outputParameter`
175
+ - `target` (string): extracted identifier type to validate; one of `field`, `inputParameter`, `outputParameter`, `roleName`, `grantedRoleName`, `sequenceName`, `jobAction`, `indexName`, `triggerName`
175
176
  - `groups.all` (optional array): all rules must match
176
177
  - `groups.any` (optional array): at least one rule must match
177
178
 
178
179
  Supported extractors in this version:
179
180
 
180
- | `target` | Supported extensions | Extracted identifiers |
181
- | ----------------- | -------------------- | ---------------------------------------------- |
182
- | `field` | `.hdbtable` | Column names |
183
- | `field` | `.hdbview` | Column aliases (explicit list or `AS` aliases) |
184
- | `inputParameter` | `.hdbprocedure` | `IN` and `INOUT` parameters |
185
- | `inputParameter` | `.hdbfunction` | `IN` parameters (functions accept `IN` only) |
186
- | `outputParameter` | `.hdbprocedure` | `OUT` and `INOUT` parameters |
181
+ | `target` | Supported extensions | Extracted identifiers |
182
+ | ----------------- | --------------------- | ----------------------------------------------------------------------------- |
183
+ | `field` | `.hdbtable` | Column names |
184
+ | `field` | `.hdbview` | Column aliases (explicit list or `AS` aliases) |
185
+ | `field` | `.hdbtabletype` | Column names |
186
+ | `inputParameter` | `.hdbprocedure` | `IN` and `INOUT` parameters |
187
+ | `inputParameter` | `.hdbfunction` | `IN` parameters (functions accept `IN` only) |
188
+ | `outputParameter` | `.hdbprocedure` | `OUT` and `INOUT` parameters |
189
+ | `roleName` | `.hdbrole` | The role name defined in the file |
190
+ | `grantedRoleName` | `.hdbrole` | Each role listed in `extends roles { ... }` |
191
+ | `field` | `.hdbcalculationview` | Output attributes, calculated attributes, base/calculated/restricted measures |
192
+ | `inputParameter` | `.hdbcalculationview` | Input parameters (`variable[@parameter="true"]`) |
193
+ | `sequenceName` | `.hdbsequence` | The sequence name declared in the file |
194
+ | `jobAction` | `.hdbschedulerjob` | The procedure/function reference in the `action` field |
195
+ | `indexName` | `.hdbindex` | The index name declared in the file |
196
+ | `triggerName` | `.hdbtrigger` | The trigger name declared in the file |
187
197
 
188
198
  ### Default Config Example
189
199
 
@@ -284,6 +294,114 @@ Supported extractors in this version:
284
294
  }
285
295
  ]
286
296
  }
297
+ },
298
+ {
299
+ "extension": ".hdbfunction",
300
+ "target": "inputParameter",
301
+ "groups": {
302
+ "all": [
303
+ {
304
+ "description": "Input parameters prefixed with IP_",
305
+ "pattern": "^IP_[A-Z0-9_]+$"
306
+ }
307
+ ]
308
+ }
309
+ },
310
+ {
311
+ "extension": ".hdbtabletype",
312
+ "target": "field",
313
+ "groups": {
314
+ "all": [
315
+ {
316
+ "description": "Field names in uppercase snake case",
317
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
318
+ }
319
+ ]
320
+ }
321
+ },
322
+ {
323
+ "extension": ".hdbrole",
324
+ "target": "roleName",
325
+ "groups": {
326
+ "all": [
327
+ {
328
+ "description": "Role names prefixed with R_",
329
+ "pattern": "^R_.+"
330
+ }
331
+ ]
332
+ }
333
+ },
334
+ {
335
+ "extension": ".hdbcalculationview",
336
+ "target": "field",
337
+ "groups": {
338
+ "all": [
339
+ {
340
+ "description": "Output column IDs in uppercase snake case",
341
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
342
+ }
343
+ ]
344
+ }
345
+ },
346
+ {
347
+ "extension": ".hdbcalculationview",
348
+ "target": "inputParameter",
349
+ "groups": {
350
+ "all": [
351
+ {
352
+ "description": "Input parameters prefixed with IP_",
353
+ "pattern": "^IP_[A-Z0-9_]+$"
354
+ }
355
+ ]
356
+ }
357
+ },
358
+ {
359
+ "extension": ".hdbsequence",
360
+ "target": "sequenceName",
361
+ "groups": {
362
+ "all": [
363
+ {
364
+ "description": "Sequence names in uppercase snake case",
365
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
366
+ }
367
+ ]
368
+ }
369
+ },
370
+ {
371
+ "extension": ".hdbschedulerjob",
372
+ "target": "jobAction",
373
+ "groups": {
374
+ "all": [
375
+ {
376
+ "description": "Job action must reference a package-qualified procedure (contains ::)",
377
+ "pattern": "::"
378
+ }
379
+ ]
380
+ }
381
+ },
382
+ {
383
+ "extension": ".hdbindex",
384
+ "target": "indexName",
385
+ "groups": {
386
+ "all": [
387
+ {
388
+ "description": "Index names in uppercase snake case",
389
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
390
+ }
391
+ ]
392
+ }
393
+ },
394
+ {
395
+ "extension": ".hdbtrigger",
396
+ "target": "triggerName",
397
+ "groups": {
398
+ "all": [
399
+ {
400
+ "description": "Trigger names in uppercase snake case",
401
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
402
+ }
403
+ ]
404
+ }
287
405
  }
288
406
  ]
289
407
  }
@@ -314,6 +432,43 @@ jobs:
314
432
  - run: npx hana-linter
315
433
  ```
316
434
 
435
+ ## Pre-commit Hook (husky + lint-staged)
436
+
437
+ hana-linter's file-list mode (passing files as arguments) integrates cleanly with [lint-staged](https://github.com/lint-staged/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.
438
+
439
+ **1. Install the tools**
440
+
441
+ ```bash
442
+ npm install --save-dev husky lint-staged
443
+ npx husky init
444
+ ```
445
+
446
+ **2. Configure lint-staged**
447
+
448
+ Add a `lint-staged` key to `package.json`:
449
+
450
+ ```json
451
+ {
452
+ "lint-staged": {
453
+ "*.hdb*": "hana-linter"
454
+ }
455
+ }
456
+ ```
457
+
458
+ 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.
459
+
460
+ **3. Wire the pre-commit hook**
461
+
462
+ Replace the contents of `.husky/pre-commit` with:
463
+
464
+ ```bash
465
+ npx lint-staged
466
+ ```
467
+
468
+ 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.
469
+
470
+ > **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.
471
+
317
472
  ## Requirements
318
473
 
319
474
  - Node.js >= 14
@@ -219,6 +219,126 @@
219
219
  }
220
220
  ]
221
221
  }
222
+ },
223
+ {
224
+ "extension": ".hdbview",
225
+ "target": "field",
226
+ "groups": {
227
+ "all": [
228
+ {
229
+ "description": "View column aliases in uppercase snake case",
230
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
231
+ }
232
+ ]
233
+ }
234
+ },
235
+ {
236
+ "extension": ".hdbfunction",
237
+ "target": "inputParameter",
238
+ "groups": {
239
+ "all": [
240
+ {
241
+ "description": "Input parameters prefixed with IP_",
242
+ "pattern": "^IP_[A-Z0-9_]+$"
243
+ }
244
+ ]
245
+ }
246
+ },
247
+ {
248
+ "extension": ".hdbtabletype",
249
+ "target": "field",
250
+ "groups": {
251
+ "all": [
252
+ {
253
+ "description": "Field names in uppercase snake case",
254
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
255
+ }
256
+ ]
257
+ }
258
+ },
259
+ {
260
+ "extension": ".hdbrole",
261
+ "target": "roleName",
262
+ "groups": {
263
+ "all": [
264
+ {
265
+ "description": "Role names prefixed with R_",
266
+ "pattern": "^R_.+"
267
+ }
268
+ ]
269
+ }
270
+ },
271
+ {
272
+ "extension": ".hdbcalculationview",
273
+ "target": "field",
274
+ "groups": {
275
+ "all": [
276
+ {
277
+ "description": "Output column IDs in uppercase snake case",
278
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
279
+ }
280
+ ]
281
+ }
282
+ },
283
+ {
284
+ "extension": ".hdbcalculationview",
285
+ "target": "inputParameter",
286
+ "groups": {
287
+ "all": [
288
+ {
289
+ "description": "Input parameters prefixed with IP_",
290
+ "pattern": "^IP_[A-Z0-9_]+$"
291
+ }
292
+ ]
293
+ }
294
+ },
295
+ {
296
+ "extension": ".hdbsequence",
297
+ "target": "sequenceName",
298
+ "groups": {
299
+ "all": [
300
+ {
301
+ "description": "Sequence names in uppercase snake case",
302
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
303
+ }
304
+ ]
305
+ }
306
+ },
307
+ {
308
+ "extension": ".hdbschedulerjob",
309
+ "target": "jobAction",
310
+ "groups": {
311
+ "all": [
312
+ {
313
+ "description": "Job action must reference a package-qualified procedure (contains ::)",
314
+ "pattern": "::"
315
+ }
316
+ ]
317
+ }
318
+ },
319
+ {
320
+ "extension": ".hdbindex",
321
+ "target": "indexName",
322
+ "groups": {
323
+ "all": [
324
+ {
325
+ "description": "Index names in uppercase snake case",
326
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
327
+ }
328
+ ]
329
+ }
330
+ },
331
+ {
332
+ "extension": ".hdbtrigger",
333
+ "target": "triggerName",
334
+ "groups": {
335
+ "all": [
336
+ {
337
+ "description": "Trigger names in uppercase snake case",
338
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
339
+ }
340
+ ]
341
+ }
222
342
  }
223
343
  ]
224
344
  }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { CliInput } from './types/cli';
2
+ /**
3
+ * Parse command-line arguments.
4
+ *
5
+ * Supported:
6
+ * - --config <path>
7
+ * - remaining arguments are treated as file paths
8
+ *
9
+ * @returns Parsed CLI input.
10
+ */
11
+ export declare function parseCliInput(): CliInput;
12
+ /**
13
+ * Create .hana-linter.json in current working directory from bundled template.
14
+ *
15
+ * @param force - Overwrite existing file when true.
16
+ */
17
+ export declare function runInit(force: boolean): Promise<void>;
@@ -0,0 +1,16 @@
1
+ import { LintConfig } from './types/config';
2
+ import { JsonLintConfig } from './types/rules';
3
+ /**
4
+ * Read and parse JSON config file.
5
+ *
6
+ * @param configPath - Path to JSON configuration.
7
+ * @returns Parsed JSON config object.
8
+ */
9
+ export declare function readJsonConfig(configPath: string): Promise<JsonLintConfig>;
10
+ /**
11
+ * Convert JSON config into runtime compiled config.
12
+ *
13
+ * @param jsonConfig - Parsed JSON config.
14
+ * @returns Runtime lint config with compiled regex.
15
+ */
16
+ export declare function toLintConfig(jsonConfig: JsonLintConfig): LintConfig;
@@ -0,0 +1,10 @@
1
+ import { LintIssue } from './types/issues';
2
+ import { ContentRuleSet } from './types/rules';
3
+ /**
4
+ * Run content-based naming lint for a file.
5
+ *
6
+ * @param filePath - Candidate file path.
7
+ * @param contentRuleSets - Configured content rule sets.
8
+ * @returns List of content-based lint issues.
9
+ */
10
+ export declare function lintFileContent(filePath: string, contentRuleSets: readonly ContentRuleSet[]): Promise<LintIssue[]>;
@@ -10,6 +10,13 @@ const index_1 = require("./parsers/hdbtable/index");
10
10
  const index_2 = require("./parsers/hdbview/index");
11
11
  const index_3 = require("./parsers/hdbprocedure/index");
12
12
  const index_4 = require("./parsers/hdbfunction/index");
13
+ const index_5 = require("./parsers/hdbtabletype/index");
14
+ const index_6 = require("./parsers/hdbrole/index");
15
+ const index_7 = require("./parsers/hdbcalculationview/index");
16
+ const index_8 = require("./parsers/hdbsequence/index");
17
+ const index_9 = require("./parsers/hdbschedulerjob/index");
18
+ const index_10 = require("./parsers/hdbindex/index");
19
+ const index_11 = require("./parsers/hdbtrigger/index");
13
20
  /**
14
21
  * Run content-based naming lint for a file.
15
22
  *
@@ -58,6 +65,27 @@ function extractSubjects(extension, fileContent) {
58
65
  if (extension === '.hdbfunction') {
59
66
  return (0, index_4.extractFunctionParameters)(fileContent);
60
67
  }
68
+ if (extension === '.hdbtabletype') {
69
+ return (0, index_5.extractTableTypeColumns)(fileContent);
70
+ }
71
+ if (extension === '.hdbrole') {
72
+ return (0, index_6.extractRoleNames)(fileContent);
73
+ }
74
+ if (extension === '.hdbcalculationview') {
75
+ return (0, index_7.extractCalculationViewOutputs)(fileContent);
76
+ }
77
+ if (extension === '.hdbsequence') {
78
+ return (0, index_8.extractSequenceName)(fileContent);
79
+ }
80
+ if (extension === '.hdbschedulerjob') {
81
+ return (0, index_9.extractSchedulerJobAction)(fileContent);
82
+ }
83
+ if (extension === '.hdbindex') {
84
+ return (0, index_10.extractIndexName)(fileContent);
85
+ }
86
+ if (extension === '.hdbtrigger') {
87
+ return (0, index_11.extractTriggerName)(fileContent);
88
+ }
61
89
  return [];
62
90
  }
63
91
  function evaluateAllRules(filePath, extension, subject, rules) {
@@ -0,0 +1,12 @@
1
+ import { CliInput } from './types/cli';
2
+ import { LintConfig } from './types/config';
3
+ /**
4
+ * Resolve files to validate:
5
+ * - If CLI files are provided: use only existing files from that list.
6
+ * - If none are provided: run full scan from rootDir.
7
+ *
8
+ * @param config - Lint configuration.
9
+ * @param cliInput - Parsed CLI input.
10
+ * @returns List of file paths to validate.
11
+ */
12
+ export declare function resolveFilesToValidate(config: LintConfig, cliInput: CliInput): Promise<string[]>;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/lib.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public library API for hana-linter.
3
+ *
4
+ * Import this entry point when using hana-linter programmatically
5
+ * (e.g. from a VS Code extension). The CLI remains available via the
6
+ * `hana-linter` binary.
7
+ */
8
+ export { runLint } from './lint';
9
+ export { lintFileContent } from './content-lint';
10
+ export { readJsonConfig, toLintConfig } from './config';
11
+ export type { LintIssue, ExtractedSubject } from './types/issues';
12
+ export type { LintConfig } from './types/config';
13
+ export type { JsonLintConfig, JsonExtensionRuleSet, JsonContentRuleSet, JsonRuleDefinition, JsonRuleGroup, ContentTarget } from './types/rules';
package/dist/lib.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * Public library API for hana-linter.
4
+ *
5
+ * Import this entry point when using hana-linter programmatically
6
+ * (e.g. from a VS Code extension). The CLI remains available via the
7
+ * `hana-linter` binary.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.toLintConfig = exports.readJsonConfig = exports.lintFileContent = exports.runLint = void 0;
11
+ var lint_1 = require("./lint");
12
+ Object.defineProperty(exports, "runLint", { enumerable: true, get: function () { return lint_1.runLint; } });
13
+ var content_lint_1 = require("./content-lint");
14
+ Object.defineProperty(exports, "lintFileContent", { enumerable: true, get: function () { return content_lint_1.lintFileContent; } });
15
+ var config_1 = require("./config");
16
+ Object.defineProperty(exports, "readJsonConfig", { enumerable: true, get: function () { return config_1.readJsonConfig; } });
17
+ Object.defineProperty(exports, "toLintConfig", { enumerable: true, get: function () { return config_1.toLintConfig; } });
package/dist/lint.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { LintIssue } from './types/issues';
2
+ import { LintConfig } from './types/config';
3
+ /**
4
+ * Run naming lint and return all discovered issues.
5
+ *
6
+ * @param config - Lint configuration.
7
+ * @param filesToValidate - File paths to validate.
8
+ * @returns All naming violations.
9
+ */
10
+ export declare function runLint(config: LintConfig, filesToValidate: readonly string[]): Promise<LintIssue[]>;