@apexdevtools/git-ops 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/CHANGELOG.md +5 -0
- package/LICENSE +23 -0
- package/README.md +41 -0
- package/lib/src/FilesChanged/BranchChanges.d.ts +2 -0
- package/lib/src/FilesChanged/BranchChanges.js +50 -0
- package/lib/src/Git/Git.d.ts +27 -0
- package/lib/src/Git/Git.js +104 -0
- package/lib/src/api/IGit.d.ts +5 -0
- package/lib/src/api/IGit.js +5 -0
- package/lib/src/index.d.ts +3 -0
- package/lib/src/index.js +11 -0
- package/lib/test/BranchChanges/BranchChanges.spec.d.ts +1 -0
- package/lib/test/BranchChanges/BranchChanges.spec.js +86 -0
- package/lib/test/FsUtils/RepoManager.d.ts +24 -0
- package/lib/test/FsUtils/RepoManager.js +133 -0
- package/lib/test/Git/Git.spec.d.ts +1 -0
- package/lib/test/Git/Git.spec.js +177 -0
- package/package.json +119 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright (c), FinancialForce.com, inc
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
- Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
- Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
|
11
|
+
and/or other materials provided with the distribution.
|
|
12
|
+
- Neither the name of the FinancialForce.com, inc nor the names of its contributors
|
|
13
|
+
may be used to endorse or promote products derived from this software without
|
|
14
|
+
specific prior written permission.
|
|
15
|
+
|
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
17
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
18
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
19
|
+
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
20
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
21
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
22
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# git-ops
|
|
2
|
+
|
|
3
|
+
Library to do git operations to find changed files in a given git repository.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
To build run
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm install
|
|
11
|
+
pnpm build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Jest unit tests can be run with
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm test
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
**Prerequisite**: The head mus tbe set on the repo otherwise any functions using default branch will fail
|
|
23
|
+
|
|
24
|
+
### Finding changed files
|
|
25
|
+
|
|
26
|
+
Getting changed files using the default branch in that repo given a ref. This find the default branch ion the repo using `git symbolic-ref 'refs/remotes/origin/HEAD'` so the `HEAD` must be set.
|
|
27
|
+
The output of the command is same as running `git diff branchName...ref` combined with `git status`.
|
|
28
|
+
|
|
29
|
+
**Note:** files with the status of deleted (`D`) and ignored (`!`) will not be included in the change set.
|
|
30
|
+
|
|
31
|
+
```TypeScript
|
|
32
|
+
getDefaultBranchDiffByRef(repoRootDir: string, ref: string): Promise<Set<string>>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Getting changed files using the default branch in that repo.
|
|
36
|
+
|
|
37
|
+
This command is same as calling `getDefaultBranchDiffByRef(repoRootDir, 'HEAD')`.
|
|
38
|
+
|
|
39
|
+
```TypeScript
|
|
40
|
+
getDefaultBranchDiff(repoRootDir: string): Promise<Set<string>>
|
|
41
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getDefaultBranchDiffByRef = exports.getDefaultBranchDiff = void 0;
|
|
16
|
+
const Git_1 = require("../Git/Git");
|
|
17
|
+
function getDefaultBranchDiff(dir) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return getDefaultBranchDiffByRef(dir, 'HEAD');
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
exports.getDefaultBranchDiff = getDefaultBranchDiff;
|
|
23
|
+
function getDefaultBranchDiffByRef(dir, ref) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const git = new Git_1.Git(dir);
|
|
26
|
+
return git
|
|
27
|
+
.getDefaultBranchName()
|
|
28
|
+
.then((branchName) => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
return yield getChanges(git, branchName, ref);
|
|
30
|
+
}))
|
|
31
|
+
.catch(er => {
|
|
32
|
+
if (er instanceof Error)
|
|
33
|
+
throw Error(`Failed getting diff: ${er.message}`);
|
|
34
|
+
else
|
|
35
|
+
throw Error('Failed getting diff');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
exports.getDefaultBranchDiffByRef = getDefaultBranchDiffByRef;
|
|
40
|
+
function getChanges(git, branchName, ref) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
const changes = yield Promise.all([
|
|
43
|
+
git.diffRange(branchName, ref),
|
|
44
|
+
git.getLocalChangedAndCreated(),
|
|
45
|
+
]);
|
|
46
|
+
const allChanges = new Set();
|
|
47
|
+
changes.forEach(set => set.forEach(file => allChanges.add(file)));
|
|
48
|
+
return allChanges;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SimpleGit } from 'simple-git';
|
|
2
|
+
import { IGit } from '../api/IGit';
|
|
3
|
+
export declare enum FileStatus {
|
|
4
|
+
Unmodified = " ",
|
|
5
|
+
Modified = "M",
|
|
6
|
+
TypeChanged = "T",
|
|
7
|
+
Added = "A",
|
|
8
|
+
Deleted = "D",
|
|
9
|
+
Renamed = "R",
|
|
10
|
+
Copied = "C",
|
|
11
|
+
Updated = "U",
|
|
12
|
+
Untracked = "?",
|
|
13
|
+
Ignore = "!"
|
|
14
|
+
}
|
|
15
|
+
export declare class Git implements IGit {
|
|
16
|
+
private static MIN_GIT_VERSION_MAJOR;
|
|
17
|
+
private static MIN_GIT_VERSION_MINOR;
|
|
18
|
+
private static MIN_GIT_VERSION_PATCH;
|
|
19
|
+
private static gitInstance;
|
|
20
|
+
private dir;
|
|
21
|
+
constructor(dir: string);
|
|
22
|
+
static versionCheck(git: SimpleGit): Promise<void>;
|
|
23
|
+
private get git();
|
|
24
|
+
getDefaultBranchName(): Promise<string>;
|
|
25
|
+
diffRange(fromRef: string, toRef: string): Promise<Set<string>>;
|
|
26
|
+
getLocalChangedAndCreated(): Promise<Set<string>>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2022, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.Git = exports.FileStatus = void 0;
|
|
16
|
+
const simple_git_1 = require("simple-git");
|
|
17
|
+
var FileStatus;
|
|
18
|
+
(function (FileStatus) {
|
|
19
|
+
FileStatus["Unmodified"] = " ";
|
|
20
|
+
FileStatus["Modified"] = "M";
|
|
21
|
+
FileStatus["TypeChanged"] = "T";
|
|
22
|
+
FileStatus["Added"] = "A";
|
|
23
|
+
FileStatus["Deleted"] = "D";
|
|
24
|
+
FileStatus["Renamed"] = "R";
|
|
25
|
+
FileStatus["Copied"] = "C";
|
|
26
|
+
FileStatus["Updated"] = "U";
|
|
27
|
+
FileStatus["Untracked"] = "?";
|
|
28
|
+
FileStatus["Ignore"] = "!";
|
|
29
|
+
})(FileStatus = exports.FileStatus || (exports.FileStatus = {}));
|
|
30
|
+
class Git {
|
|
31
|
+
constructor(dir) {
|
|
32
|
+
this.dir = dir;
|
|
33
|
+
}
|
|
34
|
+
static versionCheck(git) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const version = yield git.version();
|
|
37
|
+
const isSupported = version.major >= this.MIN_GIT_VERSION_MAJOR &&
|
|
38
|
+
version.minor >= this.MIN_GIT_VERSION_MINOR &&
|
|
39
|
+
version.patch >= this.MIN_GIT_VERSION_PATCH;
|
|
40
|
+
if (!isSupported)
|
|
41
|
+
throw new Error(`Unsupported version of git. Min version must be ${this.MIN_GIT_VERSION_MAJOR}.${this.MIN_GIT_VERSION_MINOR}.${this.MIN_GIT_VERSION_PATCH}`);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
get git() {
|
|
45
|
+
if (Git.gitInstance)
|
|
46
|
+
return Promise.resolve(Git.gitInstance);
|
|
47
|
+
//eslint-disable-next-line
|
|
48
|
+
const git = (0, simple_git_1.simpleGit)(this.dir);
|
|
49
|
+
return Git.versionCheck(git).then(() => {
|
|
50
|
+
Git.gitInstance = git;
|
|
51
|
+
return git;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
getDefaultBranchName() {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
return this.git
|
|
57
|
+
.then(git => git.raw(['symbolic-ref', 'refs/remotes/origin/HEAD', '--short']))
|
|
58
|
+
.catch(error => {
|
|
59
|
+
if (error instanceof Error)
|
|
60
|
+
throw Error(`Failed to find symbolic ref no remote HEAD with message: '${error.message.trim()}'`);
|
|
61
|
+
else
|
|
62
|
+
throw new Error('Failed to find symbolic ref no remote HEAD');
|
|
63
|
+
})
|
|
64
|
+
.then(branch => {
|
|
65
|
+
if (branch.startsWith('origin/'))
|
|
66
|
+
return branch.trim();
|
|
67
|
+
else
|
|
68
|
+
throw new Error(`Expected default branch '${branch}' to start with 'origin/'`);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
diffRange(fromRef, toRef) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
return this.git
|
|
75
|
+
.then(git => git.diff([`${fromRef}...${toRef}`, '--name-only', '-z']))
|
|
76
|
+
.then(diff => {
|
|
77
|
+
const files = diff
|
|
78
|
+
.split('\u0000')
|
|
79
|
+
.map(s => s.trim())
|
|
80
|
+
.filter(s => s); //Removes any falsy values
|
|
81
|
+
return new Set([...files]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
getLocalChangedAndCreated() {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const excludeStatus = [FileStatus.Deleted, FileStatus.Ignore];
|
|
88
|
+
return this.git
|
|
89
|
+
.then(git => git.status())
|
|
90
|
+
.then(status => {
|
|
91
|
+
const changedFiles = status.files
|
|
92
|
+
.filter(f => !excludeStatus.includes(f.index) &&
|
|
93
|
+
!excludeStatus.includes(f.working_dir))
|
|
94
|
+
.map(f => f.path);
|
|
95
|
+
return new Set(...[changedFiles]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.Git = Git;
|
|
101
|
+
Git.MIN_GIT_VERSION_MAJOR = 2;
|
|
102
|
+
Git.MIN_GIT_VERSION_MINOR = 37;
|
|
103
|
+
Git.MIN_GIT_VERSION_PATCH = 0;
|
|
104
|
+
Git.gitInstance = undefined;
|
package/lib/src/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Git = exports.getDefaultBranchDiffByRef = exports.getDefaultBranchDiff = void 0;
|
|
7
|
+
var BranchChanges_1 = require("./FilesChanged/BranchChanges");
|
|
8
|
+
Object.defineProperty(exports, "getDefaultBranchDiff", { enumerable: true, get: function () { return BranchChanges_1.getDefaultBranchDiff; } });
|
|
9
|
+
Object.defineProperty(exports, "getDefaultBranchDiffByRef", { enumerable: true, get: function () { return BranchChanges_1.getDefaultBranchDiffByRef; } });
|
|
10
|
+
var Git_1 = require("./Git/Git");
|
|
11
|
+
Object.defineProperty(exports, "Git", { enumerable: true, get: function () { return Git_1.Git; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const Git_1 = require("../../src/Git/Git");
|
|
16
|
+
const BranchChanges_1 = require("../../src/FilesChanged/BranchChanges");
|
|
17
|
+
const mockGitImpl = {
|
|
18
|
+
getDefaultBranchName: jest.fn(),
|
|
19
|
+
getLocalChangedAndCreated: jest.fn(),
|
|
20
|
+
diffRange: jest.fn(),
|
|
21
|
+
};
|
|
22
|
+
jest.mock('../../src/Git/Git', () => {
|
|
23
|
+
return {
|
|
24
|
+
Git: jest.fn().mockImplementation(() => mockGitImpl),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
const mockedGit = jest.mocked(Git_1.Git, { shallow: true });
|
|
28
|
+
describe('Branch changes', () => {
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
describe('getDefaultBranchDiffByRef', () => {
|
|
33
|
+
it('returns the correct set of files when git ops resolve', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
//Given
|
|
35
|
+
mockGitImpl.getDefaultBranchName.mockResolvedValue('default/branch/name');
|
|
36
|
+
mockGitImpl.diffRange.mockResolvedValue(new Set(['File.txt', 'AnotherClass.txt']));
|
|
37
|
+
mockGitImpl.getLocalChangedAndCreated.mockResolvedValue(new Set(['SomeFile.txt']));
|
|
38
|
+
//When
|
|
39
|
+
const res = yield (0, BranchChanges_1.getDefaultBranchDiffByRef)('./some/path/to/dir', 'abc12fcd');
|
|
40
|
+
//Then
|
|
41
|
+
expect(mockedGit).toHaveBeenCalledWith('./some/path/to/dir');
|
|
42
|
+
expect(mockGitImpl.getDefaultBranchName).toBeCalledTimes(1);
|
|
43
|
+
expect(mockGitImpl.getLocalChangedAndCreated).toBeCalledTimes(1);
|
|
44
|
+
expect(mockGitImpl.diffRange).toHaveBeenCalledWith('default/branch/name', 'abc12fcd');
|
|
45
|
+
expect(res).toEqual(new Set(['File.txt', 'AnotherClass.txt', 'SomeFile.txt']));
|
|
46
|
+
}));
|
|
47
|
+
it('rejects and throws error when "getDefaultBranchName" fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
//Given
|
|
49
|
+
mockGitImpl.getDefaultBranchName.mockRejectedValue(Error('no head ref error'));
|
|
50
|
+
//When/Then
|
|
51
|
+
yield expect((0, BranchChanges_1.getDefaultBranchDiffByRef)('./some/path/to/dir', 'abc12fcd')).rejects.toEqual(Error('Failed getting diff: no head ref error'));
|
|
52
|
+
}));
|
|
53
|
+
it('rejects and throws error when "getLocalChangedAndCreated" fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
//Given
|
|
55
|
+
mockGitImpl.getDefaultBranchName.mockResolvedValue('default/branch/name');
|
|
56
|
+
mockGitImpl.diffRange.mockResolvedValue(new Set(['File.txt', 'AnotherClass.txt']));
|
|
57
|
+
mockGitImpl.getLocalChangedAndCreated.mockRejectedValue(Error('op failed'));
|
|
58
|
+
//When/Then
|
|
59
|
+
yield expect((0, BranchChanges_1.getDefaultBranchDiffByRef)('./some/path/to/dir', 'abc12fcd')).rejects.toEqual(Error('Failed getting diff: op failed'));
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
describe('getDefaultBranchDiff', () => {
|
|
63
|
+
it('returns the correct set of files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
//Given
|
|
65
|
+
mockGitImpl.getDefaultBranchName.mockResolvedValue('default/branch/name');
|
|
66
|
+
mockGitImpl.diffRange.mockResolvedValue(new Set(['File.txt', 'AnotherClass.txt']));
|
|
67
|
+
mockGitImpl.getLocalChangedAndCreated.mockResolvedValue(new Set(['SomeFile.txt']));
|
|
68
|
+
//When
|
|
69
|
+
const res = yield (0, BranchChanges_1.getDefaultBranchDiff)('./some/path/to/dir');
|
|
70
|
+
//Then
|
|
71
|
+
expect(mockedGit).toHaveBeenCalledWith('./some/path/to/dir');
|
|
72
|
+
expect(mockGitImpl.getDefaultBranchName).toBeCalledTimes(1);
|
|
73
|
+
expect(mockGitImpl.getLocalChangedAndCreated).toBeCalledTimes(1);
|
|
74
|
+
expect(mockGitImpl.diffRange).toHaveBeenCalledWith('default/branch/name', 'HEAD');
|
|
75
|
+
expect(res).toEqual(new Set(['File.txt', 'AnotherClass.txt', 'SomeFile.txt']));
|
|
76
|
+
}));
|
|
77
|
+
it('rejects and throws error when "getLocalChangedAndCreated" fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
|
+
//Given
|
|
79
|
+
mockGitImpl.getDefaultBranchName.mockResolvedValue('default/branch/name');
|
|
80
|
+
mockGitImpl.diffRange.mockResolvedValue(new Set(['File.txt', 'AnotherClass.txt']));
|
|
81
|
+
mockGitImpl.getLocalChangedAndCreated.mockRejectedValue(Error('op failed'));
|
|
82
|
+
//When/Then
|
|
83
|
+
yield expect((0, BranchChanges_1.getDefaultBranchDiff)('./some/path/to/dir')).rejects.toEqual(Error('Failed getting diff: op failed'));
|
|
84
|
+
}));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class RepoManager {
|
|
2
|
+
private isInit;
|
|
3
|
+
private rootDir;
|
|
4
|
+
private remoteRepoDir;
|
|
5
|
+
private testRepoDir;
|
|
6
|
+
private static instances;
|
|
7
|
+
private constructor();
|
|
8
|
+
static getInstance(rootDir: string): RepoManager;
|
|
9
|
+
private get git();
|
|
10
|
+
private initRemoteRepo;
|
|
11
|
+
private cloneRepo;
|
|
12
|
+
get repoDir(): string;
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
setHead(): Promise<string | void>;
|
|
15
|
+
push(): Promise<void | import("simple-git").PushResult>;
|
|
16
|
+
checkout(branchName: string, from: string): Promise<void>;
|
|
17
|
+
stageAll(files?: string[]): Promise<string>;
|
|
18
|
+
getGitLog(): Promise<readonly (import("simple-git").DefaultLogFields & import("simple-git").ListLogLine)[]>;
|
|
19
|
+
stageAndCommitAll(files?: string[]): Promise<import("simple-git").CommitResult>;
|
|
20
|
+
tearDown(): Promise<void>;
|
|
21
|
+
createOrUpdateFile(fileName: string, content: string): Promise<void>;
|
|
22
|
+
rmFile(file: string): void;
|
|
23
|
+
renameFileInRepo(from: string, to: string): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.RepoManager = void 0;
|
|
19
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
20
|
+
const fs_1 = __importDefault(require("fs"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
class RepoManager {
|
|
23
|
+
constructor(rootDir) {
|
|
24
|
+
this.isInit = false;
|
|
25
|
+
this.rootDir = rootDir;
|
|
26
|
+
this.remoteRepoDir = rootDir + '/remote.git';
|
|
27
|
+
this.testRepoDir = rootDir + '/test-repo';
|
|
28
|
+
}
|
|
29
|
+
static getInstance(rootDir) {
|
|
30
|
+
if (!this.instances.has(rootDir)) {
|
|
31
|
+
this.instances.set(rootDir, new RepoManager(rootDir));
|
|
32
|
+
}
|
|
33
|
+
return this.instances.get(rootDir);
|
|
34
|
+
}
|
|
35
|
+
get git() {
|
|
36
|
+
if (!this.isInit) {
|
|
37
|
+
throw new Error('Cannot perform git operation before calling init()');
|
|
38
|
+
}
|
|
39
|
+
// eslint-disable-next-line
|
|
40
|
+
return (0, simple_git_1.default)(this.testRepoDir);
|
|
41
|
+
}
|
|
42
|
+
initRemoteRepo() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
if (!fs_1.default.existsSync(this.remoteRepoDir)) {
|
|
45
|
+
fs_1.default.mkdirSync(this.remoteRepoDir, { recursive: true });
|
|
46
|
+
// eslint-disable-next-line
|
|
47
|
+
const git = (0, simple_git_1.default)(this.remoteRepoDir);
|
|
48
|
+
yield git.init(true);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
cloneRepo() {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
if (fs_1.default.existsSync(this.remoteRepoDir) && !fs_1.default.existsSync(this.testRepoDir)) {
|
|
55
|
+
// eslint-disable-next-line
|
|
56
|
+
yield (0, simple_git_1.default)().clone(this.remoteRepoDir, this.testRepoDir);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
get repoDir() {
|
|
61
|
+
return this.testRepoDir;
|
|
62
|
+
}
|
|
63
|
+
init() {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
yield this.initRemoteRepo();
|
|
66
|
+
yield this.cloneRepo();
|
|
67
|
+
this.isInit = true;
|
|
68
|
+
yield this.git.raw(['checkout', '-b', 'main']);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
setHead() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
return yield this.git
|
|
74
|
+
.raw(['symbolic-ref', 'HEAD', 'refs/heads/main'])
|
|
75
|
+
.then(() => this.git.remote(['set-head', 'origin', 'main']))
|
|
76
|
+
.catch(err => console.log('set head failed ', err));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
push() {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
return yield this.git
|
|
82
|
+
.push('origin', 'main', ['-u'])
|
|
83
|
+
.catch(err => console.log('push failed ', err));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
checkout(branchName, from) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
return this.git.checkoutBranch(branchName, from);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
stageAll(files = ['.']) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
return this.git.add(files);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
getGitLog() {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const log = yield this.git.log();
|
|
99
|
+
return log.all;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
stageAndCommitAll(files) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
return this.stageAll(files).then(() => this.git.commit('commit message'));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
tearDown() {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
yield fs_1.default.promises.rm(this.rootDir, { recursive: true, force: true });
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
createOrUpdateFile(fileName, content) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const fPath = path_1.default.join(this.testRepoDir, fileName);
|
|
115
|
+
if (fs_1.default.existsSync(fPath)) {
|
|
116
|
+
yield fs_1.default.promises.appendFile(fPath, content);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
yield fs_1.default.promises.writeFile(fPath, content);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
rmFile(file) {
|
|
124
|
+
fs_1.default.unlinkSync(path_1.default.join(this.testRepoDir, file));
|
|
125
|
+
}
|
|
126
|
+
renameFileInRepo(from, to) {
|
|
127
|
+
const fromPath = path_1.default.join(this.testRepoDir, from);
|
|
128
|
+
const toPath = path_1.default.join(this.testRepoDir, to);
|
|
129
|
+
fs_1.default.renameSync(fromPath, toPath);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.RepoManager = RepoManager;
|
|
133
|
+
RepoManager.instances = new Map();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const Git_1 = require("../../src/Git/Git");
|
|
16
|
+
const RepoManager_1 = require("../FsUtils/RepoManager");
|
|
17
|
+
describe('Git', () => {
|
|
18
|
+
const repoManager = RepoManager_1.RepoManager.getInstance('./test/repos');
|
|
19
|
+
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
yield repoManager.init();
|
|
21
|
+
}));
|
|
22
|
+
afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
yield repoManager.tearDown();
|
|
24
|
+
}));
|
|
25
|
+
describe('version check', () => {
|
|
26
|
+
it('does not fail when Git version is equal to 2.37.0', () => {
|
|
27
|
+
//Given/When
|
|
28
|
+
const mock = {
|
|
29
|
+
version: jest.fn().mockReturnValue({ major: 2, minor: 37, patch: 0 }),
|
|
30
|
+
};
|
|
31
|
+
expect(Git_1.Git.versionCheck(mock)).resolves;
|
|
32
|
+
});
|
|
33
|
+
it('fails when Git major version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
//Given/When
|
|
35
|
+
const mock = {
|
|
36
|
+
version: jest.fn().mockReturnValue({ major: 1 }),
|
|
37
|
+
};
|
|
38
|
+
//Then
|
|
39
|
+
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.37.0'));
|
|
40
|
+
}));
|
|
41
|
+
it('fails when Git minor version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
+
//Given/When
|
|
43
|
+
const mock = {
|
|
44
|
+
version: jest.fn().mockReturnValue({ major: 3, minor: 36 }),
|
|
45
|
+
};
|
|
46
|
+
//Then
|
|
47
|
+
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.37.0'));
|
|
48
|
+
}));
|
|
49
|
+
it('fails when Git patch version is more than 0', () => {
|
|
50
|
+
//Given/When
|
|
51
|
+
const mock = {
|
|
52
|
+
version: jest.fn().mockReturnValue({ major: 3, minor: 38, patch: 1 }),
|
|
53
|
+
};
|
|
54
|
+
//Then
|
|
55
|
+
expect(Git_1.Git.versionCheck(mock)).resolves;
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('branch operation', () => {
|
|
59
|
+
it('fails to find default branch name when head is not set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
//Given/When/Then
|
|
61
|
+
yield expect(new Git_1.Git(repoManager.repoDir).getDefaultBranchName()).rejects.toThrow(Error("Failed to find symbolic ref no remote HEAD with message: 'fatal: ref refs/remotes/origin/HEAD is not a symbolic ref'"));
|
|
62
|
+
}));
|
|
63
|
+
it('find default branch name when head is set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
//Given
|
|
65
|
+
yield repoManager
|
|
66
|
+
.createOrUpdateFile('file.txt', 'Test Text')
|
|
67
|
+
.then(() => repoManager.stageAndCommitAll(['file.txt']))
|
|
68
|
+
.then(() => repoManager.push())
|
|
69
|
+
.then(() => repoManager.setHead());
|
|
70
|
+
//When
|
|
71
|
+
const branchName = yield new Git_1.Git(repoManager.repoDir).getDefaultBranchName();
|
|
72
|
+
//Then
|
|
73
|
+
expect(branchName).toBe('origin/main');
|
|
74
|
+
}));
|
|
75
|
+
it('find default branch name when head is set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
//Given
|
|
77
|
+
yield repoManager
|
|
78
|
+
.createOrUpdateFile('file.txt', 'Test Text')
|
|
79
|
+
.then(() => repoManager.stageAndCommitAll(['file.txt']))
|
|
80
|
+
.then(() => repoManager.push())
|
|
81
|
+
.then(() => repoManager.setHead());
|
|
82
|
+
//When
|
|
83
|
+
const branchName = yield new Git_1.Git(repoManager.repoDir).getDefaultBranchName();
|
|
84
|
+
//Then
|
|
85
|
+
expect(branchName).toBe('origin/main');
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
88
|
+
describe('file change operations', () => {
|
|
89
|
+
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
+
yield repoManager
|
|
91
|
+
.createOrUpdateFile('file.txt', 'text')
|
|
92
|
+
.then(() => repoManager.stageAndCommitAll(['file.txt']))
|
|
93
|
+
.then(() => repoManager.push())
|
|
94
|
+
.then(() => repoManager.setHead());
|
|
95
|
+
}));
|
|
96
|
+
describe('local changes', () => {
|
|
97
|
+
it('finds modified files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
+
//Given
|
|
99
|
+
yield repoManager.createOrUpdateFile('file.txt', 'modify');
|
|
100
|
+
//When
|
|
101
|
+
const files = yield new Git_1.Git(repoManager.repoDir).getLocalChangedAndCreated();
|
|
102
|
+
//Then
|
|
103
|
+
expect(files).toEqual(new Set(['file.txt']));
|
|
104
|
+
}));
|
|
105
|
+
it('finds unstaged renamed files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
+
//Given
|
|
107
|
+
repoManager.renameFileInRepo('file.txt', 'renamed.txt');
|
|
108
|
+
// await repoManager.gitStage();
|
|
109
|
+
//When
|
|
110
|
+
const files = yield new Git_1.Git(repoManager.repoDir).getLocalChangedAndCreated();
|
|
111
|
+
//Then
|
|
112
|
+
expect(files).toEqual(new Set(['renamed.txt']));
|
|
113
|
+
}));
|
|
114
|
+
it('finds unstaged new files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
+
//Given
|
|
116
|
+
yield repoManager.createOrUpdateFile('newFile.txt', 'content');
|
|
117
|
+
//When
|
|
118
|
+
const files = yield new Git_1.Git(repoManager.repoDir).getLocalChangedAndCreated();
|
|
119
|
+
//Then
|
|
120
|
+
expect(files).toEqual(new Set(['newFile.txt']));
|
|
121
|
+
}));
|
|
122
|
+
it('does not include deleted files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
//Given
|
|
124
|
+
repoManager.rmFile('file.txt');
|
|
125
|
+
//When
|
|
126
|
+
const files = yield new Git_1.Git(repoManager.repoDir).getLocalChangedAndCreated();
|
|
127
|
+
//Then
|
|
128
|
+
expect(files).toEqual(new Set());
|
|
129
|
+
}));
|
|
130
|
+
it('finds staged renamed, modified and new files ', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
131
|
+
//Setup for renamed file
|
|
132
|
+
yield repoManager
|
|
133
|
+
.createOrUpdateFile('second.txt', 'txt')
|
|
134
|
+
.then(() => repoManager.stageAndCommitAll(['second.txt']));
|
|
135
|
+
//Given
|
|
136
|
+
yield repoManager
|
|
137
|
+
.createOrUpdateFile('file.txt', 'modifiy')
|
|
138
|
+
.then(() => repoManager.renameFileInRepo('second.txt', 'renamed.txt'))
|
|
139
|
+
.then(() => repoManager.createOrUpdateFile('newFile.txt', 'content'))
|
|
140
|
+
.then(() => repoManager.stageAll());
|
|
141
|
+
//When
|
|
142
|
+
const files = yield new Git_1.Git(repoManager.repoDir).getLocalChangedAndCreated();
|
|
143
|
+
//Then
|
|
144
|
+
expect(files).toEqual(new Set(['file.txt', 'renamed.txt', 'newFile.txt']));
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
147
|
+
describe('branch diff changes', () => {
|
|
148
|
+
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
yield repoManager
|
|
150
|
+
.checkout('dev', 'main')
|
|
151
|
+
.then(() => repoManager.createOrUpdateFile('newFile.txt', 'text'))
|
|
152
|
+
.then(() => repoManager.stageAndCommitAll(['newFile.txt']));
|
|
153
|
+
}));
|
|
154
|
+
it('finds diff against for default branch and HEAD', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
155
|
+
//Given
|
|
156
|
+
yield repoManager
|
|
157
|
+
.createOrUpdateFile('anotherFileForCommit.txt', 'text')
|
|
158
|
+
.then(() => repoManager.stageAndCommitAll(['anotherFileForCommit.txt']));
|
|
159
|
+
//When
|
|
160
|
+
const files = yield new Git_1.Git(repoManager.repoDir).diffRange('origin/main', 'HEAD');
|
|
161
|
+
//Then
|
|
162
|
+
expect(files).toEqual(new Set(['newFile.txt', 'anotherFileForCommit.txt']));
|
|
163
|
+
}));
|
|
164
|
+
it('finds diff against default branch and commit ref', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
165
|
+
//Given
|
|
166
|
+
const currentRef = (yield repoManager.getGitLog())[0].hash;
|
|
167
|
+
yield repoManager
|
|
168
|
+
.createOrUpdateFile('anotherFileForCommit.txt', 'text')
|
|
169
|
+
.then(() => repoManager.stageAndCommitAll(['anotherFileForCommit.txt']));
|
|
170
|
+
//When
|
|
171
|
+
const files = yield new Git_1.Git(repoManager.repoDir).diffRange('origin/main', currentRef);
|
|
172
|
+
//Then
|
|
173
|
+
expect(files).toEqual(new Set(['newFile.txt']));
|
|
174
|
+
}));
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apexdevtools/git-ops",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Library to do git operations to find changed files in a given git repository",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Apex Dev Tools Team",
|
|
7
|
+
"email": "apexdevtools@gmail.com",
|
|
8
|
+
"url": "https://github.com/apex-dev-tools"
|
|
9
|
+
},
|
|
10
|
+
"main": "./lib/src/index.js",
|
|
11
|
+
"license": "BSD-3-Clause",
|
|
12
|
+
"files": [
|
|
13
|
+
"lib/**/*",
|
|
14
|
+
"CHANGELOG.md"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/apex-dev-tools/git-ops.git"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=14.0"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"salesforce",
|
|
25
|
+
"apex",
|
|
26
|
+
"apexlink"
|
|
27
|
+
],
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/apex-dev-tools/git-ops/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/apex-dev-tools/git-ops#readme",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@ryansonshine/commitizen": "4.2.8",
|
|
34
|
+
"@ryansonshine/cz-conventional-changelog": "3.3.4",
|
|
35
|
+
"@types/jest": "^29.4.0",
|
|
36
|
+
"@types/node": "^18.11.19",
|
|
37
|
+
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
|
38
|
+
"@typescript-eslint/parser": "^5.0.0",
|
|
39
|
+
"conventional-changelog-conventionalcommits": "5.0.0",
|
|
40
|
+
"eslint": "7.25.0",
|
|
41
|
+
"eslint-config-prettier": "8.3.0",
|
|
42
|
+
"eslint-plugin-node": "11.1.0",
|
|
43
|
+
"eslint-plugin-prettier": "3.4.0",
|
|
44
|
+
"husky": "^8.0.0",
|
|
45
|
+
"jest": "^29.4.2",
|
|
46
|
+
"lint-staged": "10.5.4",
|
|
47
|
+
"prettier": "2.2.1",
|
|
48
|
+
"semantic-release": "19.0.2",
|
|
49
|
+
"ts-jest": "^29.0.5",
|
|
50
|
+
"typescript": "^4.9.5"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"install": "^0.13.0",
|
|
54
|
+
"simple-git": "^3.16.0"
|
|
55
|
+
},
|
|
56
|
+
"config": {
|
|
57
|
+
"commitizen": {
|
|
58
|
+
"path": "./node_modules/@ryansonshine/cz-conventional-changelog"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"lint-staged": {
|
|
62
|
+
"*.ts": "eslint --cache --cache-location .eslintcache --fix"
|
|
63
|
+
},
|
|
64
|
+
"release": {
|
|
65
|
+
"branches": [
|
|
66
|
+
"main"
|
|
67
|
+
],
|
|
68
|
+
"plugins": [
|
|
69
|
+
[
|
|
70
|
+
"@semantic-release/commit-analyzer",
|
|
71
|
+
{
|
|
72
|
+
"preset": "conventionalcommits",
|
|
73
|
+
"releaseRules": [
|
|
74
|
+
{
|
|
75
|
+
"type": "build",
|
|
76
|
+
"scope": "deps",
|
|
77
|
+
"release": "patch"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
"@semantic-release/release-notes-generator",
|
|
84
|
+
{
|
|
85
|
+
"preset": "conventionalcommits",
|
|
86
|
+
"presetConfig": {
|
|
87
|
+
"types": [
|
|
88
|
+
{
|
|
89
|
+
"type": "feat",
|
|
90
|
+
"section": "Features"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "fix",
|
|
94
|
+
"section": "Bug Fixes"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"type": "build",
|
|
98
|
+
"section": "Dependencies and Other Build Updates",
|
|
99
|
+
"hidden": false
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"@semantic-release/npm",
|
|
106
|
+
"@semantic-release/github"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
"scripts": {
|
|
110
|
+
"build": "tsc",
|
|
111
|
+
"clean": "rm -rf ./lib/",
|
|
112
|
+
"cm": "cz",
|
|
113
|
+
"lint": "eslint ./src/ --fix",
|
|
114
|
+
"semantic-release": "semantic-release",
|
|
115
|
+
"test:watch": "jest --watch",
|
|
116
|
+
"test": "jest --coverage --runInBand",
|
|
117
|
+
"typecheck": "tsc --noEmit"
|
|
118
|
+
}
|
|
119
|
+
}
|