bun-git-hooks 0.2.11 โ 0.2.13
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/README.md +81 -10
- package/dist/{cli.js โ bin/cli.js} +148 -10
- package/dist/bin/config.d.ts +3 -0
- package/dist/bin/git-hooks.d.ts +61 -0
- package/dist/bin/index.d.ts +3 -0
- package/dist/bin/types.d.ts +16 -0
- package/dist/git-hooks.d.ts +12 -3
- package/dist/index.js +151 -379
- package/dist/types.d.ts +4 -35
- package/package.json +8 -20
- package/bin/cli.ts +0 -62
- package/bin/git-hooks +0 -0
- package/bin/git-hooks-darwin-arm64 +0 -0
- package/bin/git-hooks-darwin-x64 +0 -0
- package/bin/git-hooks-linux-arm64 +0 -0
- package/bin/git-hooks-linux-x64 +0 -0
- package/bin/git-hooks-windows-x64.exe +0 -0
package/README.md
CHANGED
|
@@ -12,16 +12,17 @@
|
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
-
- ๐ฏ **Simple Configuration
|
|
16
|
-
- ๐ **Automatic Installation
|
|
17
|
-
- ๐ก๏ธ **Type Safe
|
|
18
|
-
- ๐ง **Flexible Config
|
|
19
|
-
- ๐ช **Robust
|
|
20
|
-
- ๐ซ **Skip Option
|
|
21
|
-
- ๐งน **Cleanup
|
|
22
|
-
- ๐ฆ **Zero Dependencies
|
|
23
|
-
- โก **Fast
|
|
24
|
-
- ๐ **Verbose Mode
|
|
15
|
+
- ๐ฏ **Simple Configuration** _Easy setup through multiple config file formats_
|
|
16
|
+
- ๐ **Automatic Installation** _Hooks are installed on package installation_
|
|
17
|
+
- ๐ก๏ธ **Type Safe** _Written in TypeScript with comprehensive type definitions_
|
|
18
|
+
- ๐ง **Flexible Config** _Supports `.ts`, `.js`, `.mjs`, `.json` configurations_
|
|
19
|
+
- ๐ช **Robust** _Handles complex Git workspace configurations_
|
|
20
|
+
- ๐ซ **Skip Option** _Environment variable to skip hook installation_
|
|
21
|
+
- ๐งน **Cleanup** _Optional cleanup of unused hooks_
|
|
22
|
+
- ๐ฆ **Zero Dependencies** _Minimal footprint_
|
|
23
|
+
- โก **Fast** _Built for Bun with performance in mind_
|
|
24
|
+
- ๐ **Verbose Mode** _Detailed logging for troubleshooting_
|
|
25
|
+
- ๐ **Staged Lint** _Run commands only on staged files that match specific patterns_
|
|
25
26
|
|
|
26
27
|
## Installation
|
|
27
28
|
|
|
@@ -79,6 +80,9 @@ git-hooks uninstall
|
|
|
79
80
|
|
|
80
81
|
# Enable verbose logging
|
|
81
82
|
git-hooks --verbose
|
|
83
|
+
|
|
84
|
+
# Run staged lint for a specific hook manually
|
|
85
|
+
git-hooks run-staged-lint pre-commit
|
|
82
86
|
```
|
|
83
87
|
|
|
84
88
|
### Environment Variables
|
|
@@ -115,6 +119,73 @@ export default {
|
|
|
115
119
|
}
|
|
116
120
|
```
|
|
117
121
|
|
|
122
|
+
### Staged Lint (Lint Only Changed Files)
|
|
123
|
+
|
|
124
|
+
You can run linters and formatters only on staged files that match specific patterns, similar to lint-staged. This is particularly useful in pre-commit hooks to ensure quality checks run only on the files being committed.
|
|
125
|
+
|
|
126
|
+
#### Configuration
|
|
127
|
+
|
|
128
|
+
Add a `stagedLint` property to your hook configuration:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// git-hooks.config.ts
|
|
132
|
+
export default {
|
|
133
|
+
'pre-commit': {
|
|
134
|
+
stagedLint: {
|
|
135
|
+
'*.js': 'eslint --fix',
|
|
136
|
+
'*.{ts,tsx}': ['eslint --fix', 'prettier --write'],
|
|
137
|
+
'*.css': 'stylelint --fix',
|
|
138
|
+
'*.md': 'prettier --write'
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
'verbose': true
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### Manual CLI Usage
|
|
146
|
+
|
|
147
|
+
You can also run the staged lint manually using the CLI:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Run staged lint for pre-commit
|
|
151
|
+
git-hooks run-staged-lint pre-commit
|
|
152
|
+
|
|
153
|
+
# Run with verbose output
|
|
154
|
+
git-hooks run-staged-lint pre-commit --verbose
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### Pattern Matching
|
|
158
|
+
|
|
159
|
+
For each file pattern, you can specify either a single command or an array of commands that will run in sequence. The commands will only receive the staged files that match the pattern.
|
|
160
|
+
|
|
161
|
+
For example:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
// git-hooks.config.ts
|
|
165
|
+
export default {
|
|
166
|
+
'*.{js,jsx}': 'eslint --fix', // Run eslint only on JavaScript files
|
|
167
|
+
'*.{ts,tsx}': ['eslint --fix', 'prettier --write'], // Run eslint and then prettier on TypeScript files
|
|
168
|
+
'*.css': 'stylelint --fix', // Run stylelint only on CSS files
|
|
169
|
+
'*.md': 'prettier --write' // Run prettier only on Markdown files
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The output will show which files are being processed and which tasks are being run:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
$ git commit
|
|
177
|
+
|
|
178
|
+
โฏ Running tasks for staged files...
|
|
179
|
+
โฏ *.js โ 2 files
|
|
180
|
+
โ ผ eslint --fix
|
|
181
|
+
โฏ *.{ts,tsx} โ 3 files
|
|
182
|
+
โ น eslint --fix
|
|
183
|
+
โ น prettier --write
|
|
184
|
+
โฏ *.css โ 1 file
|
|
185
|
+
โ ผ stylelint --fix
|
|
186
|
+
โฏ *.md โ no files [SKIPPED]
|
|
187
|
+
```
|
|
188
|
+
|
|
118
189
|
### Error Handling
|
|
119
190
|
|
|
120
191
|
The library provides clear error messages:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// bin/cli.ts
|
|
@@ -604,7 +604,7 @@ class CAC extends EventEmitter {
|
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
// package.json
|
|
607
|
-
var version = "0.2.
|
|
607
|
+
var version = "0.2.13";
|
|
608
608
|
|
|
609
609
|
// src/git-hooks.ts
|
|
610
610
|
import fs from "fs";
|
|
@@ -777,11 +777,26 @@ async function loadConfig({
|
|
|
777
777
|
for (const ext of extensions) {
|
|
778
778
|
const fullPath = resolve(baseDir, `${configPath}${ext}`);
|
|
779
779
|
const config2 = await tryLoadConfig(fullPath, defaultConfig);
|
|
780
|
-
if (config2 !== null)
|
|
780
|
+
if (config2 !== null) {
|
|
781
|
+
console.log("config found:", `${configPath}${ext}`);
|
|
781
782
|
return config2;
|
|
783
|
+
}
|
|
782
784
|
}
|
|
783
785
|
}
|
|
784
|
-
|
|
786
|
+
try {
|
|
787
|
+
const pkgPath = resolve(baseDir, "package.json");
|
|
788
|
+
if (existsSync(pkgPath)) {
|
|
789
|
+
const pkg = await import(pkgPath);
|
|
790
|
+
const pkgConfig = pkg[name];
|
|
791
|
+
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
792
|
+
try {
|
|
793
|
+
console.log("package config found!");
|
|
794
|
+
return deepMerge(defaultConfig, pkgConfig);
|
|
795
|
+
} catch {}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
} catch {}
|
|
799
|
+
console.log("No config found, using default config");
|
|
785
800
|
return defaultConfig;
|
|
786
801
|
}
|
|
787
802
|
var defaultConfigDir = resolve(process2.cwd(), "config");
|
|
@@ -789,7 +804,12 @@ var defaultGeneratedDir = resolve(process2.cwd(), "src/generated");
|
|
|
789
804
|
|
|
790
805
|
// git-hooks.config.ts
|
|
791
806
|
var config = {
|
|
792
|
-
"pre-commit":
|
|
807
|
+
"pre-commit": {
|
|
808
|
+
stagedLint: {
|
|
809
|
+
"*.{js,ts,json,yaml,yml,md}": "bunx --bun eslint . --fix"
|
|
810
|
+
}
|
|
811
|
+
},
|
|
812
|
+
"commit-msg": "bun commitlint --edit $1",
|
|
793
813
|
verbose: true
|
|
794
814
|
};
|
|
795
815
|
var git_hooks_config_default = config;
|
|
@@ -802,6 +822,9 @@ var config2 = await loadConfig({
|
|
|
802
822
|
});
|
|
803
823
|
|
|
804
824
|
// src/git-hooks.ts
|
|
825
|
+
import { exec } from "child_process";
|
|
826
|
+
import { promisify } from "util";
|
|
827
|
+
var execAsync = promisify(exec);
|
|
805
828
|
var VALID_GIT_HOOKS = [
|
|
806
829
|
"applypatch-msg",
|
|
807
830
|
"pre-applypatch",
|
|
@@ -894,13 +917,86 @@ function setHooksFromConfig(projectRootPath = process4.cwd(), options) {
|
|
|
894
917
|
}
|
|
895
918
|
}
|
|
896
919
|
}
|
|
897
|
-
function
|
|
920
|
+
async function getStagedFiles(projectRoot = process4.cwd()) {
|
|
921
|
+
try {
|
|
922
|
+
const { stdout } = await execAsync("git diff --staged --name-only --diff-filter=ACMR", { cwd: projectRoot });
|
|
923
|
+
return stdout.trim().split(`
|
|
924
|
+
`).filter(Boolean);
|
|
925
|
+
} catch (error) {
|
|
926
|
+
console.error("[ERROR] Failed to get staged files:", error);
|
|
927
|
+
return [];
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function matchesGlob(file, pattern) {
|
|
931
|
+
if (pattern.includes("*")) {
|
|
932
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
933
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
934
|
+
return regex.test(file);
|
|
935
|
+
}
|
|
936
|
+
return file === pattern;
|
|
937
|
+
}
|
|
938
|
+
function filterFilesByPattern(files, pattern) {
|
|
939
|
+
return files.filter((file) => matchesGlob(file, pattern));
|
|
940
|
+
}
|
|
941
|
+
async function runCommandOnStagedFiles(command, files, projectRoot = process4.cwd(), verbose = false) {
|
|
942
|
+
if (files.length === 0) {
|
|
943
|
+
if (verbose)
|
|
944
|
+
console.info("[INFO] No matching files for pattern");
|
|
945
|
+
return true;
|
|
946
|
+
}
|
|
947
|
+
const commands = Array.isArray(command) ? command : [command];
|
|
948
|
+
for (const cmd of commands) {
|
|
949
|
+
try {
|
|
950
|
+
const fullCommand = `${cmd} ${files.join(" ")}`;
|
|
951
|
+
if (verbose)
|
|
952
|
+
console.info(`[INFO] Running: ${fullCommand}`);
|
|
953
|
+
const { stdout, stderr } = await execAsync(fullCommand, { cwd: projectRoot });
|
|
954
|
+
if (verbose) {
|
|
955
|
+
if (stdout)
|
|
956
|
+
console.info(stdout);
|
|
957
|
+
if (stderr)
|
|
958
|
+
console.error(stderr);
|
|
959
|
+
}
|
|
960
|
+
} catch (error) {
|
|
961
|
+
console.error(`[ERROR] Command failed: ${cmd}`, error);
|
|
962
|
+
return false;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
967
|
+
async function processStagedLint(stagedLintConfig, projectRoot, verbose = false) {
|
|
968
|
+
const stagedFiles = await getStagedFiles(projectRoot);
|
|
969
|
+
if (stagedFiles.length === 0) {
|
|
970
|
+
if (verbose)
|
|
971
|
+
console.info("[INFO] No staged files found");
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
let success = true;
|
|
975
|
+
for (const [pattern, task] of Object.entries(stagedLintConfig)) {
|
|
976
|
+
const matchedFiles = filterFilesByPattern(stagedFiles, pattern);
|
|
977
|
+
const taskResult = await runCommandOnStagedFiles(task, matchedFiles, projectRoot, verbose);
|
|
978
|
+
if (!taskResult) {
|
|
979
|
+
success = false;
|
|
980
|
+
break;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return success;
|
|
984
|
+
}
|
|
985
|
+
function _setHook(hook, commandOrConfig, projectRoot = process4.cwd()) {
|
|
898
986
|
const gitRoot = getGitProjectRoot(projectRoot);
|
|
899
987
|
if (!gitRoot) {
|
|
900
988
|
console.info("[INFO] No `.git` root folder found, skipping");
|
|
901
989
|
return;
|
|
902
990
|
}
|
|
903
|
-
|
|
991
|
+
let hookCommand;
|
|
992
|
+
if (typeof commandOrConfig === "string") {
|
|
993
|
+
hookCommand = PREPEND_SCRIPT + commandOrConfig;
|
|
994
|
+
} else if (commandOrConfig.stagedLint) {
|
|
995
|
+
hookCommand = PREPEND_SCRIPT + `git-hooks run-staged-lint ${hook}`;
|
|
996
|
+
} else {
|
|
997
|
+
console.error(`[ERROR] Invalid command or config for hook ${hook}`);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
904
1000
|
const hookDirectory = path.join(gitRoot, "hooks");
|
|
905
1001
|
const hookPath = path.normalize(path.join(hookDirectory, hook));
|
|
906
1002
|
if (!fs.existsSync(hookDirectory)) {
|
|
@@ -920,6 +1016,25 @@ function _removeHook(hook, projectRoot = process4.cwd(), verbose = false) {
|
|
|
920
1016
|
if (verbose)
|
|
921
1017
|
console.info(`[INFO] Successfully removed the ${hook} hook`);
|
|
922
1018
|
}
|
|
1019
|
+
async function runStagedLint(hook) {
|
|
1020
|
+
try {
|
|
1021
|
+
const hookConfig = config2[hook];
|
|
1022
|
+
if (!hookConfig || typeof hookConfig !== "object" || !("stagedLint" in hookConfig)) {
|
|
1023
|
+
console.error(`[ERROR] No stagedLint configuration found for hook ${hook}`);
|
|
1024
|
+
return false;
|
|
1025
|
+
}
|
|
1026
|
+
const stagedLintConfig = hookConfig.stagedLint;
|
|
1027
|
+
if (!stagedLintConfig) {
|
|
1028
|
+
console.error(`[ERROR] Invalid stagedLint configuration for hook ${hook}`);
|
|
1029
|
+
return false;
|
|
1030
|
+
}
|
|
1031
|
+
const verbose = config2.verbose === true;
|
|
1032
|
+
return await processStagedLint(stagedLintConfig, process4.cwd(), verbose);
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
console.error("[ERROR] Failed to run staged lint:", error);
|
|
1035
|
+
return false;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
923
1038
|
|
|
924
1039
|
// bin/cli.ts
|
|
925
1040
|
var cli = new CAC("git-hooks");
|
|
@@ -928,20 +1043,25 @@ if (["1", "true"].includes(SKIP_INSTALL_GIT_HOOKS || "")) {
|
|
|
928
1043
|
console.log(`[INFO] SKIP_INSTALL_GIT_HOOKS is set to "${SKIP_INSTALL_GIT_HOOKS}", skipping installing hooks.`);
|
|
929
1044
|
process5.exit(0);
|
|
930
1045
|
}
|
|
931
|
-
cli.command("[configPath]", "Install git hooks, optionally from specified config file").option("--verbose", "Enable verbose logging").example("
|
|
1046
|
+
cli.command("[configPath]", "Install git hooks, optionally from specified config file").option("--verbose", "Enable verbose logging").example("git-hooks").example("git-hooks ../src/config.ts").example("git-hooks --verbose").action(async (configPath, options) => {
|
|
932
1047
|
try {
|
|
933
1048
|
if (options?.verbose) {
|
|
934
1049
|
console.log("[DEBUG] Config path:", configPath || "using default");
|
|
935
1050
|
console.log("[DEBUG] Working directory:", process5.cwd());
|
|
936
1051
|
}
|
|
937
|
-
|
|
1052
|
+
if (configPath) {
|
|
1053
|
+
const config3 = await import(configPath);
|
|
1054
|
+
setHooksFromConfig(process5.cwd(), { configFile: config3 });
|
|
1055
|
+
} else {
|
|
1056
|
+
setHooksFromConfig(process5.cwd());
|
|
1057
|
+
}
|
|
938
1058
|
console.log("[INFO] Successfully set all git hooks");
|
|
939
1059
|
} catch (err) {
|
|
940
1060
|
console.error("[ERROR] Was not able to set git hooks. Error:", err);
|
|
941
1061
|
process5.exit(1);
|
|
942
1062
|
}
|
|
943
1063
|
});
|
|
944
|
-
cli.command("uninstall", "Remove all git hooks").alias("remove").option("--verbose", "Enable verbose logging").example("
|
|
1064
|
+
cli.command("uninstall", "Remove all git hooks").alias("remove").option("--verbose", "Enable verbose logging").example("git-hooks uninstall").example("git-hooks remove").example("git-hooks uninstall --verbose").action(async (options) => {
|
|
945
1065
|
try {
|
|
946
1066
|
if (options?.verbose) {
|
|
947
1067
|
console.log("[DEBUG] Removing hooks from:", process5.cwd());
|
|
@@ -953,6 +1073,24 @@ cli.command("uninstall", "Remove all git hooks").alias("remove").option("--verbo
|
|
|
953
1073
|
process5.exit(1);
|
|
954
1074
|
}
|
|
955
1075
|
});
|
|
1076
|
+
cli.command("run-staged-lint <hook>", "Run staged lint for a specific git hook").option("--verbose", "Enable verbose logging").example("git-hooks run-staged-lint pre-commit").example("git-hooks run-staged-lint pre-push --verbose").action(async (hook, options) => {
|
|
1077
|
+
try {
|
|
1078
|
+
if (options?.verbose) {
|
|
1079
|
+
console.log("[DEBUG] Running staged lint for hook:", hook);
|
|
1080
|
+
console.log("[DEBUG] Working directory:", process5.cwd());
|
|
1081
|
+
}
|
|
1082
|
+
const success = await runStagedLint(hook);
|
|
1083
|
+
if (success) {
|
|
1084
|
+
console.log("[INFO] Staged lint completed successfully");
|
|
1085
|
+
} else {
|
|
1086
|
+
console.error("[ERROR] Staged lint failed");
|
|
1087
|
+
process5.exit(1);
|
|
1088
|
+
}
|
|
1089
|
+
} catch (err) {
|
|
1090
|
+
console.error("[ERROR] Was not able to run staged lint. Error:", err);
|
|
1091
|
+
process5.exit(1);
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
956
1094
|
cli.version(version);
|
|
957
1095
|
cli.help();
|
|
958
1096
|
cli.parse();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SetHooksFromConfigOptions, StagedLintConfig } from './types';
|
|
2
|
+
|
|
3
|
+
declare const execAsync: unknown;
|
|
4
|
+
export declare const VALID_GIT_HOOKS: Array<
|
|
5
|
+
'applypatch-msg' |
|
|
6
|
+
'pre-applypatch' |
|
|
7
|
+
'post-applypatch' |
|
|
8
|
+
'pre-commit' |
|
|
9
|
+
'pre-merge-commit' |
|
|
10
|
+
'prepare-commit-msg' |
|
|
11
|
+
'commit-msg' |
|
|
12
|
+
'post-commit' |
|
|
13
|
+
'pre-rebase' |
|
|
14
|
+
'post-checkout' |
|
|
15
|
+
'post-merge' |
|
|
16
|
+
'pre-push' |
|
|
17
|
+
'pre-receive' |
|
|
18
|
+
'update' |
|
|
19
|
+
'proc-receive' |
|
|
20
|
+
'post-receive' |
|
|
21
|
+
'post-update' |
|
|
22
|
+
'reference-transaction' |
|
|
23
|
+
'push-to-checkout' |
|
|
24
|
+
'pre-auto-gc' |
|
|
25
|
+
'post-rewrite' |
|
|
26
|
+
'sendemail-validate' |
|
|
27
|
+
'fsmonitor-watchman' |
|
|
28
|
+
'p4-changelist' |
|
|
29
|
+
'p4-prepare-changelist' |
|
|
30
|
+
'p4-post-changelist' |
|
|
31
|
+
'p4-pre-submit' |
|
|
32
|
+
'post-index-change'
|
|
33
|
+
>;
|
|
34
|
+
export declare const VALID_OPTIONS: Array<'preserveUnused'>;
|
|
35
|
+
export declare const PREPEND_SCRIPT: unknown;
|
|
36
|
+
export declare function getGitProjectRoot(directory: string): string | undefined;
|
|
37
|
+
export declare function checkBunGitHooksInDependencies(projectRootPath: string): boolean;
|
|
38
|
+
declare function _getPackageJson(projectPath): void;
|
|
39
|
+
export declare function setHooksFromConfig(projectRootPath: string, options?: SetHooksFromConfigOptions): void;
|
|
40
|
+
declare function getStagedFiles(projectRoot: string): Promise<string[]>;
|
|
41
|
+
declare function matchesGlob(file: string, pattern: string): boolean;
|
|
42
|
+
declare function filterFilesByPattern(files: string[], pattern: string): string[];
|
|
43
|
+
declare function runCommandOnStagedFiles(command: string | string[], files: string[], projectRoot: string, verbose): Promise<boolean>;
|
|
44
|
+
declare function processStagedLint(stagedLintConfig: StagedLintConfig, projectRoot: string, verbose): Promise<boolean>;
|
|
45
|
+
declare function _setHook(hook: string, commandOrConfig: string | { stagedLint?: StagedLintConfig }, projectRoot: string): void;
|
|
46
|
+
export declare function removeHooks(projectRoot: string, verbose): void;
|
|
47
|
+
declare function _removeHook(hook: string, projectRoot, verbose): void;
|
|
48
|
+
export declare function runStagedLint(hook: string): Promise<boolean>;
|
|
49
|
+
declare function _validateHooks(config: Record<string, any>): boolean;
|
|
50
|
+
declare const gitHooks: {
|
|
51
|
+
PREPEND_SCRIPT: typeof PREPEND_SCRIPT
|
|
52
|
+
setHooksFromConfig: typeof setHooksFromConfig
|
|
53
|
+
removeHooks: typeof removeHooks
|
|
54
|
+
checkBunGitHooksInDependencies: typeof checkBunGitHooksInDependencies
|
|
55
|
+
getProjectRootDirectoryFromNodeModules: typeof getProjectRootDirectoryFromNodeModules
|
|
56
|
+
getGitProjectRoot: typeof getGitProjectRoot
|
|
57
|
+
runStagedLint: typeof runStagedLint
|
|
58
|
+
getStagedFiles: typeof getStagedFiles
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default gitHooks;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare type StagedLintTask = string | string[]
|
|
2
|
+
|
|
3
|
+
export interface StagedLintConfig {
|
|
4
|
+
[pattern: string]: StagedLintTask
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type GitHooksConfig = {
|
|
8
|
+
[K in typeof VALID_GIT_HOOKS[number]]?: string | { stagedLint?: StagedLintConfig }
|
|
9
|
+
} & {
|
|
10
|
+
preserveUnused?: boolean | typeof VALID_GIT_HOOKS[number][]
|
|
11
|
+
verbose?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SetHooksFromConfigOptions {
|
|
15
|
+
configFile?: GitHooksConfig
|
|
16
|
+
}
|
package/dist/git-hooks.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SetHooksFromConfigOptions } from './types';
|
|
1
|
+
import type { SetHooksFromConfigOptions, StagedLintConfig } from './types';
|
|
2
2
|
|
|
3
|
+
declare const execAsync: unknown;
|
|
3
4
|
export declare const VALID_GIT_HOOKS: Array<
|
|
4
5
|
'applypatch-msg' |
|
|
5
6
|
'pre-applypatch' |
|
|
@@ -36,10 +37,16 @@ export declare function getGitProjectRoot(directory: string): string | undefined
|
|
|
36
37
|
export declare function checkBunGitHooksInDependencies(projectRootPath: string): boolean;
|
|
37
38
|
declare function _getPackageJson(projectPath): void;
|
|
38
39
|
export declare function setHooksFromConfig(projectRootPath: string, options?: SetHooksFromConfigOptions): void;
|
|
39
|
-
declare function
|
|
40
|
+
declare function getStagedFiles(projectRoot: string): Promise<string[]>;
|
|
41
|
+
declare function matchesGlob(file: string, pattern: string): boolean;
|
|
42
|
+
declare function filterFilesByPattern(files: string[], pattern: string): string[];
|
|
43
|
+
declare function runCommandOnStagedFiles(command: string | string[], files: string[], projectRoot: string, verbose): Promise<boolean>;
|
|
44
|
+
declare function processStagedLint(stagedLintConfig: StagedLintConfig, projectRoot: string, verbose): Promise<boolean>;
|
|
45
|
+
declare function _setHook(hook: string, commandOrConfig: string | { stagedLint?: StagedLintConfig }, projectRoot: string): void;
|
|
40
46
|
export declare function removeHooks(projectRoot: string, verbose): void;
|
|
41
47
|
declare function _removeHook(hook: string, projectRoot, verbose): void;
|
|
42
|
-
declare function
|
|
48
|
+
export declare function runStagedLint(hook: string): Promise<boolean>;
|
|
49
|
+
declare function _validateHooks(config: Record<string, any>): boolean;
|
|
43
50
|
declare const gitHooks: {
|
|
44
51
|
PREPEND_SCRIPT: typeof PREPEND_SCRIPT
|
|
45
52
|
setHooksFromConfig: typeof setHooksFromConfig
|
|
@@ -47,6 +54,8 @@ declare const gitHooks: {
|
|
|
47
54
|
checkBunGitHooksInDependencies: typeof checkBunGitHooksInDependencies
|
|
48
55
|
getProjectRootDirectoryFromNodeModules: typeof getProjectRootDirectoryFromNodeModules
|
|
49
56
|
getGitProjectRoot: typeof getGitProjectRoot
|
|
57
|
+
runStagedLint: typeof runStagedLint
|
|
58
|
+
getStagedFiles: typeof getStagedFiles
|
|
50
59
|
};
|
|
51
60
|
|
|
52
61
|
export default gitHooks;
|
package/dist/index.js
CHANGED
|
@@ -1,355 +1,10 @@
|
|
|
1
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
2
|
-
|
|
3
|
-
// node:process
|
|
4
|
-
var C, T, q, A, I, Q, S = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), N = (e, t) => {
|
|
5
|
-
for (var n in t)
|
|
6
|
-
T(e, n, { get: t[n], enumerable: true });
|
|
7
|
-
}, d = (e, t, n, w) => {
|
|
8
|
-
if (t && typeof t == "object" || typeof t == "function")
|
|
9
|
-
for (let l of A(t))
|
|
10
|
-
!Q.call(e, l) && l !== n && T(e, l, { get: () => t[l], enumerable: !(w = q(t, l)) || w.enumerable });
|
|
11
|
-
return e;
|
|
12
|
-
}, h = (e, t, n) => (d(e, t, "default"), n && d(n, t, "default")), y = (e, t, n) => (n = e != null ? C(I(e)) : {}, d(t || !e || !e.__esModule ? T(n, "default", { value: e, enumerable: true }) : n, e)), v, f, j;
|
|
13
|
-
var init_process = __esm(() => {
|
|
14
|
-
C = Object.create;
|
|
15
|
-
T = Object.defineProperty;
|
|
16
|
-
q = Object.getOwnPropertyDescriptor;
|
|
17
|
-
A = Object.getOwnPropertyNames;
|
|
18
|
-
I = Object.getPrototypeOf;
|
|
19
|
-
Q = Object.prototype.hasOwnProperty;
|
|
20
|
-
v = S((B, E) => {
|
|
21
|
-
var r = E.exports = {}, i, u;
|
|
22
|
-
function p() {
|
|
23
|
-
throw new Error("setTimeout has not been defined");
|
|
24
|
-
}
|
|
25
|
-
function g() {
|
|
26
|
-
throw new Error("clearTimeout has not been defined");
|
|
27
|
-
}
|
|
28
|
-
(function() {
|
|
29
|
-
try {
|
|
30
|
-
typeof setTimeout == "function" ? i = setTimeout : i = p;
|
|
31
|
-
} catch {
|
|
32
|
-
i = p;
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
typeof clearTimeout == "function" ? u = clearTimeout : u = g;
|
|
36
|
-
} catch {
|
|
37
|
-
u = g;
|
|
38
|
-
}
|
|
39
|
-
})();
|
|
40
|
-
function b(e) {
|
|
41
|
-
if (i === setTimeout)
|
|
42
|
-
return setTimeout(e, 0);
|
|
43
|
-
if ((i === p || !i) && setTimeout)
|
|
44
|
-
return i = setTimeout, setTimeout(e, 0);
|
|
45
|
-
try {
|
|
46
|
-
return i(e, 0);
|
|
47
|
-
} catch {
|
|
48
|
-
try {
|
|
49
|
-
return i.call(null, e, 0);
|
|
50
|
-
} catch {
|
|
51
|
-
return i.call(this, e, 0);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function O(e) {
|
|
56
|
-
if (u === clearTimeout)
|
|
57
|
-
return clearTimeout(e);
|
|
58
|
-
if ((u === g || !u) && clearTimeout)
|
|
59
|
-
return u = clearTimeout, clearTimeout(e);
|
|
60
|
-
try {
|
|
61
|
-
return u(e);
|
|
62
|
-
} catch {
|
|
63
|
-
try {
|
|
64
|
-
return u.call(null, e);
|
|
65
|
-
} catch {
|
|
66
|
-
return u.call(this, e);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
var o = [], s = false, a, m = -1;
|
|
71
|
-
function U() {
|
|
72
|
-
!s || !a || (s = false, a.length ? o = a.concat(o) : m = -1, o.length && x());
|
|
73
|
-
}
|
|
74
|
-
function x() {
|
|
75
|
-
if (!s) {
|
|
76
|
-
var e = b(U);
|
|
77
|
-
s = true;
|
|
78
|
-
for (var t = o.length;t; ) {
|
|
79
|
-
for (a = o, o = [];++m < t; )
|
|
80
|
-
a && a[m].run();
|
|
81
|
-
m = -1, t = o.length;
|
|
82
|
-
}
|
|
83
|
-
a = null, s = false, O(e);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
r.nextTick = function(e) {
|
|
87
|
-
var t = new Array(arguments.length - 1);
|
|
88
|
-
if (arguments.length > 1)
|
|
89
|
-
for (var n = 1;n < arguments.length; n++)
|
|
90
|
-
t[n - 1] = arguments[n];
|
|
91
|
-
o.push(new L(e, t)), o.length === 1 && !s && b(x);
|
|
92
|
-
};
|
|
93
|
-
function L(e, t) {
|
|
94
|
-
this.fun = e, this.array = t;
|
|
95
|
-
}
|
|
96
|
-
L.prototype.run = function() {
|
|
97
|
-
this.fun.apply(null, this.array);
|
|
98
|
-
};
|
|
99
|
-
r.title = "browser";
|
|
100
|
-
r.browser = true;
|
|
101
|
-
r.env = {};
|
|
102
|
-
r.argv = [];
|
|
103
|
-
r.version = "";
|
|
104
|
-
r.versions = {};
|
|
105
|
-
function c() {}
|
|
106
|
-
r.on = c;
|
|
107
|
-
r.addListener = c;
|
|
108
|
-
r.once = c;
|
|
109
|
-
r.off = c;
|
|
110
|
-
r.removeListener = c;
|
|
111
|
-
r.removeAllListeners = c;
|
|
112
|
-
r.emit = c;
|
|
113
|
-
r.prependListener = c;
|
|
114
|
-
r.prependOnceListener = c;
|
|
115
|
-
r.listeners = function(e) {
|
|
116
|
-
return [];
|
|
117
|
-
};
|
|
118
|
-
r.binding = function(e) {
|
|
119
|
-
throw new Error("process.binding is not supported");
|
|
120
|
-
};
|
|
121
|
-
r.cwd = function() {
|
|
122
|
-
return "/";
|
|
123
|
-
};
|
|
124
|
-
r.chdir = function(e) {
|
|
125
|
-
throw new Error("process.chdir is not supported");
|
|
126
|
-
};
|
|
127
|
-
r.umask = function() {
|
|
128
|
-
return 0;
|
|
129
|
-
};
|
|
130
|
-
});
|
|
131
|
-
f = {};
|
|
132
|
-
N(f, { default: () => j });
|
|
133
|
-
h(f, y(v()));
|
|
134
|
-
j = y(v());
|
|
135
|
-
});
|
|
136
|
-
|
|
137
1
|
// src/config.ts
|
|
138
|
-
|
|
2
|
+
import process2 from "node:process";
|
|
139
3
|
|
|
140
4
|
// node_modules/bunfig/dist/index.js
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
var L = Object.create;
|
|
145
|
-
var h2 = Object.defineProperty;
|
|
146
|
-
var D = Object.getOwnPropertyDescriptor;
|
|
147
|
-
var T2 = Object.getOwnPropertyNames;
|
|
148
|
-
var _ = Object.getPrototypeOf;
|
|
149
|
-
var E = Object.prototype.hasOwnProperty;
|
|
150
|
-
var R = (s, e) => () => (e || s((e = { exports: {} }).exports, e), e.exports);
|
|
151
|
-
var N2 = (s, e, r, t) => {
|
|
152
|
-
if (e && typeof e == "object" || typeof e == "function")
|
|
153
|
-
for (let i of T2(e))
|
|
154
|
-
!E.call(s, i) && i !== r && h2(s, i, { get: () => e[i], enumerable: !(t = D(e, i)) || t.enumerable });
|
|
155
|
-
return s;
|
|
156
|
-
};
|
|
157
|
-
var j2 = (s, e, r) => (r = s != null ? L(_(s)) : {}, N2(e || !s || !s.__esModule ? h2(r, "default", { value: s, enumerable: true }) : r, s));
|
|
158
|
-
var k = R((W, w) => {
|
|
159
|
-
function v2(s) {
|
|
160
|
-
if (typeof s != "string")
|
|
161
|
-
throw new TypeError("Path must be a string. Received " + JSON.stringify(s));
|
|
162
|
-
}
|
|
163
|
-
function C2(s, e) {
|
|
164
|
-
for (var r = "", t = 0, i = -1, a = 0, n, l = 0;l <= s.length; ++l) {
|
|
165
|
-
if (l < s.length)
|
|
166
|
-
n = s.charCodeAt(l);
|
|
167
|
-
else {
|
|
168
|
-
if (n === 47)
|
|
169
|
-
break;
|
|
170
|
-
n = 47;
|
|
171
|
-
}
|
|
172
|
-
if (n === 47) {
|
|
173
|
-
if (!(i === l - 1 || a === 1))
|
|
174
|
-
if (i !== l - 1 && a === 2) {
|
|
175
|
-
if (r.length < 2 || t !== 2 || r.charCodeAt(r.length - 1) !== 46 || r.charCodeAt(r.length - 2) !== 46) {
|
|
176
|
-
if (r.length > 2) {
|
|
177
|
-
var f2 = r.lastIndexOf("/");
|
|
178
|
-
if (f2 !== r.length - 1) {
|
|
179
|
-
f2 === -1 ? (r = "", t = 0) : (r = r.slice(0, f2), t = r.length - 1 - r.lastIndexOf("/")), i = l, a = 0;
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
} else if (r.length === 2 || r.length === 1) {
|
|
183
|
-
r = "", t = 0, i = l, a = 0;
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
e && (r.length > 0 ? r += "/.." : r = "..", t = 2);
|
|
188
|
-
} else
|
|
189
|
-
r.length > 0 ? r += "/" + s.slice(i + 1, l) : r = s.slice(i + 1, l), t = l - i - 1;
|
|
190
|
-
i = l, a = 0;
|
|
191
|
-
} else
|
|
192
|
-
n === 46 && a !== -1 ? ++a : a = -1;
|
|
193
|
-
}
|
|
194
|
-
return r;
|
|
195
|
-
}
|
|
196
|
-
function F(s, e) {
|
|
197
|
-
var r = e.dir || e.root, t = e.base || (e.name || "") + (e.ext || "");
|
|
198
|
-
return r ? r === e.root ? r + t : r + s + t : t;
|
|
199
|
-
}
|
|
200
|
-
var m = { resolve: function() {
|
|
201
|
-
for (var e = "", r = false, t, i = arguments.length - 1;i >= -1 && !r; i--) {
|
|
202
|
-
var a;
|
|
203
|
-
i >= 0 ? a = arguments[i] : (t === undefined && (t = process.cwd()), a = t), v2(a), a.length !== 0 && (e = a + "/" + e, r = a.charCodeAt(0) === 47);
|
|
204
|
-
}
|
|
205
|
-
return e = C2(e, !r), r ? e.length > 0 ? "/" + e : "/" : e.length > 0 ? e : ".";
|
|
206
|
-
}, normalize: function(e) {
|
|
207
|
-
if (v2(e), e.length === 0)
|
|
208
|
-
return ".";
|
|
209
|
-
var r = e.charCodeAt(0) === 47, t = e.charCodeAt(e.length - 1) === 47;
|
|
210
|
-
return e = C2(e, !r), e.length === 0 && !r && (e = "."), e.length > 0 && t && (e += "/"), r ? "/" + e : e;
|
|
211
|
-
}, isAbsolute: function(e) {
|
|
212
|
-
return v2(e), e.length > 0 && e.charCodeAt(0) === 47;
|
|
213
|
-
}, join: function() {
|
|
214
|
-
if (arguments.length === 0)
|
|
215
|
-
return ".";
|
|
216
|
-
for (var e, r = 0;r < arguments.length; ++r) {
|
|
217
|
-
var t = arguments[r];
|
|
218
|
-
v2(t), t.length > 0 && (e === undefined ? e = t : e += "/" + t);
|
|
219
|
-
}
|
|
220
|
-
return e === undefined ? "." : m.normalize(e);
|
|
221
|
-
}, relative: function(e, r) {
|
|
222
|
-
if (v2(e), v2(r), e === r || (e = m.resolve(e), r = m.resolve(r), e === r))
|
|
223
|
-
return "";
|
|
224
|
-
for (var t = 1;t < e.length && e.charCodeAt(t) === 47; ++t)
|
|
225
|
-
;
|
|
226
|
-
for (var i = e.length, a = i - t, n = 1;n < r.length && r.charCodeAt(n) === 47; ++n)
|
|
227
|
-
;
|
|
228
|
-
for (var l = r.length, f2 = l - n, c = a < f2 ? a : f2, d2 = -1, o = 0;o <= c; ++o) {
|
|
229
|
-
if (o === c) {
|
|
230
|
-
if (f2 > c) {
|
|
231
|
-
if (r.charCodeAt(n + o) === 47)
|
|
232
|
-
return r.slice(n + o + 1);
|
|
233
|
-
if (o === 0)
|
|
234
|
-
return r.slice(n + o);
|
|
235
|
-
} else
|
|
236
|
-
a > c && (e.charCodeAt(t + o) === 47 ? d2 = o : o === 0 && (d2 = 0));
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
var A2 = e.charCodeAt(t + o), z = r.charCodeAt(n + o);
|
|
240
|
-
if (A2 !== z)
|
|
241
|
-
break;
|
|
242
|
-
A2 === 47 && (d2 = o);
|
|
243
|
-
}
|
|
244
|
-
var b = "";
|
|
245
|
-
for (o = t + d2 + 1;o <= i; ++o)
|
|
246
|
-
(o === i || e.charCodeAt(o) === 47) && (b.length === 0 ? b += ".." : b += "/..");
|
|
247
|
-
return b.length > 0 ? b + r.slice(n + d2) : (n += d2, r.charCodeAt(n) === 47 && ++n, r.slice(n));
|
|
248
|
-
}, _makeLong: function(e) {
|
|
249
|
-
return e;
|
|
250
|
-
}, dirname: function(e) {
|
|
251
|
-
if (v2(e), e.length === 0)
|
|
252
|
-
return ".";
|
|
253
|
-
for (var r = e.charCodeAt(0), t = r === 47, i = -1, a = true, n = e.length - 1;n >= 1; --n)
|
|
254
|
-
if (r = e.charCodeAt(n), r === 47) {
|
|
255
|
-
if (!a) {
|
|
256
|
-
i = n;
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
} else
|
|
260
|
-
a = false;
|
|
261
|
-
return i === -1 ? t ? "/" : "." : t && i === 1 ? "//" : e.slice(0, i);
|
|
262
|
-
}, basename: function(e, r) {
|
|
263
|
-
if (r !== undefined && typeof r != "string")
|
|
264
|
-
throw new TypeError('"ext" argument must be a string');
|
|
265
|
-
v2(e);
|
|
266
|
-
var t = 0, i = -1, a = true, n;
|
|
267
|
-
if (r !== undefined && r.length > 0 && r.length <= e.length) {
|
|
268
|
-
if (r.length === e.length && r === e)
|
|
269
|
-
return "";
|
|
270
|
-
var l = r.length - 1, f2 = -1;
|
|
271
|
-
for (n = e.length - 1;n >= 0; --n) {
|
|
272
|
-
var c = e.charCodeAt(n);
|
|
273
|
-
if (c === 47) {
|
|
274
|
-
if (!a) {
|
|
275
|
-
t = n + 1;
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
} else
|
|
279
|
-
f2 === -1 && (a = false, f2 = n + 1), l >= 0 && (c === r.charCodeAt(l) ? --l === -1 && (i = n) : (l = -1, i = f2));
|
|
280
|
-
}
|
|
281
|
-
return t === i ? i = f2 : i === -1 && (i = e.length), e.slice(t, i);
|
|
282
|
-
} else {
|
|
283
|
-
for (n = e.length - 1;n >= 0; --n)
|
|
284
|
-
if (e.charCodeAt(n) === 47) {
|
|
285
|
-
if (!a) {
|
|
286
|
-
t = n + 1;
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
} else
|
|
290
|
-
i === -1 && (a = false, i = n + 1);
|
|
291
|
-
return i === -1 ? "" : e.slice(t, i);
|
|
292
|
-
}
|
|
293
|
-
}, extname: function(e) {
|
|
294
|
-
v2(e);
|
|
295
|
-
for (var r = -1, t = 0, i = -1, a = true, n = 0, l = e.length - 1;l >= 0; --l) {
|
|
296
|
-
var f2 = e.charCodeAt(l);
|
|
297
|
-
if (f2 === 47) {
|
|
298
|
-
if (!a) {
|
|
299
|
-
t = l + 1;
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
i === -1 && (a = false, i = l + 1), f2 === 46 ? r === -1 ? r = l : n !== 1 && (n = 1) : r !== -1 && (n = -1);
|
|
305
|
-
}
|
|
306
|
-
return r === -1 || i === -1 || n === 0 || n === 1 && r === i - 1 && r === t + 1 ? "" : e.slice(r, i);
|
|
307
|
-
}, format: function(e) {
|
|
308
|
-
if (e === null || typeof e != "object")
|
|
309
|
-
throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof e);
|
|
310
|
-
return F("/", e);
|
|
311
|
-
}, parse: function(e) {
|
|
312
|
-
v2(e);
|
|
313
|
-
var r = { root: "", dir: "", base: "", ext: "", name: "" };
|
|
314
|
-
if (e.length === 0)
|
|
315
|
-
return r;
|
|
316
|
-
var t = e.charCodeAt(0), i = t === 47, a;
|
|
317
|
-
i ? (r.root = "/", a = 1) : a = 0;
|
|
318
|
-
for (var n = -1, l = 0, f2 = -1, c = true, d2 = e.length - 1, o = 0;d2 >= a; --d2) {
|
|
319
|
-
if (t = e.charCodeAt(d2), t === 47) {
|
|
320
|
-
if (!c) {
|
|
321
|
-
l = d2 + 1;
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
f2 === -1 && (c = false, f2 = d2 + 1), t === 46 ? n === -1 ? n = d2 : o !== 1 && (o = 1) : n !== -1 && (o = -1);
|
|
327
|
-
}
|
|
328
|
-
return n === -1 || f2 === -1 || o === 0 || o === 1 && n === f2 - 1 && n === l + 1 ? f2 !== -1 && (l === 0 && i ? r.base = r.name = e.slice(1, f2) : r.base = r.name = e.slice(l, f2)) : (l === 0 && i ? (r.name = e.slice(1, n), r.base = e.slice(1, f2)) : (r.name = e.slice(l, n), r.base = e.slice(l, f2)), r.ext = e.slice(n, f2)), l > 0 ? r.dir = e.slice(0, l - 1) : i && (r.dir = "/"), r;
|
|
329
|
-
}, sep: "/", delimiter: ":", win32: null, posix: null };
|
|
330
|
-
m.posix = m;
|
|
331
|
-
w.exports = m;
|
|
332
|
-
});
|
|
333
|
-
var x = j2(k());
|
|
334
|
-
var u = x;
|
|
335
|
-
var J = x;
|
|
336
|
-
var P = function(s) {
|
|
337
|
-
return s;
|
|
338
|
-
};
|
|
339
|
-
var S2 = function() {
|
|
340
|
-
throw new Error("Not implemented");
|
|
341
|
-
};
|
|
342
|
-
u.parse ??= S2;
|
|
343
|
-
J.parse ??= S2;
|
|
344
|
-
var g = { resolve: u.resolve.bind(u), normalize: u.normalize.bind(u), isAbsolute: u.isAbsolute.bind(u), join: u.join.bind(u), relative: u.relative.bind(u), toNamespacedPath: P, dirname: u.dirname.bind(u), basename: u.basename.bind(u), extname: u.extname.bind(u), format: u.format.bind(u), parse: u.parse.bind(u), sep: "/", delimiter: ":", win32: undefined, posix: undefined, _makeLong: P };
|
|
345
|
-
var y2 = { sep: "\\", delimiter: ";", win32: undefined, ...g, posix: g };
|
|
346
|
-
g.win32 = y2.win32 = y2;
|
|
347
|
-
g.posix = g;
|
|
348
|
-
var q2 = g;
|
|
349
|
-
var { resolve: B, normalize: G, isAbsolute: H, join: K, relative: Q2, toNamespacedPath: U, dirname: V, basename: X, extname: Y, format: Z, parse: $, sep: I2, delimiter: O } = g;
|
|
350
|
-
|
|
351
|
-
// node_modules/bunfig/dist/index.js
|
|
352
|
-
init_process();
|
|
5
|
+
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
6
|
+
import { dirname, resolve } from "path";
|
|
7
|
+
import process from "process";
|
|
353
8
|
function deepMerge(target, source) {
|
|
354
9
|
if (Array.isArray(source) && Array.isArray(target) && source.length === 2 && target.length === 2 && isObject(source[0]) && "id" in source[0] && source[0].id === 3 && isObject(source[1]) && "id" in source[1] && source[1].id === 4) {
|
|
355
10
|
return source;
|
|
@@ -497,7 +152,7 @@ async function loadConfig({
|
|
|
497
152
|
cwd,
|
|
498
153
|
defaultConfig
|
|
499
154
|
}) {
|
|
500
|
-
const baseDir = cwd ||
|
|
155
|
+
const baseDir = cwd || process.cwd();
|
|
501
156
|
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
502
157
|
const configPaths = [
|
|
503
158
|
`${name}.config`,
|
|
@@ -507,21 +162,41 @@ async function loadConfig({
|
|
|
507
162
|
];
|
|
508
163
|
for (const configPath of configPaths) {
|
|
509
164
|
for (const ext of extensions) {
|
|
510
|
-
const fullPath =
|
|
165
|
+
const fullPath = resolve(baseDir, `${configPath}${ext}`);
|
|
511
166
|
const config2 = await tryLoadConfig(fullPath, defaultConfig);
|
|
512
|
-
if (config2 !== null)
|
|
167
|
+
if (config2 !== null) {
|
|
168
|
+
console.log("config found:", `${configPath}${ext}`);
|
|
513
169
|
return config2;
|
|
170
|
+
}
|
|
514
171
|
}
|
|
515
172
|
}
|
|
516
|
-
|
|
173
|
+
try {
|
|
174
|
+
const pkgPath = resolve(baseDir, "package.json");
|
|
175
|
+
if (existsSync(pkgPath)) {
|
|
176
|
+
const pkg = await import(pkgPath);
|
|
177
|
+
const pkgConfig = pkg[name];
|
|
178
|
+
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
179
|
+
try {
|
|
180
|
+
console.log("package config found!");
|
|
181
|
+
return deepMerge(defaultConfig, pkgConfig);
|
|
182
|
+
} catch {}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch {}
|
|
186
|
+
console.log("No config found, using default config");
|
|
517
187
|
return defaultConfig;
|
|
518
188
|
}
|
|
519
|
-
var defaultConfigDir =
|
|
520
|
-
var defaultGeneratedDir =
|
|
189
|
+
var defaultConfigDir = resolve(process.cwd(), "config");
|
|
190
|
+
var defaultGeneratedDir = resolve(process.cwd(), "src/generated");
|
|
521
191
|
|
|
522
192
|
// git-hooks.config.ts
|
|
523
193
|
var config = {
|
|
524
|
-
"pre-commit":
|
|
194
|
+
"pre-commit": {
|
|
195
|
+
stagedLint: {
|
|
196
|
+
"*.{js,ts,json,yaml,yml,md}": "bunx --bun eslint . --fix"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"commit-msg": "bun commitlint --edit $1",
|
|
525
200
|
verbose: true
|
|
526
201
|
};
|
|
527
202
|
var git_hooks_config_default = config;
|
|
@@ -529,12 +204,16 @@ var git_hooks_config_default = config;
|
|
|
529
204
|
// src/config.ts
|
|
530
205
|
var config2 = await loadConfig({
|
|
531
206
|
name: "git-hooks",
|
|
532
|
-
cwd:
|
|
207
|
+
cwd: process2.cwd(),
|
|
533
208
|
defaultConfig: git_hooks_config_default
|
|
534
209
|
});
|
|
535
210
|
// src/git-hooks.ts
|
|
536
|
-
|
|
537
|
-
|
|
211
|
+
import fs from "node:fs";
|
|
212
|
+
import path from "node:path";
|
|
213
|
+
import process3 from "node:process";
|
|
214
|
+
import { exec } from "node:child_process";
|
|
215
|
+
import { promisify } from "node:util";
|
|
216
|
+
var execAsync = promisify(exec);
|
|
538
217
|
var VALID_GIT_HOOKS = [
|
|
539
218
|
"applypatch-msg",
|
|
540
219
|
"pre-applypatch",
|
|
@@ -578,32 +257,32 @@ if [ -f "$BUN_GIT_HOOKS_RC" ]; then
|
|
|
578
257
|
fi
|
|
579
258
|
|
|
580
259
|
`;
|
|
581
|
-
function getGitProjectRoot(directory =
|
|
260
|
+
function getGitProjectRoot(directory = process3.cwd()) {
|
|
582
261
|
if (directory.endsWith(".git")) {
|
|
583
|
-
return
|
|
262
|
+
return path.normalize(directory);
|
|
584
263
|
}
|
|
585
|
-
let start =
|
|
586
|
-
if (!start || start ===
|
|
264
|
+
let start = path.normalize(directory);
|
|
265
|
+
if (!start || start === path.sep || start === ".") {
|
|
587
266
|
return;
|
|
588
267
|
}
|
|
589
|
-
const fullPath =
|
|
268
|
+
const fullPath = path.join(start, ".git");
|
|
590
269
|
if (fs.existsSync(fullPath)) {
|
|
591
270
|
if (!fs.lstatSync(fullPath).isDirectory()) {
|
|
592
271
|
const content = fs.readFileSync(fullPath, { encoding: "utf-8" });
|
|
593
272
|
const match = /^gitdir: (.*)\s*$/.exec(content);
|
|
594
273
|
if (match) {
|
|
595
274
|
const gitDir = match[1];
|
|
596
|
-
let commonDir =
|
|
275
|
+
let commonDir = path.join(gitDir, "commondir");
|
|
597
276
|
if (fs.existsSync(commonDir)) {
|
|
598
277
|
commonDir = fs.readFileSync(commonDir, "utf8").trim();
|
|
599
|
-
return
|
|
278
|
+
return path.resolve(gitDir, commonDir);
|
|
600
279
|
}
|
|
601
|
-
return
|
|
280
|
+
return path.normalize(gitDir);
|
|
602
281
|
}
|
|
603
282
|
}
|
|
604
|
-
return
|
|
283
|
+
return path.normalize(fullPath);
|
|
605
284
|
}
|
|
606
|
-
const parentDir =
|
|
285
|
+
const parentDir = path.dirname(start);
|
|
607
286
|
if (parentDir === start) {
|
|
608
287
|
return;
|
|
609
288
|
}
|
|
@@ -640,18 +319,18 @@ function checkBunGitHooksInDependencies(projectRootPath) {
|
|
|
640
319
|
}
|
|
641
320
|
return "bun-git-hooks" in packageJsonContent.devDependencies;
|
|
642
321
|
}
|
|
643
|
-
function _getPackageJson(projectPath =
|
|
322
|
+
function _getPackageJson(projectPath = process3.cwd()) {
|
|
644
323
|
if (typeof projectPath !== "string") {
|
|
645
324
|
throw new TypeError("projectPath is not a string");
|
|
646
325
|
}
|
|
647
|
-
const targetPackageJson =
|
|
326
|
+
const targetPackageJson = path.normalize(`${projectPath}/package.json`);
|
|
648
327
|
if (!fs.statSync(targetPackageJson).isFile()) {
|
|
649
328
|
throw new Error("Package.json doesn't exist");
|
|
650
329
|
}
|
|
651
330
|
const packageJsonDataRaw = fs.readFileSync(targetPackageJson, { encoding: "utf-8" });
|
|
652
331
|
return { packageJsonContent: JSON.parse(packageJsonDataRaw), packageJsonPath: targetPackageJson };
|
|
653
332
|
}
|
|
654
|
-
function setHooksFromConfig(projectRootPath =
|
|
333
|
+
function setHooksFromConfig(projectRootPath = process3.cwd(), options) {
|
|
655
334
|
if (!config2 || Object.keys(config2).length === 0)
|
|
656
335
|
throw new Error("[ERROR] Config was not found! Please add `.git-hooks.config.{ts,js,mjs,cjs,mts,cts,json}` or `git-hooks.config.{ts,js,mjs,cjs,mts,cts,json}` or the `git-hooks` entry in package.json.\r\nCheck README for details");
|
|
657
336
|
const configFile = options?.configFile ? options.configFile : config2;
|
|
@@ -670,34 +349,127 @@ function setHooksFromConfig(projectRootPath = j.cwd(), options) {
|
|
|
670
349
|
}
|
|
671
350
|
}
|
|
672
351
|
}
|
|
673
|
-
function
|
|
352
|
+
async function getStagedFiles(projectRoot = process3.cwd()) {
|
|
353
|
+
try {
|
|
354
|
+
const { stdout } = await execAsync("git diff --staged --name-only --diff-filter=ACMR", { cwd: projectRoot });
|
|
355
|
+
return stdout.trim().split(`
|
|
356
|
+
`).filter(Boolean);
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error("[ERROR] Failed to get staged files:", error);
|
|
359
|
+
return [];
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function matchesGlob(file, pattern) {
|
|
363
|
+
if (pattern.includes("*")) {
|
|
364
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
365
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
366
|
+
return regex.test(file);
|
|
367
|
+
}
|
|
368
|
+
return file === pattern;
|
|
369
|
+
}
|
|
370
|
+
function filterFilesByPattern(files, pattern) {
|
|
371
|
+
return files.filter((file) => matchesGlob(file, pattern));
|
|
372
|
+
}
|
|
373
|
+
async function runCommandOnStagedFiles(command, files, projectRoot = process3.cwd(), verbose = false) {
|
|
374
|
+
if (files.length === 0) {
|
|
375
|
+
if (verbose)
|
|
376
|
+
console.info("[INFO] No matching files for pattern");
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
const commands = Array.isArray(command) ? command : [command];
|
|
380
|
+
for (const cmd of commands) {
|
|
381
|
+
try {
|
|
382
|
+
const fullCommand = `${cmd} ${files.join(" ")}`;
|
|
383
|
+
if (verbose)
|
|
384
|
+
console.info(`[INFO] Running: ${fullCommand}`);
|
|
385
|
+
const { stdout, stderr } = await execAsync(fullCommand, { cwd: projectRoot });
|
|
386
|
+
if (verbose) {
|
|
387
|
+
if (stdout)
|
|
388
|
+
console.info(stdout);
|
|
389
|
+
if (stderr)
|
|
390
|
+
console.error(stderr);
|
|
391
|
+
}
|
|
392
|
+
} catch (error) {
|
|
393
|
+
console.error(`[ERROR] Command failed: ${cmd}`, error);
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
async function processStagedLint(stagedLintConfig, projectRoot, verbose = false) {
|
|
400
|
+
const stagedFiles = await getStagedFiles(projectRoot);
|
|
401
|
+
if (stagedFiles.length === 0) {
|
|
402
|
+
if (verbose)
|
|
403
|
+
console.info("[INFO] No staged files found");
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
let success = true;
|
|
407
|
+
for (const [pattern, task] of Object.entries(stagedLintConfig)) {
|
|
408
|
+
const matchedFiles = filterFilesByPattern(stagedFiles, pattern);
|
|
409
|
+
const taskResult = await runCommandOnStagedFiles(task, matchedFiles, projectRoot, verbose);
|
|
410
|
+
if (!taskResult) {
|
|
411
|
+
success = false;
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return success;
|
|
416
|
+
}
|
|
417
|
+
function _setHook(hook, commandOrConfig, projectRoot = process3.cwd()) {
|
|
674
418
|
const gitRoot = getGitProjectRoot(projectRoot);
|
|
675
419
|
if (!gitRoot) {
|
|
676
420
|
console.info("[INFO] No `.git` root folder found, skipping");
|
|
677
421
|
return;
|
|
678
422
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
423
|
+
let hookCommand;
|
|
424
|
+
if (typeof commandOrConfig === "string") {
|
|
425
|
+
hookCommand = PREPEND_SCRIPT + commandOrConfig;
|
|
426
|
+
} else if (commandOrConfig.stagedLint) {
|
|
427
|
+
hookCommand = PREPEND_SCRIPT + `git-hooks run-staged-lint ${hook}`;
|
|
428
|
+
} else {
|
|
429
|
+
console.error(`[ERROR] Invalid command or config for hook ${hook}`);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const hookDirectory = path.join(gitRoot, "hooks");
|
|
433
|
+
const hookPath = path.normalize(path.join(hookDirectory, hook));
|
|
682
434
|
if (!fs.existsSync(hookDirectory)) {
|
|
683
435
|
fs.mkdirSync(hookDirectory, { recursive: true });
|
|
684
436
|
}
|
|
685
437
|
fs.writeFileSync(hookPath, hookCommand, { mode: 493 });
|
|
686
438
|
}
|
|
687
|
-
function removeHooks(projectRoot =
|
|
439
|
+
function removeHooks(projectRoot = process3.cwd(), verbose = false) {
|
|
688
440
|
for (const configEntry of VALID_GIT_HOOKS)
|
|
689
441
|
_removeHook(configEntry, projectRoot, verbose);
|
|
690
442
|
}
|
|
691
|
-
function _removeHook(hook, projectRoot =
|
|
443
|
+
function _removeHook(hook, projectRoot = process3.cwd(), verbose = false) {
|
|
692
444
|
const gitRoot = getGitProjectRoot(projectRoot);
|
|
693
|
-
const hookPath =
|
|
445
|
+
const hookPath = path.normalize(`${gitRoot}/hooks/${hook}`);
|
|
694
446
|
if (fs.existsSync(hookPath))
|
|
695
447
|
fs.unlinkSync(hookPath);
|
|
696
448
|
if (verbose)
|
|
697
449
|
console.info(`[INFO] Successfully removed the ${hook} hook`);
|
|
698
450
|
}
|
|
451
|
+
async function runStagedLint(hook) {
|
|
452
|
+
try {
|
|
453
|
+
const hookConfig = config2[hook];
|
|
454
|
+
if (!hookConfig || typeof hookConfig !== "object" || !("stagedLint" in hookConfig)) {
|
|
455
|
+
console.error(`[ERROR] No stagedLint configuration found for hook ${hook}`);
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
const stagedLintConfig = hookConfig.stagedLint;
|
|
459
|
+
if (!stagedLintConfig) {
|
|
460
|
+
console.error(`[ERROR] Invalid stagedLint configuration for hook ${hook}`);
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
const verbose = config2.verbose === true;
|
|
464
|
+
return await processStagedLint(stagedLintConfig, process3.cwd(), verbose);
|
|
465
|
+
} catch (error) {
|
|
466
|
+
console.error("[ERROR] Failed to run staged lint:", error);
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
699
470
|
export {
|
|
700
471
|
setHooksFromConfig,
|
|
472
|
+
runStagedLint,
|
|
701
473
|
removeHooks,
|
|
702
474
|
getProjectRootDirectoryFromNodeModules,
|
|
703
475
|
getGitProjectRoot,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,42 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
export declare type StagedLintTask = string | string[]
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
height: number
|
|
6
|
-
data: T
|
|
7
|
-
}
|
|
8
|
-
export declare interface BufferRet {
|
|
9
|
-
data: Buffer | Uint8ClampedArray
|
|
10
|
-
width: number
|
|
11
|
-
height: number
|
|
12
|
-
exifBuffer?: ArrayBuffer
|
|
13
|
-
comments?: string[]
|
|
14
|
-
}
|
|
15
|
-
export declare type UintArrRet = ImageData & {
|
|
16
|
-
exifBuffer?: ArrayBuffer
|
|
17
|
-
comments?: string[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ImageData {
|
|
21
|
-
width: number
|
|
22
|
-
height: number
|
|
23
|
-
data: Uint8ClampedArray | Buffer
|
|
24
|
-
colorSpace?: 'srgb'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type BufferLike = Buffer | Uint8Array | ArrayLike<number> | Iterable<number> | ArrayBuffer
|
|
28
|
-
|
|
29
|
-
export interface DecoderOptions {
|
|
30
|
-
useTArray: boolean
|
|
31
|
-
colorTransform?: boolean
|
|
32
|
-
formatAsRGBA?: boolean
|
|
33
|
-
tolerantDecoding?: boolean
|
|
34
|
-
maxResolutionInMP?: number
|
|
35
|
-
maxMemoryUsageInMB?: number
|
|
3
|
+
export interface StagedLintConfig {
|
|
4
|
+
[pattern: string]: StagedLintTask
|
|
36
5
|
}
|
|
37
6
|
|
|
38
7
|
export type GitHooksConfig = {
|
|
39
|
-
[K in typeof VALID_GIT_HOOKS[number]]?: string
|
|
8
|
+
[K in typeof VALID_GIT_HOOKS[number]]?: string | { stagedLint?: StagedLintConfig }
|
|
40
9
|
} & {
|
|
41
10
|
preserveUnused?: boolean | typeof VALID_GIT_HOOKS[number][]
|
|
42
11
|
verbose?: boolean
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-git-hooks",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.13",
|
|
5
5
|
"description": "A modern, zero dependency tool for managing git hooks in Bun projects.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"module": "./dist/index.js",
|
|
39
39
|
"types": "./dist/index.d.ts",
|
|
40
40
|
"bin": {
|
|
41
|
-
"git-hooks": "./bin/
|
|
42
|
-
"bun-git-hooks": "./bin/
|
|
41
|
+
"git-hooks": "./dist/bin/cli.js",
|
|
42
|
+
"bun-git-hooks": "./dist/bin/cli.js"
|
|
43
43
|
},
|
|
44
|
-
"files": ["README.md", "
|
|
44
|
+
"files": ["README.md", "dist"],
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "bun build.ts && bun run compile",
|
|
47
47
|
"compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/git-hooks",
|
|
@@ -73,29 +73,17 @@
|
|
|
73
73
|
"zip:darwin-arm64": "zip -j bin/git-hooks-darwin-arm64.zip bin/git-hooks-darwin-arm64"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@
|
|
77
|
-
"@shikijs/vitepress-twoslash": "^3.2.2",
|
|
76
|
+
"@stacksjs/docs": "^0.70.23",
|
|
78
77
|
"@stacksjs/eslint-config": "^4.10.2-beta.3",
|
|
79
|
-
"@types/bun": "^1.2.
|
|
80
|
-
"@types/node": "^22.14.0",
|
|
81
|
-
"@vite-pwa/vitepress": "^1.0.0",
|
|
78
|
+
"@types/bun": "^1.2.10",
|
|
82
79
|
"bumpp": "^10.1.0",
|
|
83
80
|
"bun-plugin-dtsx": "^0.21.9",
|
|
84
|
-
"bunfig": "^0.8.
|
|
81
|
+
"bunfig": "^0.8.3",
|
|
85
82
|
"cac": "^6.7.14",
|
|
86
83
|
"changelogen": "^0.6.1",
|
|
87
|
-
"
|
|
88
|
-
"typescript": "^5.8.3",
|
|
89
|
-
"unocss": "^66.0.0",
|
|
90
|
-
"unplugin-icons": "^22.1.0",
|
|
91
|
-
"unplugin-vue-components": "^28.4.1",
|
|
92
|
-
"vite-plugin-pwa": "^1.0.0",
|
|
93
|
-
"vitepress": "^1.6.3"
|
|
84
|
+
"typescript": "^5.8.3"
|
|
94
85
|
},
|
|
95
86
|
"overrides": {
|
|
96
87
|
"unconfig": "0.3.10"
|
|
97
|
-
},
|
|
98
|
-
"lint-staged": {
|
|
99
|
-
"*.{js,ts}": "bunx --bun eslint . --fix"
|
|
100
88
|
}
|
|
101
89
|
}
|
package/bin/cli.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import { CAC } from 'cac'
|
|
4
|
-
import { version } from '../package.json'
|
|
5
|
-
import { removeHooks, setHooksFromConfig } from '../src/git-hooks'
|
|
6
|
-
|
|
7
|
-
const cli = new CAC('git-hooks')
|
|
8
|
-
|
|
9
|
-
// Check if installation should be skipped
|
|
10
|
-
const { SKIP_INSTALL_GIT_HOOKS } = process.env
|
|
11
|
-
if (['1', 'true'].includes(SKIP_INSTALL_GIT_HOOKS || '')) {
|
|
12
|
-
console.log(`[INFO] SKIP_INSTALL_GIT_HOOKS is set to "${SKIP_INSTALL_GIT_HOOKS}", skipping installing hooks.`)
|
|
13
|
-
process.exit(0)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
cli
|
|
17
|
-
.command('[configPath]', 'Install git hooks, optionally from specified config file')
|
|
18
|
-
.option('--verbose', 'Enable verbose logging')
|
|
19
|
-
.example('bun-git-hooks')
|
|
20
|
-
.example('bun-git-hooks ../src/config.ts')
|
|
21
|
-
.example('bun-git-hooks --verbose')
|
|
22
|
-
.action(async (configPath?: string, options?: { verbose?: boolean }) => {
|
|
23
|
-
try {
|
|
24
|
-
if (options?.verbose) {
|
|
25
|
-
console.log('[DEBUG] Config path:', configPath || 'using default')
|
|
26
|
-
console.log('[DEBUG] Working directory:', process.cwd())
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setHooksFromConfig(process.cwd(), { configFile: configPath })
|
|
30
|
-
console.log('[INFO] Successfully set all git hooks')
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
console.error('[ERROR] Was not able to set git hooks. Error:', err)
|
|
34
|
-
process.exit(1)
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
cli
|
|
39
|
-
.command('uninstall', 'Remove all git hooks')
|
|
40
|
-
.alias('remove') // Add alias for uninstall
|
|
41
|
-
.option('--verbose', 'Enable verbose logging')
|
|
42
|
-
.example('bun-git-hooks uninstall')
|
|
43
|
-
.example('bunx bun-git-hooks remove')
|
|
44
|
-
.example('bunx git-hooks uninstall --verbose')
|
|
45
|
-
.action(async (options?: { verbose?: boolean }) => {
|
|
46
|
-
try {
|
|
47
|
-
if (options?.verbose) {
|
|
48
|
-
console.log('[DEBUG] Removing hooks from:', process.cwd())
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
removeHooks(process.cwd(), options?.verbose)
|
|
52
|
-
console.log('[INFO] Successfully removed all git hooks')
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
console.error('[ERROR] Was not able to remove git hooks. Error:', err)
|
|
56
|
-
process.exit(1)
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
cli.version(version)
|
|
61
|
-
cli.help()
|
|
62
|
-
cli.parse()
|
package/bin/git-hooks
DELETED
|
Binary file
|
|
Binary file
|
package/bin/git-hooks-darwin-x64
DELETED
|
Binary file
|
|
Binary file
|
package/bin/git-hooks-linux-x64
DELETED
|
Binary file
|
|
Binary file
|