@elsikora/git-branch-lint 1.0.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.
- package/LICENSE +21 -0
- package/LICENSE.md +21 -0
- package/README.md +154 -0
- package/bin/application/use-cases/get-branch-config-use-case.d.ts +19 -0
- package/bin/application/use-cases/get-current-branch-use-case.d.ts +18 -0
- package/bin/application/use-cases/lint-branch-name-use-case.d.ts +23 -0
- package/bin/domain/entities/branch.d.ts +12 -0
- package/bin/domain/errors/lint-errors.d.ts +30 -0
- package/bin/domain/interfaces/branch-interfaces.d.ts +22 -0
- package/bin/domain/interfaces/repositories/ibranch-repository.d.ts +10 -0
- package/bin/domain/interfaces/repositories/iconfig-repository.d.ts +11 -0
- package/bin/domain/interfaces/repository-interfaces.d.ts +2 -0
- package/bin/domain/repositories/branch-repository.d.ts +11 -0
- package/bin/domain/repositories/config-repository.d.ts +12 -0
- package/bin/index.d.ts +1 -0
- package/bin/index.js +446 -0
- package/bin/index.js.map +1 -0
- package/bin/infrastructure/config/cosmiconfig-repository.d.ts +13 -0
- package/bin/infrastructure/git/git-branch-repository.d.ts +12 -0
- package/bin/presentation/cli/cli-controller.d.ts +30 -0
- package/bin/presentation/cli/formatters/error-formatter.d.ts +11 -0
- package/bin/presentation/cli/formatters/hint-formatter.d.ts +25 -0
- package/package.json +83 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ElsiKora
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Bogdan Kolesnyk (bogdan.kolesnyk@gmail.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://6jft62zmy9nx2oea.public.blob.vercel-storage.com/git-branch-lint-0rauIZprtXnHOrt840ZtTzrUK32erg.png" width="500" alt="project-logo">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Git Branch Lint 🌿</h1>
|
|
6
|
+
<p align="center"><em>Enforce consistent git branch naming conventions across your projects</em></p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a aria-label="ElsiKora logo" href="https://elsikora.com">
|
|
10
|
+
<img src="https://img.shields.io/badge/MADE%20BY%20ElsiKora-333333.svg?style=for-the-badge" alt="ElsiKora">
|
|
11
|
+
</a> <img src="https://img.shields.io/badge/version-blue.svg?style=for-the-badge&logo=npm&logoColor=white" alt="version"> <img src="https://img.shields.io/badge/typescript-blue.svg?style=for-the-badge&logo=typescript&logoColor=white" alt="typescript"> <img src="https://img.shields.io/badge/license-green.svg?style=for-the-badge&logo=license&logoColor=white" alt="license"> <img src="https://img.shields.io/badge/node-green.svg?style=for-the-badge&logo=node.js&logoColor=white" alt="node">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 📚 Table of Contents
|
|
16
|
+
- [Description](#-description)
|
|
17
|
+
- [Features](#-features)
|
|
18
|
+
- [Installation](#-installation)
|
|
19
|
+
- [Usage](#-usage)
|
|
20
|
+
- [Roadmap](#-roadmap)
|
|
21
|
+
- [FAQ](#-faq)
|
|
22
|
+
- [License](#-license)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 📖 Description
|
|
26
|
+
Git Branch Lint is a powerful tool designed to maintain consistent git branch naming conventions in your development workflow. It helps teams enforce standardized branch naming patterns, prevent common naming mistakes, and maintain a clean git history. Built with TypeScript and following clean architecture principles, it provides flexible configuration options and helpful error messages to guide developers in following your team's branch naming conventions.
|
|
27
|
+
|
|
28
|
+
## 🚀 Features
|
|
29
|
+
- ✨ **🔍 Validates branch names against customizable patterns**
|
|
30
|
+
- ✨ **⚡ Fast and lightweight with minimal dependencies**
|
|
31
|
+
- ✨ **🛠 Flexible configuration through multiple formats (JS, JSON, YAML)**
|
|
32
|
+
- ✨ **💡 Helpful error messages with suggestions for fixing invalid names**
|
|
33
|
+
- ✨ **🔒 Prevents usage of prohibited branch names**
|
|
34
|
+
- ✨ **📏 Configurable length restrictions for branch names**
|
|
35
|
+
- ✨ **🎨 Colored CLI output for better readability**
|
|
36
|
+
- ✨ **🔧 Easy integration with git hooks and CI/CD pipelines**
|
|
37
|
+
|
|
38
|
+
## 🛠 Installation
|
|
39
|
+
```bash
|
|
40
|
+
# Using npm
|
|
41
|
+
npm install --save-dev git-branch-lint
|
|
42
|
+
|
|
43
|
+
# Using yarn
|
|
44
|
+
yarn add -D git-branch-lint
|
|
45
|
+
|
|
46
|
+
# Using pnpm
|
|
47
|
+
pnpm add -D git-branch-lint
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 💡 Usage
|
|
51
|
+
## Basic Usage
|
|
52
|
+
|
|
53
|
+
Run the linter directly:
|
|
54
|
+
```bash
|
|
55
|
+
git-branch-lint
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
Create a configuration file `.elsikora/.git-branch-lintrc.json`:
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"pattern": ":type/:name",
|
|
64
|
+
"params": {
|
|
65
|
+
"type": ["feature", "bugfix", "hotfix", "release"],
|
|
66
|
+
"name": ["[a-z0-9-]+"]
|
|
67
|
+
},
|
|
68
|
+
"prohibited": ["master", "main", "develop"],
|
|
69
|
+
"minLength": 5,
|
|
70
|
+
"maxLength": 50
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Git Hooks Integration
|
|
75
|
+
|
|
76
|
+
Add to your `package.json`:
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"husky": {
|
|
80
|
+
"hooks": {
|
|
81
|
+
"pre-commit": "git-branch-lint"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Advanced Usage
|
|
88
|
+
|
|
89
|
+
Custom configuration in JavaScript (`.elsikora/git-branch-lint.config.js`):
|
|
90
|
+
```javascript
|
|
91
|
+
module.exports = {
|
|
92
|
+
pattern: ':type/:scope/:name',
|
|
93
|
+
params: {
|
|
94
|
+
type: ['feature', 'bugfix', 'hotfix'],
|
|
95
|
+
scope: ['api', 'ui', 'core'],
|
|
96
|
+
name: ['[a-z0-9-]+'],
|
|
97
|
+
},
|
|
98
|
+
prohibited: ['wip', 'temp'],
|
|
99
|
+
minLength: 10,
|
|
100
|
+
maxLength: 100
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## CI/CD Integration
|
|
105
|
+
|
|
106
|
+
GitHub Actions example:
|
|
107
|
+
```yaml
|
|
108
|
+
name: Lint Branch Names
|
|
109
|
+
on: [push]
|
|
110
|
+
|
|
111
|
+
jobs:
|
|
112
|
+
lint:
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
steps:
|
|
115
|
+
- uses: actions/checkout@v2
|
|
116
|
+
- uses: actions/setup-node@v2
|
|
117
|
+
- run: npm install
|
|
118
|
+
- run: npx git-branch-lint
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 🛣 Roadmap
|
|
122
|
+
| Task / Feature | Status |
|
|
123
|
+
|---------------|--------|
|
|
124
|
+
| - Add support for custom error messages | 🚧 In Progress |
|
|
125
|
+
| - Implement branch name suggestions when validation fails | 🚧 In Progress |
|
|
126
|
+
| - Add support for regex-based branch name validation | 🚧 In Progress |
|
|
127
|
+
| - Create GitHub Action for easier CI integration | 🚧 In Progress |
|
|
128
|
+
| - Add support for branch name templates | 🚧 In Progress |
|
|
129
|
+
| - Implement branch name statistics and reporting | 🚧 In Progress |
|
|
130
|
+
| (done) 🔍 Validates branch names against customizable patterns | 🚧 In Progress |
|
|
131
|
+
| (done) ⚡ Fast and lightweight with minimal dependencies | 🚧 In Progress |
|
|
132
|
+
| (done) 🛠 Flexible configuration through multiple formats (JS, JSON, YAML) | 🚧 In Progress |
|
|
133
|
+
|
|
134
|
+
## ❓ FAQ
|
|
135
|
+
### Why should I use Git Branch Lint?
|
|
136
|
+
Maintaining consistent branch naming conventions helps teams track work effectively and automate processes like deployment and versioning.
|
|
137
|
+
|
|
138
|
+
### Can I use custom regular expressions?
|
|
139
|
+
Yes, you can define custom regex patterns in the configuration file's `params` section.
|
|
140
|
+
|
|
141
|
+
### How do I skip validation for certain branches?
|
|
142
|
+
You can exclude branches by adding them to the `prohibited` list with a negative pattern.
|
|
143
|
+
|
|
144
|
+
### Does it work with monorepos?
|
|
145
|
+
Yes, you can configure different patterns for different parts of your monorepo using workspace-specific configuration files.
|
|
146
|
+
|
|
147
|
+
## 🔒 License
|
|
148
|
+
This project is licensed under **MIT License
|
|
149
|
+
|
|
150
|
+
Copyright (c) 2025 ElsiKora
|
|
151
|
+
|
|
152
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
153
|
+
|
|
154
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.**.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IBranchConfig } from "../../domain/interfaces/branch-interfaces";
|
|
2
|
+
import type { IConfigRepository } from "../../domain/interfaces/repository-interfaces";
|
|
3
|
+
/**
|
|
4
|
+
* Use case for getting branch configuration
|
|
5
|
+
*/
|
|
6
|
+
export declare class GetBranchConfigUseCase {
|
|
7
|
+
private readonly CONFIG_REPOSITORY;
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
* @param configRepository The configuration repository
|
|
11
|
+
*/
|
|
12
|
+
constructor(configRepository: IConfigRepository);
|
|
13
|
+
/**
|
|
14
|
+
* Execute the use case
|
|
15
|
+
* @param appName The application name
|
|
16
|
+
* @returns The branch configuration
|
|
17
|
+
*/
|
|
18
|
+
execute(appName: string): Promise<IBranchConfig>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TBranchName } from "../../domain/interfaces/branch-interfaces";
|
|
2
|
+
import type { IBranchRepository } from "../../domain/interfaces/repository-interfaces";
|
|
3
|
+
/**
|
|
4
|
+
* Use case for getting the current branch name
|
|
5
|
+
*/
|
|
6
|
+
export declare class GetCurrentBranchUseCase {
|
|
7
|
+
private readonly BRANCH_REPOSITORY;
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
* @param branchRepository The branch repository
|
|
11
|
+
*/
|
|
12
|
+
constructor(branchRepository: IBranchRepository);
|
|
13
|
+
/**
|
|
14
|
+
* Execute the use case
|
|
15
|
+
* @returns The current branch name
|
|
16
|
+
*/
|
|
17
|
+
execute(): Promise<TBranchName>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IBranchConfig, TBranchName } from "../../domain/interfaces/branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Use case for linting a branch name
|
|
4
|
+
*/
|
|
5
|
+
export declare class LintBranchNameUseCase {
|
|
6
|
+
/**
|
|
7
|
+
* Lint a branch name against a configuration
|
|
8
|
+
* @param branchName The branch name to lint
|
|
9
|
+
* @param config The branch configuration
|
|
10
|
+
* @throws {ProhibitedBranchError} When branch name is prohibited
|
|
11
|
+
* @throws {PatternMatchError} When branch name doesn't match pattern
|
|
12
|
+
* @throws {BranchTooShortError} When branch name is shorter than the minimum length
|
|
13
|
+
* @throws {BranchTooLongError} When branch name is longer than the maximum length
|
|
14
|
+
*/
|
|
15
|
+
execute(branchName: TBranchName, config: IBranchConfig): void;
|
|
16
|
+
/**
|
|
17
|
+
* Validate the branch name against the pattern
|
|
18
|
+
* @param branchName The branch name to validate
|
|
19
|
+
* @param config The branch configuration
|
|
20
|
+
* @throws {PatternMatchError} When branch name doesn't match pattern
|
|
21
|
+
*/
|
|
22
|
+
private validatePattern;
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TBranchName } from "../interfaces/branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Domain entity representing a Git branch
|
|
4
|
+
*/
|
|
5
|
+
export declare class Branch {
|
|
6
|
+
private readonly VALUE;
|
|
7
|
+
constructor(name: TBranchName);
|
|
8
|
+
getName(): TBranchName;
|
|
9
|
+
isProhibited(prohibitedNames: ReadonlyArray<string>): boolean;
|
|
10
|
+
isTooLong(maxLength?: number): boolean;
|
|
11
|
+
isTooShort(minLength?: number): boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for branch linting errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class LintError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when branch name is too long
|
|
9
|
+
*/
|
|
10
|
+
export declare class BranchTooLongError extends LintError {
|
|
11
|
+
constructor(branchName: string, maxLength: number);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown when branch name is too short
|
|
15
|
+
*/
|
|
16
|
+
export declare class BranchTooShortError extends LintError {
|
|
17
|
+
constructor(branchName: string, minLength: number);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when branch name doesn't match the pattern
|
|
21
|
+
*/
|
|
22
|
+
export declare class PatternMatchError extends LintError {
|
|
23
|
+
constructor(branchName: string);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when branch name is prohibited
|
|
27
|
+
*/
|
|
28
|
+
export declare class ProhibitedBranchError extends LintError {
|
|
29
|
+
constructor(branchName: string);
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for branch configuration
|
|
3
|
+
*/
|
|
4
|
+
export interface IBranchConfig {
|
|
5
|
+
readonly MAXLENGTH?: number;
|
|
6
|
+
readonly MINLENGTH?: number;
|
|
7
|
+
PARAMS: IBranchParameters;
|
|
8
|
+
readonly PATTERN: string;
|
|
9
|
+
readonly PROHIBITED: ReadonlyArray<string>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Interface for branch parameters
|
|
13
|
+
*/
|
|
14
|
+
export interface IBranchParameters {
|
|
15
|
+
readonly NAME: ReadonlyArray<string>;
|
|
16
|
+
readonly TYPE: ReadonlyArray<string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Type definition for a branch name
|
|
20
|
+
* We explicitly keep this type for semantic clarity
|
|
21
|
+
*/
|
|
22
|
+
export type TBranchName = string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IBranchConfig } from "../branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for configuration operations
|
|
4
|
+
*/
|
|
5
|
+
export interface IConfigRepository {
|
|
6
|
+
/**
|
|
7
|
+
* Get the branch configuration
|
|
8
|
+
* @param appName The name of the application
|
|
9
|
+
*/
|
|
10
|
+
getConfig(appName: string): Promise<IBranchConfig>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TBranchName } from "../interfaces/branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for branch operations
|
|
4
|
+
* @deprecated Use IBranchRepository instead
|
|
5
|
+
*/
|
|
6
|
+
export interface BranchRepository {
|
|
7
|
+
/**
|
|
8
|
+
* Get the current branch name
|
|
9
|
+
*/
|
|
10
|
+
getCurrentBranchName(): Promise<TBranchName>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IBranchConfig } from "../interfaces/branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for configuration operations
|
|
4
|
+
* @deprecated Use IConfigRepository instead
|
|
5
|
+
*/
|
|
6
|
+
export interface ConfigRepository {
|
|
7
|
+
/**
|
|
8
|
+
* Get the branch configuration
|
|
9
|
+
* @param appName The name of the application
|
|
10
|
+
*/
|
|
11
|
+
getConfig(appName: string): Promise<IBranchConfig>;
|
|
12
|
+
}
|
package/bin/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cosmiconfig } from 'cosmiconfig';
|
|
3
|
+
import { exec } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Use case for getting branch configuration
|
|
9
|
+
*/
|
|
10
|
+
class GetBranchConfigUseCase {
|
|
11
|
+
CONFIG_REPOSITORY;
|
|
12
|
+
/**
|
|
13
|
+
* Constructor
|
|
14
|
+
* @param configRepository The configuration repository
|
|
15
|
+
*/
|
|
16
|
+
constructor(configRepository) {
|
|
17
|
+
this.CONFIG_REPOSITORY = configRepository;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Execute the use case
|
|
21
|
+
* @param appName The application name
|
|
22
|
+
* @returns The branch configuration
|
|
23
|
+
*/
|
|
24
|
+
async execute(appName) {
|
|
25
|
+
return this.CONFIG_REPOSITORY.getConfig(appName);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Use case for getting the current branch name
|
|
31
|
+
*/
|
|
32
|
+
class GetCurrentBranchUseCase {
|
|
33
|
+
BRANCH_REPOSITORY;
|
|
34
|
+
/**
|
|
35
|
+
* Constructor
|
|
36
|
+
* @param branchRepository The branch repository
|
|
37
|
+
*/
|
|
38
|
+
constructor(branchRepository) {
|
|
39
|
+
this.BRANCH_REPOSITORY = branchRepository;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Execute the use case
|
|
43
|
+
* @returns The current branch name
|
|
44
|
+
*/
|
|
45
|
+
async execute() {
|
|
46
|
+
return this.BRANCH_REPOSITORY.getCurrentBranchName();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Domain entity representing a Git branch
|
|
52
|
+
*/
|
|
53
|
+
class Branch {
|
|
54
|
+
VALUE;
|
|
55
|
+
constructor(name) {
|
|
56
|
+
this.VALUE = name;
|
|
57
|
+
}
|
|
58
|
+
getName() {
|
|
59
|
+
return this.VALUE;
|
|
60
|
+
}
|
|
61
|
+
isProhibited(prohibitedNames) {
|
|
62
|
+
return prohibitedNames.includes(this.VALUE);
|
|
63
|
+
}
|
|
64
|
+
isTooLong(maxLength) {
|
|
65
|
+
if (maxLength === undefined) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return this.VALUE.length > maxLength;
|
|
69
|
+
}
|
|
70
|
+
isTooShort(minLength) {
|
|
71
|
+
if (minLength === undefined) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return this.VALUE.length < minLength;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Base error class for branch linting errors
|
|
80
|
+
*/
|
|
81
|
+
class LintError extends Error {
|
|
82
|
+
constructor(message) {
|
|
83
|
+
super(message);
|
|
84
|
+
this.name = "LintError";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Error thrown when branch name is too long
|
|
89
|
+
*/
|
|
90
|
+
class BranchTooLongError extends LintError {
|
|
91
|
+
constructor(branchName, maxLength) {
|
|
92
|
+
// eslint-disable-next-line @elsikora-typescript/restrict-template-expressions
|
|
93
|
+
super(`Branch name "${branchName}" is too long (maximum length: ${maxLength})`);
|
|
94
|
+
this.name = "BranchTooLongError";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Error thrown when branch name is too short
|
|
99
|
+
*/
|
|
100
|
+
class BranchTooShortError extends LintError {
|
|
101
|
+
constructor(branchName, minLength) {
|
|
102
|
+
// eslint-disable-next-line @elsikora-typescript/restrict-template-expressions
|
|
103
|
+
super(`Branch name "${branchName}" is too short (minimum length: ${minLength})`);
|
|
104
|
+
this.name = "BranchTooShortError";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Error thrown when branch name doesn't match the pattern
|
|
109
|
+
*/
|
|
110
|
+
class PatternMatchError extends LintError {
|
|
111
|
+
constructor(branchName) {
|
|
112
|
+
super(`Branch name "${branchName}" doesn't match pattern`);
|
|
113
|
+
this.name = "PatternMatchError";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Error thrown when branch name is prohibited
|
|
118
|
+
*/
|
|
119
|
+
class ProhibitedBranchError extends LintError {
|
|
120
|
+
constructor(branchName) {
|
|
121
|
+
super(`Branch name "${branchName}" is prohibited`);
|
|
122
|
+
this.name = "ProhibitedBranchError";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Use case for linting a branch name
|
|
128
|
+
*/
|
|
129
|
+
class LintBranchNameUseCase {
|
|
130
|
+
/**
|
|
131
|
+
* Lint a branch name against a configuration
|
|
132
|
+
* @param branchName The branch name to lint
|
|
133
|
+
* @param config The branch configuration
|
|
134
|
+
* @throws {ProhibitedBranchError} When branch name is prohibited
|
|
135
|
+
* @throws {PatternMatchError} When branch name doesn't match pattern
|
|
136
|
+
* @throws {BranchTooShortError} When branch name is shorter than the minimum length
|
|
137
|
+
* @throws {BranchTooLongError} When branch name is longer than the maximum length
|
|
138
|
+
*/
|
|
139
|
+
execute(branchName, config) {
|
|
140
|
+
const branch = new Branch(branchName);
|
|
141
|
+
if (branch.isProhibited(config.PROHIBITED)) {
|
|
142
|
+
throw new ProhibitedBranchError(branchName);
|
|
143
|
+
}
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
if (branch.isTooShort(config.MINLENGTH)) {
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
throw new BranchTooShortError(branchName, config.MINLENGTH);
|
|
148
|
+
}
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
if (branch.isTooLong(config.MAXLENGTH)) {
|
|
151
|
+
// @ts-ignore
|
|
152
|
+
throw new BranchTooLongError(branchName, config.MAXLENGTH);
|
|
153
|
+
}
|
|
154
|
+
this.validatePattern(branch.getName(), config);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Validate the branch name against the pattern
|
|
158
|
+
* @param branchName The branch name to validate
|
|
159
|
+
* @param config The branch configuration
|
|
160
|
+
* @throws {PatternMatchError} When branch name doesn't match pattern
|
|
161
|
+
*/
|
|
162
|
+
validatePattern(branchName, config) {
|
|
163
|
+
// Start with original pattern
|
|
164
|
+
let pattern = config.PATTERN;
|
|
165
|
+
// Process each parameter in the configuration
|
|
166
|
+
for (const [key, values] of Object.entries(config.PARAMS)) {
|
|
167
|
+
// Create the placeholder - IMPORTANT: Convert to lowercase to match pattern
|
|
168
|
+
const placeholder = `:${key.toLowerCase()}`;
|
|
169
|
+
const parameterValues = values;
|
|
170
|
+
let replacement = "(";
|
|
171
|
+
for (let index = 0; index < parameterValues.length; index++) {
|
|
172
|
+
const value = parameterValues[index];
|
|
173
|
+
// Add the value to the replacement pattern
|
|
174
|
+
if (value.startsWith("[")) {
|
|
175
|
+
replacement += value;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const escapedValue = value.replaceAll(/[-/\\^$*+?.()|[\]{}]/g, String.raw `\$&`);
|
|
179
|
+
replacement += escapedValue;
|
|
180
|
+
}
|
|
181
|
+
// Add OR separator if not the last value
|
|
182
|
+
if (index < parameterValues.length - 1) {
|
|
183
|
+
replacement += "|";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
replacement += ")";
|
|
187
|
+
// Replace the placeholder in the pattern
|
|
188
|
+
pattern = pattern.replaceAll(new RegExp(placeholder, "g"), replacement);
|
|
189
|
+
}
|
|
190
|
+
// Create the regular expression
|
|
191
|
+
const regexp = new RegExp(`^${pattern}$`);
|
|
192
|
+
// Test the branch name against the pattern
|
|
193
|
+
if (!regexp.test(branchName)) {
|
|
194
|
+
throw new PatternMatchError(branchName);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Default configuration for branch linting
|
|
201
|
+
*/
|
|
202
|
+
const DEFAULT_CONFIG = {
|
|
203
|
+
// eslint-disable-next-line @elsikora-typescript/no-magic-numbers
|
|
204
|
+
MAXLENGTH: 50,
|
|
205
|
+
// eslint-disable-next-line @elsikora-typescript/no-magic-numbers
|
|
206
|
+
MINLENGTH: 5,
|
|
207
|
+
PARAMS: {
|
|
208
|
+
NAME: ["[a-z0-9-]+"],
|
|
209
|
+
TYPE: ["feature", "hotfix", "support", "bugfix", "release"],
|
|
210
|
+
},
|
|
211
|
+
PATTERN: ":type/:name",
|
|
212
|
+
PROHIBITED: ["ci", "wip", "main", "test", "build", "master", "release", "dev", "develop"],
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Cosmiconfig implementation of ConfigRepository
|
|
216
|
+
*/
|
|
217
|
+
class CosmiconfigRepository {
|
|
218
|
+
/**
|
|
219
|
+
* Get the branch configuration
|
|
220
|
+
* @param appName The name of the application
|
|
221
|
+
* @returns A promise that resolves to the branch configuration
|
|
222
|
+
*/
|
|
223
|
+
async getConfig(appName) {
|
|
224
|
+
const configExplorer = cosmiconfig(appName, {
|
|
225
|
+
packageProp: `elsikora.${appName}`,
|
|
226
|
+
searchPlaces: ["package.json", `.elsikora/.${appName}rc`, `.elsikora/.${appName}rc.json`, `.elsikora/.${appName}rc.yaml`, `.elsikora/.${appName}rc.yml`, `.elsikora/.${appName}rc.js`, `.elsikora/.${appName}rc.ts`, `.elsikora/.${appName}rc.mjs`, `.elsikora/.${appName}rc.cjs`, `.elsikora/${appName}.config.js`, `.elsikora/${appName}.config.ts`, `.elsikora/${appName}.config.mjs`, `.elsikora/${appName}.config.cjs`],
|
|
227
|
+
});
|
|
228
|
+
const result = await configExplorer.search();
|
|
229
|
+
if (!result || result.isEmpty) {
|
|
230
|
+
return DEFAULT_CONFIG;
|
|
231
|
+
}
|
|
232
|
+
// Convert the config to match our interfaces
|
|
233
|
+
const providedConfig = result.config;
|
|
234
|
+
const uppercasedConfig = {};
|
|
235
|
+
// Create a new object with uppercase keys instead of modifying the original
|
|
236
|
+
for (const key of Object.keys(providedConfig)) {
|
|
237
|
+
const uppercaseKey = key.toUpperCase();
|
|
238
|
+
const value = providedConfig[key];
|
|
239
|
+
if (Array.isArray(value)) {
|
|
240
|
+
// Preserve arrays
|
|
241
|
+
// eslint-disable-next-line @elsikora-typescript/no-unsafe-assignment
|
|
242
|
+
uppercasedConfig[uppercaseKey] = [...value];
|
|
243
|
+
}
|
|
244
|
+
else if (typeof value === "object" && value !== null) {
|
|
245
|
+
// Handle nested objects
|
|
246
|
+
const nestedObject = {};
|
|
247
|
+
for (const subKey of Object.keys(value)) {
|
|
248
|
+
const subValue = value[subKey];
|
|
249
|
+
if (Array.isArray(subValue)) {
|
|
250
|
+
// Preserve nested arrays
|
|
251
|
+
// eslint-disable-next-line @elsikora-typescript/no-unsafe-assignment
|
|
252
|
+
nestedObject[subKey.toUpperCase()] = [...subValue];
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
nestedObject[subKey.toUpperCase()] = subValue;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
uppercasedConfig[uppercaseKey] = nestedObject;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
// Handle primitive values
|
|
262
|
+
uppercasedConfig[uppercaseKey] = value;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const mergedConfig = {
|
|
266
|
+
...DEFAULT_CONFIG,
|
|
267
|
+
...uppercasedConfig,
|
|
268
|
+
};
|
|
269
|
+
if (uppercasedConfig.PARAMS && DEFAULT_CONFIG.PARAMS) {
|
|
270
|
+
mergedConfig.PARAMS = {
|
|
271
|
+
...DEFAULT_CONFIG.PARAMS,
|
|
272
|
+
...uppercasedConfig.PARAMS,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
return mergedConfig;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const execAsync = promisify(exec);
|
|
280
|
+
/**
|
|
281
|
+
* Git implementation of BranchRepository
|
|
282
|
+
*/
|
|
283
|
+
class GitBranchRepository {
|
|
284
|
+
/**
|
|
285
|
+
* Get the current branch name
|
|
286
|
+
* @returns A promise that resolves to the current branch name
|
|
287
|
+
*/
|
|
288
|
+
async getCurrentBranchName() {
|
|
289
|
+
const command = "git rev-parse --abbrev-ref HEAD";
|
|
290
|
+
const { stdout } = await execAsync(command);
|
|
291
|
+
return stdout.trim();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Format error messages for CLI output
|
|
297
|
+
*/
|
|
298
|
+
class ErrorFormatter {
|
|
299
|
+
/**
|
|
300
|
+
* Format an error message
|
|
301
|
+
* @param message The error message
|
|
302
|
+
* @returns The formatted error message
|
|
303
|
+
*/
|
|
304
|
+
format(message) {
|
|
305
|
+
return chalk.red(`✖ ${message}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Format hint messages for CLI output
|
|
311
|
+
*/
|
|
312
|
+
class HintFormatter {
|
|
313
|
+
/**
|
|
314
|
+
* Format a hint message based on error type and config
|
|
315
|
+
* @param error The error that occurred
|
|
316
|
+
* @param config The branch configuration
|
|
317
|
+
* @returns The formatted hint message
|
|
318
|
+
*/
|
|
319
|
+
format(error, config) {
|
|
320
|
+
let output = "";
|
|
321
|
+
if (error instanceof PatternMatchError) {
|
|
322
|
+
output += this.formatPatternMatchHint(config);
|
|
323
|
+
}
|
|
324
|
+
else if (error instanceof ProhibitedBranchError) {
|
|
325
|
+
output += this.formatProhibitedBranchHint(config);
|
|
326
|
+
}
|
|
327
|
+
return output;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Format a hint for pattern match errors
|
|
331
|
+
* @param config The branch configuration
|
|
332
|
+
* @returns The formatted hint
|
|
333
|
+
*/
|
|
334
|
+
formatPatternMatchHint(config) {
|
|
335
|
+
let output = "";
|
|
336
|
+
output += `${chalk.blue("Expected pattern:")} ${chalk.yellow(config.PATTERN)}\n`;
|
|
337
|
+
// Format the parameters
|
|
338
|
+
for (const [parameterName, parameterValues] of Object.entries(config.PARAMS)) {
|
|
339
|
+
const valuesList = parameterValues.map((value) => chalk.yellow(value)).join(", ");
|
|
340
|
+
output += chalk.blue(`Valid ${parameterName} values:`) + " " + valuesList + "\n";
|
|
341
|
+
}
|
|
342
|
+
return output.trim();
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Format a hint for prohibited branch errors
|
|
346
|
+
* @param config The branch configuration
|
|
347
|
+
* @returns The formatted hint
|
|
348
|
+
*/
|
|
349
|
+
formatProhibitedBranchHint(config) {
|
|
350
|
+
const prohibitedList = config.PROHIBITED.map((name) => chalk.yellow(name)).join(", ");
|
|
351
|
+
return `${chalk.blue("Prohibited branch names:")} ${prohibitedList}`;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Controller for CLI operations
|
|
357
|
+
*/
|
|
358
|
+
class CliController {
|
|
359
|
+
ERROR_FORMATTER;
|
|
360
|
+
GET_BRANCH_CONFIG_USE_CASE;
|
|
361
|
+
GET_CURRENT_BRANCH_USE_CASE;
|
|
362
|
+
HINT_FORMATTER;
|
|
363
|
+
LINT_BRANCH_NAME_USE_CASE;
|
|
364
|
+
/**
|
|
365
|
+
* Constructor
|
|
366
|
+
* @param getBranchConfigUseCase The use case for getting branch configuration
|
|
367
|
+
* @param getCurrentBranchUseCase The use case for getting the current branch
|
|
368
|
+
* @param lintBranchNameUseCase The use case for linting branch names
|
|
369
|
+
*/
|
|
370
|
+
constructor(getBranchConfigUseCase, getCurrentBranchUseCase, lintBranchNameUseCase) {
|
|
371
|
+
this.GET_BRANCH_CONFIG_USE_CASE = getBranchConfigUseCase;
|
|
372
|
+
this.GET_CURRENT_BRANCH_USE_CASE = getCurrentBranchUseCase;
|
|
373
|
+
this.LINT_BRANCH_NAME_USE_CASE = lintBranchNameUseCase;
|
|
374
|
+
this.ERROR_FORMATTER = new ErrorFormatter();
|
|
375
|
+
this.HINT_FORMATTER = new HintFormatter();
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Execute the CLI command
|
|
379
|
+
* @param appName The application name
|
|
380
|
+
*/
|
|
381
|
+
async execute(appName) {
|
|
382
|
+
try {
|
|
383
|
+
const [config, branchName] = await Promise.all([this.GET_BRANCH_CONFIG_USE_CASE.execute(appName), this.GET_CURRENT_BRANCH_USE_CASE.execute()]);
|
|
384
|
+
this.LINT_BRANCH_NAME_USE_CASE.execute(branchName, config);
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
await this.handleError(error);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Handle errors that occur during execution
|
|
392
|
+
* @param error The error that occurred
|
|
393
|
+
*/
|
|
394
|
+
async handleError(error) {
|
|
395
|
+
if (!(error instanceof Error)) {
|
|
396
|
+
console.error(this.ERROR_FORMATTER.format("[LintBranchName] Unhandled error occurred"));
|
|
397
|
+
throw new Error("Unknown error occurred");
|
|
398
|
+
}
|
|
399
|
+
if (error instanceof LintError) {
|
|
400
|
+
try {
|
|
401
|
+
// Get the configuration using the service instead of hardcoded values
|
|
402
|
+
const config = await this.GET_BRANCH_CONFIG_USE_CASE.execute("git-branch-lint");
|
|
403
|
+
console.error(this.ERROR_FORMATTER.format(error.message));
|
|
404
|
+
console.log(this.HINT_FORMATTER.format(error, config));
|
|
405
|
+
// Since this is a CLI tool, it's appropriate to exit the process on validation errors
|
|
406
|
+
// ESLint wants us to throw instead, but this is a CLI application where exit is acceptable
|
|
407
|
+
// eslint-disable-next-line elsikora-node/no-process-exit, @elsikora-unicorn/no-process-exit
|
|
408
|
+
process.exit(1);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
console.error(this.ERROR_FORMATTER.format("Failed to load configuration for error hint"));
|
|
412
|
+
console.error(this.ERROR_FORMATTER.format(error.message));
|
|
413
|
+
// eslint-disable-next-line elsikora-node/no-process-exit, @elsikora-unicorn/no-process-exit
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Application name used for configuration
|
|
423
|
+
*/
|
|
424
|
+
const APP_NAME = "git-branch-lint";
|
|
425
|
+
/**
|
|
426
|
+
* Main function that bootstraps the application
|
|
427
|
+
*/
|
|
428
|
+
const main = async () => {
|
|
429
|
+
// Infrastructure layer
|
|
430
|
+
const configRepository = new CosmiconfigRepository();
|
|
431
|
+
const branchRepository = new GitBranchRepository();
|
|
432
|
+
// Application layer
|
|
433
|
+
const getBranchConfigUseCase = new GetBranchConfigUseCase(configRepository);
|
|
434
|
+
const getCurrentBranchUseCase = new GetCurrentBranchUseCase(branchRepository);
|
|
435
|
+
const lintBranchNameUseCase = new LintBranchNameUseCase();
|
|
436
|
+
// Presentation layer
|
|
437
|
+
const cliController = new CliController(getBranchConfigUseCase, getCurrentBranchUseCase, lintBranchNameUseCase);
|
|
438
|
+
// Execute the application
|
|
439
|
+
await cliController.execute(APP_NAME);
|
|
440
|
+
};
|
|
441
|
+
// Bootstrap the application and handle errors
|
|
442
|
+
main().catch((error) => {
|
|
443
|
+
console.error("[LintBranchName] Unhandled error occurred");
|
|
444
|
+
throw error;
|
|
445
|
+
});
|
|
446
|
+
//# sourceMappingURL=index.js.map
|
package/bin/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/application/use-cases/get-branch-config-use-case.ts","../src/application/use-cases/get-current-branch-use-case.ts","../src/domain/entities/branch.ts","../src/domain/errors/lint-errors.ts","../src/application/use-cases/lint-branch-name-use-case.ts","../src/infrastructure/config/cosmiconfig-repository.ts","../src/infrastructure/git/git-branch-repository.ts","../src/presentation/cli/formatters/error-formatter.ts","../src/presentation/cli/formatters/hint-formatter.ts","../src/presentation/cli/cli-controller.ts","../src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IBranchConfig } from "../../domain/interfaces/branch-interfaces";
|
|
2
|
+
import type { IConfigRepository } from "../../domain/interfaces/repository-interfaces";
|
|
3
|
+
/**
|
|
4
|
+
* Cosmiconfig implementation of ConfigRepository
|
|
5
|
+
*/
|
|
6
|
+
export declare class CosmiconfigRepository implements IConfigRepository {
|
|
7
|
+
/**
|
|
8
|
+
* Get the branch configuration
|
|
9
|
+
* @param appName The name of the application
|
|
10
|
+
* @returns A promise that resolves to the branch configuration
|
|
11
|
+
*/
|
|
12
|
+
getConfig(appName: string): Promise<IBranchConfig>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TBranchName } from "../../domain/interfaces/branch-interfaces";
|
|
2
|
+
import type { IBranchRepository } from "../../domain/interfaces/repository-interfaces";
|
|
3
|
+
/**
|
|
4
|
+
* Git implementation of BranchRepository
|
|
5
|
+
*/
|
|
6
|
+
export declare class GitBranchRepository implements IBranchRepository {
|
|
7
|
+
/**
|
|
8
|
+
* Get the current branch name
|
|
9
|
+
* @returns A promise that resolves to the current branch name
|
|
10
|
+
*/
|
|
11
|
+
getCurrentBranchName(): Promise<TBranchName>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { GetBranchConfigUseCase } from "../../application/use-cases/get-branch-config-use-case";
|
|
2
|
+
import type { GetCurrentBranchUseCase } from "../../application/use-cases/get-current-branch-use-case";
|
|
3
|
+
import type { LintBranchNameUseCase } from "../../application/use-cases/lint-branch-name-use-case";
|
|
4
|
+
/**
|
|
5
|
+
* Controller for CLI operations
|
|
6
|
+
*/
|
|
7
|
+
export declare class CliController {
|
|
8
|
+
private readonly ERROR_FORMATTER;
|
|
9
|
+
private readonly GET_BRANCH_CONFIG_USE_CASE;
|
|
10
|
+
private readonly GET_CURRENT_BRANCH_USE_CASE;
|
|
11
|
+
private readonly HINT_FORMATTER;
|
|
12
|
+
private readonly LINT_BRANCH_NAME_USE_CASE;
|
|
13
|
+
/**
|
|
14
|
+
* Constructor
|
|
15
|
+
* @param getBranchConfigUseCase The use case for getting branch configuration
|
|
16
|
+
* @param getCurrentBranchUseCase The use case for getting the current branch
|
|
17
|
+
* @param lintBranchNameUseCase The use case for linting branch names
|
|
18
|
+
*/
|
|
19
|
+
constructor(getBranchConfigUseCase: GetBranchConfigUseCase, getCurrentBranchUseCase: GetCurrentBranchUseCase, lintBranchNameUseCase: LintBranchNameUseCase);
|
|
20
|
+
/**
|
|
21
|
+
* Execute the CLI command
|
|
22
|
+
* @param appName The application name
|
|
23
|
+
*/
|
|
24
|
+
execute(appName: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Handle errors that occur during execution
|
|
27
|
+
* @param error The error that occurred
|
|
28
|
+
*/
|
|
29
|
+
private handleError;
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IBranchConfig } from "../../../domain/interfaces/branch-interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* Format hint messages for CLI output
|
|
4
|
+
*/
|
|
5
|
+
export declare class HintFormatter {
|
|
6
|
+
/**
|
|
7
|
+
* Format a hint message based on error type and config
|
|
8
|
+
* @param error The error that occurred
|
|
9
|
+
* @param config The branch configuration
|
|
10
|
+
* @returns The formatted hint message
|
|
11
|
+
*/
|
|
12
|
+
format(error: unknown, config: IBranchConfig): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format a hint for pattern match errors
|
|
15
|
+
* @param config The branch configuration
|
|
16
|
+
* @returns The formatted hint
|
|
17
|
+
*/
|
|
18
|
+
private formatPatternMatchHint;
|
|
19
|
+
/**
|
|
20
|
+
* Format a hint for prohibited branch errors
|
|
21
|
+
* @param config The branch configuration
|
|
22
|
+
* @returns The formatted hint
|
|
23
|
+
*/
|
|
24
|
+
private formatProhibitedBranchHint;
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elsikora/git-branch-lint",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Lint your git branch names",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lint",
|
|
7
|
+
"validate",
|
|
8
|
+
"branch",
|
|
9
|
+
"name",
|
|
10
|
+
"git",
|
|
11
|
+
"git-branch",
|
|
12
|
+
"branch-name"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/ElsiKora/Git-Branch-Lint.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "ElsiKora",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "bin/index.js",
|
|
22
|
+
"bin": {
|
|
23
|
+
"branch-name-lint": "./bin/index.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"prebuild": "rimraf dist",
|
|
30
|
+
"build": "npm run prebuild && rollup -c",
|
|
31
|
+
"commit": "cz",
|
|
32
|
+
"format": "prettier --check .",
|
|
33
|
+
"format:fix": "prettier --write .",
|
|
34
|
+
"lint": "eslint ./",
|
|
35
|
+
"lint:all": "npm run lint && npm run lint:types",
|
|
36
|
+
"lint:all:fix": "npm run lint:fix && npm run lint:types:fix",
|
|
37
|
+
"lint:fix": "eslint --fix ./",
|
|
38
|
+
"lint:types": "tsc --noEmit",
|
|
39
|
+
"lint:types:fix": "tsc --noEmit --skipLibCheck",
|
|
40
|
+
"prepare": "husky",
|
|
41
|
+
"release": "semantic-release"
|
|
42
|
+
},
|
|
43
|
+
"config": {
|
|
44
|
+
"commitizen": {
|
|
45
|
+
"path": "@elsikora/commitizen-plugin-commitlint-ai"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"chalk": "^5.4.1",
|
|
50
|
+
"cosmiconfig": "^9.0.0",
|
|
51
|
+
"path-to-regexp": "^8.2.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@commitlint/cli": "^19.7.1",
|
|
55
|
+
"@commitlint/config-conventional": "^19.7.1",
|
|
56
|
+
"@elsikora/commitizen-plugin-commitlint-ai": "^1.0.0",
|
|
57
|
+
"@elsikora/eslint-config": "^3.3.4",
|
|
58
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
59
|
+
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
|
60
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
61
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
62
|
+
"@semantic-release/git": "^10.0.1",
|
|
63
|
+
"@semantic-release/github": "^11.0.1",
|
|
64
|
+
"@semantic-release/npm": "^12.0.1",
|
|
65
|
+
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
66
|
+
"@types/node": "^22.13.8",
|
|
67
|
+
"commitizen": "^4.3.1",
|
|
68
|
+
"conventional-changelog-conventionalcommits": "^8.0.0",
|
|
69
|
+
"eslint": "^9.21.0",
|
|
70
|
+
"eslint-plugin-n": "^17.16.1",
|
|
71
|
+
"husky": "^9.1.7",
|
|
72
|
+
"lint-staged": "^15.4.3",
|
|
73
|
+
"prettier": "^3.5.3",
|
|
74
|
+
"rimraf": "^6.0.1",
|
|
75
|
+
"rollup": "^4.34.9",
|
|
76
|
+
"semantic-release": "^24.2.3",
|
|
77
|
+
"tslib": "^2.8.1",
|
|
78
|
+
"typescript": "^5.7.3"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
}
|
|
83
|
+
}
|