plop-pack-git-commit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/index.cjs +226 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +54 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Borja López Felipe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# plop-pack-git-commit
|
|
2
|
+
|
|
3
|
+
PlopJS action pack that stages changes, creates a git commit, and pushes to `origin`.
|
|
4
|
+
|
|
5
|
+
Inspired by [plop-pack-git-init](https://github.com/crutchcorn/plop-pack-git-init), but focused on committing existing or generated files in an already initialized repository.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add plop-pack-git-commit
|
|
11
|
+
# or
|
|
12
|
+
npm i plop-pack-git-commit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
module.exports = function (plop) {
|
|
19
|
+
plop.load("plop-pack-git-commit");
|
|
20
|
+
|
|
21
|
+
plop.setGenerator("example", {
|
|
22
|
+
prompts: [],
|
|
23
|
+
actions: [
|
|
24
|
+
{
|
|
25
|
+
type: "add",
|
|
26
|
+
path: "notes/{{name}}.md",
|
|
27
|
+
template: "# {{name}}\n",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: "gitCommit",
|
|
31
|
+
path: process.cwd(),
|
|
32
|
+
message: "docs: add {{name}} note",
|
|
33
|
+
files: "notes/{{name}}.md",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Commit specific file(s)
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
{
|
|
44
|
+
type: "gitCommit",
|
|
45
|
+
path: process.cwd(),
|
|
46
|
+
message: "docs: add contact note",
|
|
47
|
+
files: "notes/contacto.md",
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`files` accepts a string or an array of strings.
|
|
52
|
+
|
|
53
|
+
### Commit everything pending
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
{
|
|
57
|
+
type: "gitCommit",
|
|
58
|
+
path: process.cwd(),
|
|
59
|
+
message: "chore: sync generated files",
|
|
60
|
+
all: true,
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This runs `git add -A` before committing.
|
|
65
|
+
|
|
66
|
+
## Options
|
|
67
|
+
|
|
68
|
+
| Option | Type | Default | Description |
|
|
69
|
+
|--------|------|---------|-------------|
|
|
70
|
+
| `path` | `string` | `process.cwd()` | Repository path |
|
|
71
|
+
| `message` | `string` | required | Commit message |
|
|
72
|
+
| `files` | `string \| string[]` | — | Stage only these paths |
|
|
73
|
+
| `all` | `boolean` | — | Stage all changes with `git add -A` |
|
|
74
|
+
| `verbose` | `boolean` | `false` | Stream git output to the terminal |
|
|
75
|
+
| `skipEmpty` | `boolean` | `true` | Resolve instead of failing when there is nothing to commit |
|
|
76
|
+
|
|
77
|
+
Provide either `files` or `all: true`. They are mutually exclusive.
|
|
78
|
+
|
|
79
|
+
## Push behavior
|
|
80
|
+
|
|
81
|
+
After a successful commit, the action always runs:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git push origin HEAD
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- If there was nothing to commit (`skipEmpty`), push is skipped.
|
|
88
|
+
- If `origin` is missing or push fails, the action resolves with a warning instead of failing the generator. The commit remains local.
|
|
89
|
+
|
|
90
|
+
## Schema export
|
|
91
|
+
|
|
92
|
+
You can validate action configs outside Plop:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { gitCommitConfigSchema } from "plop-pack-git-commit";
|
|
96
|
+
|
|
97
|
+
const result = gitCommitConfigSchema.safeParse({
|
|
98
|
+
path: process.cwd(),
|
|
99
|
+
message: "feat: add generator output",
|
|
100
|
+
all: true,
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Requirements
|
|
105
|
+
|
|
106
|
+
- `git` available in `PATH`
|
|
107
|
+
- Git user identity configured (`user.name`, `user.email`)
|
|
108
|
+
- Remote `origin` configured when you expect push to succeed
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pnpm install
|
|
114
|
+
pnpm check # lint + test + build
|
|
115
|
+
pnpm lint
|
|
116
|
+
pnpm test
|
|
117
|
+
pnpm build
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## GitHub Actions
|
|
121
|
+
|
|
122
|
+
| Workflow | Trigger | Purpose |
|
|
123
|
+
|----------|---------|---------|
|
|
124
|
+
| `CI` | push/PR to `main` | lint, test, build |
|
|
125
|
+
| `Security audit` | push/PR + weekly | `pnpm audit` fails on high/critical |
|
|
126
|
+
| `Dependency review` | pull requests | blocks PRs that add vulnerable deps |
|
|
127
|
+
| `CodeQL` | push/PR + weekly | static analysis for TypeScript/JavaScript |
|
|
128
|
+
| `Release` | GitHub Release published | verify tag, `pnpm check`, publish to npm |
|
|
129
|
+
|
|
130
|
+
Dependabot opens weekly PRs to update dependencies.
|
|
131
|
+
|
|
132
|
+
### Security releases (automated)
|
|
133
|
+
|
|
134
|
+
When a **Dependabot security PR** is merged to `main`:
|
|
135
|
+
|
|
136
|
+
1. `Security release prepare` checks:
|
|
137
|
+
- PR author is `dependabot[bot]`
|
|
138
|
+
- PR body/labels reference security advisories (GHSA/CVE)
|
|
139
|
+
- `pnpm audit` shows fewer vulnerabilities than before the merge
|
|
140
|
+
2. If all pass, it opens a review PR (`security-release/x.y.z`) that bumps the **patch** version (`z`) and prepends a **Security** section to `CHANGELOG.md` (packages, versions, advisories).
|
|
141
|
+
3. If audit does not improve, no release PR is created.
|
|
142
|
+
4. When you merge the security release PR, `Security release publish` tags `vx.y.z`, creates a GitHub Release titled `Security release x.y.z`, and publishes to npm.
|
|
143
|
+
|
|
144
|
+
Manual feature releases still use the `Release` workflow (GitHub Release UI). Bot-authored security releases use the dedicated publish workflow to avoid duplicate npm publishes.
|
|
145
|
+
|
|
146
|
+
### Releasing to npm (manual)
|
|
147
|
+
|
|
148
|
+
1. Bump `version` in `package.json` (e.g. `0.1.1`).
|
|
149
|
+
2. Commit, push to `main`, and create a GitHub Release with tag `v0.1.1` (must match `package.json`).
|
|
150
|
+
3. The `Release` workflow runs `pnpm check` and publishes with [npm provenance](https://docs.npmjs.com/generating-provenance-statements).
|
|
151
|
+
|
|
152
|
+
Repository secret required:
|
|
153
|
+
|
|
154
|
+
| Secret | Purpose |
|
|
155
|
+
|--------|---------|
|
|
156
|
+
| `NPM_TOKEN` | npm automation token with publish access to this package |
|
|
157
|
+
|
|
158
|
+
Enable **Dependabot alerts** and **Code scanning** under repository Settings → Code security.
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
default: () => registerGitCommitPack,
|
|
34
|
+
gitCommitAction: () => gitCommitAction,
|
|
35
|
+
gitCommitConfigSchema: () => gitCommitConfigSchema
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/git-commit-action.ts
|
|
40
|
+
var import_promises = require("fs/promises");
|
|
41
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
42
|
+
|
|
43
|
+
// src/lib/run-git.ts
|
|
44
|
+
var import_node_child_process = require("child_process");
|
|
45
|
+
var didSucceed = (code) => code === 0;
|
|
46
|
+
function runGit(args, options) {
|
|
47
|
+
const { cwd, verbose = false } = options;
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const child = (0, import_node_child_process.spawn)("git", args, {
|
|
50
|
+
cwd,
|
|
51
|
+
stdio: verbose ? "inherit" : "pipe"
|
|
52
|
+
});
|
|
53
|
+
if (verbose) {
|
|
54
|
+
child.on("close", (code) => {
|
|
55
|
+
if (didSucceed(code)) {
|
|
56
|
+
resolve({ stdout: "", stderr: "" });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
reject(new Error(`git ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
60
|
+
});
|
|
61
|
+
child.on("error", reject);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let stdout = "";
|
|
65
|
+
let stderr = "";
|
|
66
|
+
child.stdout?.on("data", (chunk) => {
|
|
67
|
+
stdout += chunk.toString();
|
|
68
|
+
});
|
|
69
|
+
child.stderr?.on("data", (chunk) => {
|
|
70
|
+
stderr += chunk.toString();
|
|
71
|
+
});
|
|
72
|
+
child.on("close", (code) => {
|
|
73
|
+
if (didSucceed(code)) {
|
|
74
|
+
resolve({ stdout, stderr });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const detail = stderr.trim() || stdout.trim();
|
|
78
|
+
reject(
|
|
79
|
+
new Error(
|
|
80
|
+
detail ? `git ${args.join(" ")} failed: ${detail}` : `git ${args.join(" ")} exited with code ${code ?? "unknown"}`
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
child.on("error", reject);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/lib/git-push.ts
|
|
89
|
+
async function hasOriginRemote(repoPath, verbose) {
|
|
90
|
+
try {
|
|
91
|
+
await runGit(["remote", "get-url", "origin"], { cwd: repoPath, verbose });
|
|
92
|
+
return true;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function pushToOrigin(repoPath, verbose = false) {
|
|
98
|
+
if (!await hasOriginRemote(repoPath, verbose)) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
warning: "Committed; push skipped: remote origin is not configured"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
await runGit(["push", "origin", "HEAD"], { cwd: repoPath, verbose });
|
|
106
|
+
return { ok: true };
|
|
107
|
+
} catch (error) {
|
|
108
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
warning: `Committed; push failed: ${message}`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/schemas/git-commit-config.ts
|
|
117
|
+
var import_zod = require("zod");
|
|
118
|
+
var gitCommitConfigSchema = import_zod.z.object({
|
|
119
|
+
path: import_zod.z.string().min(1),
|
|
120
|
+
message: import_zod.z.string().trim().min(1),
|
|
121
|
+
files: import_zod.z.union([import_zod.z.string().min(1), import_zod.z.array(import_zod.z.string().min(1)).min(1)]).optional(),
|
|
122
|
+
all: import_zod.z.boolean().optional(),
|
|
123
|
+
verbose: import_zod.z.boolean().default(false),
|
|
124
|
+
skipEmpty: import_zod.z.boolean().default(true)
|
|
125
|
+
}).refine((data) => data.files !== void 0 !== (data.all === true), {
|
|
126
|
+
message: "Provide either files or all: true, not both or neither"
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// src/git-commit-action.ts
|
|
130
|
+
async function isGitRepository(repoPath) {
|
|
131
|
+
try {
|
|
132
|
+
await (0, import_promises.access)(import_node_path.default.join(repoPath, ".git"));
|
|
133
|
+
return true;
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function formatZodError(error) {
|
|
139
|
+
return error.issues.map((issue) => `${issue.path.join(".") || "config"}: ${issue.message}`).join("; ");
|
|
140
|
+
}
|
|
141
|
+
function normalizeFiles(files) {
|
|
142
|
+
return Array.isArray(files) ? files : [files];
|
|
143
|
+
}
|
|
144
|
+
async function hasChangesToStage(repoPath, verbose) {
|
|
145
|
+
const { stdout } = await runGit(["status", "--porcelain"], {
|
|
146
|
+
cwd: repoPath,
|
|
147
|
+
verbose
|
|
148
|
+
});
|
|
149
|
+
return stdout.trim().length > 0;
|
|
150
|
+
}
|
|
151
|
+
async function stageFiles(repoPath, config, verbose) {
|
|
152
|
+
if (config.files !== void 0) {
|
|
153
|
+
await runGit(["add", "--", ...normalizeFiles(config.files)], {
|
|
154
|
+
cwd: repoPath,
|
|
155
|
+
verbose
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (config.all) {
|
|
160
|
+
await runGit(["add", "-A"], { cwd: repoPath, verbose });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async function hasStagedDiff(repoPath, verbose) {
|
|
164
|
+
try {
|
|
165
|
+
await runGit(["diff", "--cached", "--quiet"], { cwd: repoPath, verbose });
|
|
166
|
+
return false;
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (error instanceof Error && error.message.includes("exited with code 1")) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function gitCommitAction(_answers, config) {
|
|
175
|
+
const parsed = gitCommitConfigSchema.safeParse({
|
|
176
|
+
path: config.path ?? process.cwd(),
|
|
177
|
+
message: config.message,
|
|
178
|
+
files: config.files,
|
|
179
|
+
all: config.all,
|
|
180
|
+
verbose: config.verbose ?? false,
|
|
181
|
+
skipEmpty: config.skipEmpty ?? true
|
|
182
|
+
});
|
|
183
|
+
if (!parsed.success) {
|
|
184
|
+
throw new Error(`Invalid gitCommit config: ${formatZodError(parsed.error)}`);
|
|
185
|
+
}
|
|
186
|
+
const { path: repoPath, message, verbose, skipEmpty, files, all } = parsed.data;
|
|
187
|
+
if (!await isGitRepository(repoPath)) {
|
|
188
|
+
throw new Error(`Not a git repository: ${repoPath}`);
|
|
189
|
+
}
|
|
190
|
+
const hasWorkingTreeChanges = await hasChangesToStage(repoPath, verbose);
|
|
191
|
+
if (!hasWorkingTreeChanges && skipEmpty) {
|
|
192
|
+
return "Nothing to commit";
|
|
193
|
+
}
|
|
194
|
+
if (!hasWorkingTreeChanges && !skipEmpty) {
|
|
195
|
+
throw new Error("Nothing to commit");
|
|
196
|
+
}
|
|
197
|
+
await stageFiles(repoPath, { files, all }, verbose);
|
|
198
|
+
const staged = await hasStagedDiff(repoPath, verbose);
|
|
199
|
+
if (!staged && skipEmpty) {
|
|
200
|
+
return "Nothing to commit";
|
|
201
|
+
}
|
|
202
|
+
if (!staged && !skipEmpty) {
|
|
203
|
+
throw new Error("Nothing to commit after staging");
|
|
204
|
+
}
|
|
205
|
+
await runGit(["commit", "-m", message], { cwd: repoPath, verbose });
|
|
206
|
+
const pushResult = await pushToOrigin(repoPath, verbose);
|
|
207
|
+
if (pushResult.ok) {
|
|
208
|
+
return `Committed and pushed to origin: ${message}`;
|
|
209
|
+
}
|
|
210
|
+
if (verbose) {
|
|
211
|
+
console.warn(pushResult.warning);
|
|
212
|
+
}
|
|
213
|
+
return pushResult.warning;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/index.ts
|
|
217
|
+
function registerGitCommitPack(plop) {
|
|
218
|
+
plop.setDefaultInclude({ actionTypes: true });
|
|
219
|
+
plop.setActionType("gitCommit", gitCommitAction);
|
|
220
|
+
}
|
|
221
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
222
|
+
0 && (module.exports = {
|
|
223
|
+
gitCommitAction,
|
|
224
|
+
gitCommitConfigSchema
|
|
225
|
+
});
|
|
226
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/git-commit-action.ts","../src/lib/run-git.ts","../src/lib/git-push.ts","../src/schemas/git-commit-config.ts"],"sourcesContent":["import type { CustomActionFunction, NodePlopAPI } from \"node-plop\";\nimport { gitCommitAction } from \"./git-commit-action.js\";\nimport {\n type GitCommitActionConfig,\n type GitCommitConfig,\n gitCommitConfigSchema,\n} from \"./schemas/git-commit-config.js\";\n\nexport { gitCommitAction, gitCommitConfigSchema };\nexport type { GitCommitActionConfig, GitCommitConfig };\n\nexport default function registerGitCommitPack(plop: NodePlopAPI): void {\n plop.setDefaultInclude({ actionTypes: true });\n plop.setActionType(\"gitCommit\", gitCommitAction as CustomActionFunction);\n}\n","import { access } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pushToOrigin } from \"./lib/git-push.js\";\nimport { runGit } from \"./lib/run-git.js\";\nimport { type GitCommitActionConfig, gitCommitConfigSchema } from \"./schemas/git-commit-config.js\";\n\nasync function isGitRepository(repoPath: string): Promise<boolean> {\n try {\n await access(path.join(repoPath, \".git\"));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatZodError(error: {\n issues: Array<{ path: Array<string | number>; message: string }>;\n}) {\n return error.issues\n .map((issue) => `${issue.path.join(\".\") || \"config\"}: ${issue.message}`)\n .join(\"; \");\n}\n\nfunction normalizeFiles(files: string | string[]): string[] {\n return Array.isArray(files) ? files : [files];\n}\n\nasync function hasChangesToStage(repoPath: string, verbose: boolean): Promise<boolean> {\n const { stdout } = await runGit([\"status\", \"--porcelain\"], {\n cwd: repoPath,\n verbose,\n });\n return stdout.trim().length > 0;\n}\n\nasync function stageFiles(\n repoPath: string,\n config: { files?: string | string[]; all?: boolean },\n verbose: boolean,\n): Promise<void> {\n if (config.files !== undefined) {\n await runGit([\"add\", \"--\", ...normalizeFiles(config.files)], {\n cwd: repoPath,\n verbose,\n });\n return;\n }\n\n if (config.all) {\n await runGit([\"add\", \"-A\"], { cwd: repoPath, verbose });\n }\n}\n\nasync function hasStagedDiff(repoPath: string, verbose: boolean): Promise<boolean> {\n try {\n await runGit([\"diff\", \"--cached\", \"--quiet\"], { cwd: repoPath, verbose });\n return false;\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"exited with code 1\")) {\n return true;\n }\n throw error;\n }\n}\n\nexport async function gitCommitAction(\n _answers: unknown,\n config: GitCommitActionConfig & Record<string, unknown>,\n): Promise<string> {\n const parsed = gitCommitConfigSchema.safeParse({\n path: config.path ?? process.cwd(),\n message: config.message,\n files: config.files,\n all: config.all,\n verbose: config.verbose ?? false,\n skipEmpty: config.skipEmpty ?? true,\n });\n\n if (!parsed.success) {\n throw new Error(`Invalid gitCommit config: ${formatZodError(parsed.error)}`);\n }\n\n const { path: repoPath, message, verbose, skipEmpty, files, all } = parsed.data;\n\n if (!(await isGitRepository(repoPath))) {\n throw new Error(`Not a git repository: ${repoPath}`);\n }\n\n const hasWorkingTreeChanges = await hasChangesToStage(repoPath, verbose);\n\n if (!hasWorkingTreeChanges && skipEmpty) {\n return \"Nothing to commit\";\n }\n\n if (!hasWorkingTreeChanges && !skipEmpty) {\n throw new Error(\"Nothing to commit\");\n }\n\n await stageFiles(repoPath, { files, all }, verbose);\n\n const staged = await hasStagedDiff(repoPath, verbose);\n\n if (!staged && skipEmpty) {\n return \"Nothing to commit\";\n }\n\n if (!staged && !skipEmpty) {\n throw new Error(\"Nothing to commit after staging\");\n }\n\n await runGit([\"commit\", \"-m\", message], { cwd: repoPath, verbose });\n\n const pushResult = await pushToOrigin(repoPath, verbose);\n\n if (pushResult.ok) {\n return `Committed and pushed to origin: ${message}`;\n }\n\n if (verbose) {\n console.warn(pushResult.warning);\n }\n\n return pushResult.warning;\n}\n","import { spawn } from \"node:child_process\";\n\nexport type RunGitOptions = {\n cwd: string;\n verbose?: boolean;\n};\n\nexport type RunGitResult = {\n stdout: string;\n stderr: string;\n};\n\nconst didSucceed = (code: number | null): boolean => code === 0;\n\nexport function runGit(args: string[], options: RunGitOptions): Promise<RunGitResult> {\n const { cwd, verbose = false } = options;\n\n return new Promise((resolve, reject) => {\n const child = spawn(\"git\", args, {\n cwd,\n stdio: verbose ? \"inherit\" : \"pipe\",\n });\n\n if (verbose) {\n child.on(\"close\", (code) => {\n if (didSucceed(code)) {\n resolve({ stdout: \"\", stderr: \"\" });\n return;\n }\n\n reject(new Error(`git ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`));\n });\n child.on(\"error\", reject);\n return;\n }\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk: Buffer | string) => {\n stdout += chunk.toString();\n });\n\n child.stderr?.on(\"data\", (chunk: Buffer | string) => {\n stderr += chunk.toString();\n });\n\n child.on(\"close\", (code) => {\n if (didSucceed(code)) {\n resolve({ stdout, stderr });\n return;\n }\n\n const detail = stderr.trim() || stdout.trim();\n reject(\n new Error(\n detail\n ? `git ${args.join(\" \")} failed: ${detail}`\n : `git ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n\n child.on(\"error\", reject);\n });\n}\n","import { runGit } from \"./run-git.js\";\n\nexport type PushResult = { ok: true } | { ok: false; warning: string };\n\nasync function hasOriginRemote(repoPath: string, verbose: boolean): Promise<boolean> {\n try {\n await runGit([\"remote\", \"get-url\", \"origin\"], { cwd: repoPath, verbose });\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function pushToOrigin(repoPath: string, verbose = false): Promise<PushResult> {\n if (!(await hasOriginRemote(repoPath, verbose))) {\n return {\n ok: false,\n warning: \"Committed; push skipped: remote origin is not configured\",\n };\n }\n\n try {\n await runGit([\"push\", \"origin\", \"HEAD\"], { cwd: repoPath, verbose });\n return { ok: true };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n ok: false,\n warning: `Committed; push failed: ${message}`,\n };\n }\n}\n","import { z } from \"zod\";\n\nexport const gitCommitConfigSchema = z\n .object({\n path: z.string().min(1),\n message: z.string().trim().min(1),\n files: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(),\n all: z.boolean().optional(),\n verbose: z.boolean().default(false),\n skipEmpty: z.boolean().default(true),\n })\n .refine((data) => (data.files !== undefined) !== (data.all === true), {\n message: \"Provide either files or all: true, not both or neither\",\n });\n\nexport type GitCommitConfig = z.infer<typeof gitCommitConfigSchema>;\n\nexport type GitCommitActionConfig = {\n path?: string;\n message?: string;\n files?: string | string[];\n all?: boolean;\n verbose?: boolean;\n skipEmpty?: boolean;\n};\n"],"mappings":"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","names":["path"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { NodePlopAPI } from 'node-plop';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
declare const gitCommitConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
5
|
+
path: z.ZodString;
|
|
6
|
+
message: z.ZodString;
|
|
7
|
+
files: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
|
+
all: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
verbose: z.ZodDefault<z.ZodBoolean>;
|
|
10
|
+
skipEmpty: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
verbose: boolean;
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
skipEmpty: boolean;
|
|
16
|
+
files?: string | string[] | undefined;
|
|
17
|
+
all?: boolean | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
path: string;
|
|
20
|
+
message: string;
|
|
21
|
+
verbose?: boolean | undefined;
|
|
22
|
+
files?: string | string[] | undefined;
|
|
23
|
+
all?: boolean | undefined;
|
|
24
|
+
skipEmpty?: boolean | undefined;
|
|
25
|
+
}>, {
|
|
26
|
+
verbose: boolean;
|
|
27
|
+
path: string;
|
|
28
|
+
message: string;
|
|
29
|
+
skipEmpty: boolean;
|
|
30
|
+
files?: string | string[] | undefined;
|
|
31
|
+
all?: boolean | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
path: string;
|
|
34
|
+
message: string;
|
|
35
|
+
verbose?: boolean | undefined;
|
|
36
|
+
files?: string | string[] | undefined;
|
|
37
|
+
all?: boolean | undefined;
|
|
38
|
+
skipEmpty?: boolean | undefined;
|
|
39
|
+
}>;
|
|
40
|
+
type GitCommitConfig = z.infer<typeof gitCommitConfigSchema>;
|
|
41
|
+
type GitCommitActionConfig = {
|
|
42
|
+
path?: string;
|
|
43
|
+
message?: string;
|
|
44
|
+
files?: string | string[];
|
|
45
|
+
all?: boolean;
|
|
46
|
+
verbose?: boolean;
|
|
47
|
+
skipEmpty?: boolean;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
declare function gitCommitAction(_answers: unknown, config: GitCommitActionConfig & Record<string, unknown>): Promise<string>;
|
|
51
|
+
|
|
52
|
+
declare function registerGitCommitPack(plop: NodePlopAPI): void;
|
|
53
|
+
|
|
54
|
+
export { type GitCommitActionConfig, type GitCommitConfig, registerGitCommitPack as default, gitCommitAction, gitCommitConfigSchema };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { NodePlopAPI } from 'node-plop';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
declare const gitCommitConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
5
|
+
path: z.ZodString;
|
|
6
|
+
message: z.ZodString;
|
|
7
|
+
files: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
8
|
+
all: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
verbose: z.ZodDefault<z.ZodBoolean>;
|
|
10
|
+
skipEmpty: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
verbose: boolean;
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
skipEmpty: boolean;
|
|
16
|
+
files?: string | string[] | undefined;
|
|
17
|
+
all?: boolean | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
path: string;
|
|
20
|
+
message: string;
|
|
21
|
+
verbose?: boolean | undefined;
|
|
22
|
+
files?: string | string[] | undefined;
|
|
23
|
+
all?: boolean | undefined;
|
|
24
|
+
skipEmpty?: boolean | undefined;
|
|
25
|
+
}>, {
|
|
26
|
+
verbose: boolean;
|
|
27
|
+
path: string;
|
|
28
|
+
message: string;
|
|
29
|
+
skipEmpty: boolean;
|
|
30
|
+
files?: string | string[] | undefined;
|
|
31
|
+
all?: boolean | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
path: string;
|
|
34
|
+
message: string;
|
|
35
|
+
verbose?: boolean | undefined;
|
|
36
|
+
files?: string | string[] | undefined;
|
|
37
|
+
all?: boolean | undefined;
|
|
38
|
+
skipEmpty?: boolean | undefined;
|
|
39
|
+
}>;
|
|
40
|
+
type GitCommitConfig = z.infer<typeof gitCommitConfigSchema>;
|
|
41
|
+
type GitCommitActionConfig = {
|
|
42
|
+
path?: string;
|
|
43
|
+
message?: string;
|
|
44
|
+
files?: string | string[];
|
|
45
|
+
all?: boolean;
|
|
46
|
+
verbose?: boolean;
|
|
47
|
+
skipEmpty?: boolean;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
declare function gitCommitAction(_answers: unknown, config: GitCommitActionConfig & Record<string, unknown>): Promise<string>;
|
|
51
|
+
|
|
52
|
+
declare function registerGitCommitPack(plop: NodePlopAPI): void;
|
|
53
|
+
|
|
54
|
+
export { type GitCommitActionConfig, type GitCommitConfig, registerGitCommitPack as default, gitCommitAction, gitCommitConfigSchema };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// src/git-commit-action.ts
|
|
2
|
+
import { access } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
// src/lib/run-git.ts
|
|
6
|
+
import { spawn } from "child_process";
|
|
7
|
+
var didSucceed = (code) => code === 0;
|
|
8
|
+
function runGit(args, options) {
|
|
9
|
+
const { cwd, verbose = false } = options;
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const child = spawn("git", args, {
|
|
12
|
+
cwd,
|
|
13
|
+
stdio: verbose ? "inherit" : "pipe"
|
|
14
|
+
});
|
|
15
|
+
if (verbose) {
|
|
16
|
+
child.on("close", (code) => {
|
|
17
|
+
if (didSucceed(code)) {
|
|
18
|
+
resolve({ stdout: "", stderr: "" });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
reject(new Error(`git ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
22
|
+
});
|
|
23
|
+
child.on("error", reject);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let stdout = "";
|
|
27
|
+
let stderr = "";
|
|
28
|
+
child.stdout?.on("data", (chunk) => {
|
|
29
|
+
stdout += chunk.toString();
|
|
30
|
+
});
|
|
31
|
+
child.stderr?.on("data", (chunk) => {
|
|
32
|
+
stderr += chunk.toString();
|
|
33
|
+
});
|
|
34
|
+
child.on("close", (code) => {
|
|
35
|
+
if (didSucceed(code)) {
|
|
36
|
+
resolve({ stdout, stderr });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const detail = stderr.trim() || stdout.trim();
|
|
40
|
+
reject(
|
|
41
|
+
new Error(
|
|
42
|
+
detail ? `git ${args.join(" ")} failed: ${detail}` : `git ${args.join(" ")} exited with code ${code ?? "unknown"}`
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
child.on("error", reject);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/lib/git-push.ts
|
|
51
|
+
async function hasOriginRemote(repoPath, verbose) {
|
|
52
|
+
try {
|
|
53
|
+
await runGit(["remote", "get-url", "origin"], { cwd: repoPath, verbose });
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function pushToOrigin(repoPath, verbose = false) {
|
|
60
|
+
if (!await hasOriginRemote(repoPath, verbose)) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
warning: "Committed; push skipped: remote origin is not configured"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
await runGit(["push", "origin", "HEAD"], { cwd: repoPath, verbose });
|
|
68
|
+
return { ok: true };
|
|
69
|
+
} catch (error) {
|
|
70
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
warning: `Committed; push failed: ${message}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/schemas/git-commit-config.ts
|
|
79
|
+
import { z } from "zod";
|
|
80
|
+
var gitCommitConfigSchema = z.object({
|
|
81
|
+
path: z.string().min(1),
|
|
82
|
+
message: z.string().trim().min(1),
|
|
83
|
+
files: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(),
|
|
84
|
+
all: z.boolean().optional(),
|
|
85
|
+
verbose: z.boolean().default(false),
|
|
86
|
+
skipEmpty: z.boolean().default(true)
|
|
87
|
+
}).refine((data) => data.files !== void 0 !== (data.all === true), {
|
|
88
|
+
message: "Provide either files or all: true, not both or neither"
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// src/git-commit-action.ts
|
|
92
|
+
async function isGitRepository(repoPath) {
|
|
93
|
+
try {
|
|
94
|
+
await access(path.join(repoPath, ".git"));
|
|
95
|
+
return true;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function formatZodError(error) {
|
|
101
|
+
return error.issues.map((issue) => `${issue.path.join(".") || "config"}: ${issue.message}`).join("; ");
|
|
102
|
+
}
|
|
103
|
+
function normalizeFiles(files) {
|
|
104
|
+
return Array.isArray(files) ? files : [files];
|
|
105
|
+
}
|
|
106
|
+
async function hasChangesToStage(repoPath, verbose) {
|
|
107
|
+
const { stdout } = await runGit(["status", "--porcelain"], {
|
|
108
|
+
cwd: repoPath,
|
|
109
|
+
verbose
|
|
110
|
+
});
|
|
111
|
+
return stdout.trim().length > 0;
|
|
112
|
+
}
|
|
113
|
+
async function stageFiles(repoPath, config, verbose) {
|
|
114
|
+
if (config.files !== void 0) {
|
|
115
|
+
await runGit(["add", "--", ...normalizeFiles(config.files)], {
|
|
116
|
+
cwd: repoPath,
|
|
117
|
+
verbose
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (config.all) {
|
|
122
|
+
await runGit(["add", "-A"], { cwd: repoPath, verbose });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function hasStagedDiff(repoPath, verbose) {
|
|
126
|
+
try {
|
|
127
|
+
await runGit(["diff", "--cached", "--quiet"], { cwd: repoPath, verbose });
|
|
128
|
+
return false;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (error instanceof Error && error.message.includes("exited with code 1")) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function gitCommitAction(_answers, config) {
|
|
137
|
+
const parsed = gitCommitConfigSchema.safeParse({
|
|
138
|
+
path: config.path ?? process.cwd(),
|
|
139
|
+
message: config.message,
|
|
140
|
+
files: config.files,
|
|
141
|
+
all: config.all,
|
|
142
|
+
verbose: config.verbose ?? false,
|
|
143
|
+
skipEmpty: config.skipEmpty ?? true
|
|
144
|
+
});
|
|
145
|
+
if (!parsed.success) {
|
|
146
|
+
throw new Error(`Invalid gitCommit config: ${formatZodError(parsed.error)}`);
|
|
147
|
+
}
|
|
148
|
+
const { path: repoPath, message, verbose, skipEmpty, files, all } = parsed.data;
|
|
149
|
+
if (!await isGitRepository(repoPath)) {
|
|
150
|
+
throw new Error(`Not a git repository: ${repoPath}`);
|
|
151
|
+
}
|
|
152
|
+
const hasWorkingTreeChanges = await hasChangesToStage(repoPath, verbose);
|
|
153
|
+
if (!hasWorkingTreeChanges && skipEmpty) {
|
|
154
|
+
return "Nothing to commit";
|
|
155
|
+
}
|
|
156
|
+
if (!hasWorkingTreeChanges && !skipEmpty) {
|
|
157
|
+
throw new Error("Nothing to commit");
|
|
158
|
+
}
|
|
159
|
+
await stageFiles(repoPath, { files, all }, verbose);
|
|
160
|
+
const staged = await hasStagedDiff(repoPath, verbose);
|
|
161
|
+
if (!staged && skipEmpty) {
|
|
162
|
+
return "Nothing to commit";
|
|
163
|
+
}
|
|
164
|
+
if (!staged && !skipEmpty) {
|
|
165
|
+
throw new Error("Nothing to commit after staging");
|
|
166
|
+
}
|
|
167
|
+
await runGit(["commit", "-m", message], { cwd: repoPath, verbose });
|
|
168
|
+
const pushResult = await pushToOrigin(repoPath, verbose);
|
|
169
|
+
if (pushResult.ok) {
|
|
170
|
+
return `Committed and pushed to origin: ${message}`;
|
|
171
|
+
}
|
|
172
|
+
if (verbose) {
|
|
173
|
+
console.warn(pushResult.warning);
|
|
174
|
+
}
|
|
175
|
+
return pushResult.warning;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/index.ts
|
|
179
|
+
function registerGitCommitPack(plop) {
|
|
180
|
+
plop.setDefaultInclude({ actionTypes: true });
|
|
181
|
+
plop.setActionType("gitCommit", gitCommitAction);
|
|
182
|
+
}
|
|
183
|
+
export {
|
|
184
|
+
registerGitCommitPack as default,
|
|
185
|
+
gitCommitAction,
|
|
186
|
+
gitCommitConfigSchema
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/git-commit-action.ts","../src/lib/run-git.ts","../src/lib/git-push.ts","../src/schemas/git-commit-config.ts","../src/index.ts"],"sourcesContent":["import { access } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pushToOrigin } from \"./lib/git-push.js\";\nimport { runGit } from \"./lib/run-git.js\";\nimport { type GitCommitActionConfig, gitCommitConfigSchema } from \"./schemas/git-commit-config.js\";\n\nasync function isGitRepository(repoPath: string): Promise<boolean> {\n try {\n await access(path.join(repoPath, \".git\"));\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatZodError(error: {\n issues: Array<{ path: Array<string | number>; message: string }>;\n}) {\n return error.issues\n .map((issue) => `${issue.path.join(\".\") || \"config\"}: ${issue.message}`)\n .join(\"; \");\n}\n\nfunction normalizeFiles(files: string | string[]): string[] {\n return Array.isArray(files) ? files : [files];\n}\n\nasync function hasChangesToStage(repoPath: string, verbose: boolean): Promise<boolean> {\n const { stdout } = await runGit([\"status\", \"--porcelain\"], {\n cwd: repoPath,\n verbose,\n });\n return stdout.trim().length > 0;\n}\n\nasync function stageFiles(\n repoPath: string,\n config: { files?: string | string[]; all?: boolean },\n verbose: boolean,\n): Promise<void> {\n if (config.files !== undefined) {\n await runGit([\"add\", \"--\", ...normalizeFiles(config.files)], {\n cwd: repoPath,\n verbose,\n });\n return;\n }\n\n if (config.all) {\n await runGit([\"add\", \"-A\"], { cwd: repoPath, verbose });\n }\n}\n\nasync function hasStagedDiff(repoPath: string, verbose: boolean): Promise<boolean> {\n try {\n await runGit([\"diff\", \"--cached\", \"--quiet\"], { cwd: repoPath, verbose });\n return false;\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"exited with code 1\")) {\n return true;\n }\n throw error;\n }\n}\n\nexport async function gitCommitAction(\n _answers: unknown,\n config: GitCommitActionConfig & Record<string, unknown>,\n): Promise<string> {\n const parsed = gitCommitConfigSchema.safeParse({\n path: config.path ?? process.cwd(),\n message: config.message,\n files: config.files,\n all: config.all,\n verbose: config.verbose ?? false,\n skipEmpty: config.skipEmpty ?? true,\n });\n\n if (!parsed.success) {\n throw new Error(`Invalid gitCommit config: ${formatZodError(parsed.error)}`);\n }\n\n const { path: repoPath, message, verbose, skipEmpty, files, all } = parsed.data;\n\n if (!(await isGitRepository(repoPath))) {\n throw new Error(`Not a git repository: ${repoPath}`);\n }\n\n const hasWorkingTreeChanges = await hasChangesToStage(repoPath, verbose);\n\n if (!hasWorkingTreeChanges && skipEmpty) {\n return \"Nothing to commit\";\n }\n\n if (!hasWorkingTreeChanges && !skipEmpty) {\n throw new Error(\"Nothing to commit\");\n }\n\n await stageFiles(repoPath, { files, all }, verbose);\n\n const staged = await hasStagedDiff(repoPath, verbose);\n\n if (!staged && skipEmpty) {\n return \"Nothing to commit\";\n }\n\n if (!staged && !skipEmpty) {\n throw new Error(\"Nothing to commit after staging\");\n }\n\n await runGit([\"commit\", \"-m\", message], { cwd: repoPath, verbose });\n\n const pushResult = await pushToOrigin(repoPath, verbose);\n\n if (pushResult.ok) {\n return `Committed and pushed to origin: ${message}`;\n }\n\n if (verbose) {\n console.warn(pushResult.warning);\n }\n\n return pushResult.warning;\n}\n","import { spawn } from \"node:child_process\";\n\nexport type RunGitOptions = {\n cwd: string;\n verbose?: boolean;\n};\n\nexport type RunGitResult = {\n stdout: string;\n stderr: string;\n};\n\nconst didSucceed = (code: number | null): boolean => code === 0;\n\nexport function runGit(args: string[], options: RunGitOptions): Promise<RunGitResult> {\n const { cwd, verbose = false } = options;\n\n return new Promise((resolve, reject) => {\n const child = spawn(\"git\", args, {\n cwd,\n stdio: verbose ? \"inherit\" : \"pipe\",\n });\n\n if (verbose) {\n child.on(\"close\", (code) => {\n if (didSucceed(code)) {\n resolve({ stdout: \"\", stderr: \"\" });\n return;\n }\n\n reject(new Error(`git ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`));\n });\n child.on(\"error\", reject);\n return;\n }\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (chunk: Buffer | string) => {\n stdout += chunk.toString();\n });\n\n child.stderr?.on(\"data\", (chunk: Buffer | string) => {\n stderr += chunk.toString();\n });\n\n child.on(\"close\", (code) => {\n if (didSucceed(code)) {\n resolve({ stdout, stderr });\n return;\n }\n\n const detail = stderr.trim() || stdout.trim();\n reject(\n new Error(\n detail\n ? `git ${args.join(\" \")} failed: ${detail}`\n : `git ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n\n child.on(\"error\", reject);\n });\n}\n","import { runGit } from \"./run-git.js\";\n\nexport type PushResult = { ok: true } | { ok: false; warning: string };\n\nasync function hasOriginRemote(repoPath: string, verbose: boolean): Promise<boolean> {\n try {\n await runGit([\"remote\", \"get-url\", \"origin\"], { cwd: repoPath, verbose });\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function pushToOrigin(repoPath: string, verbose = false): Promise<PushResult> {\n if (!(await hasOriginRemote(repoPath, verbose))) {\n return {\n ok: false,\n warning: \"Committed; push skipped: remote origin is not configured\",\n };\n }\n\n try {\n await runGit([\"push\", \"origin\", \"HEAD\"], { cwd: repoPath, verbose });\n return { ok: true };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n ok: false,\n warning: `Committed; push failed: ${message}`,\n };\n }\n}\n","import { z } from \"zod\";\n\nexport const gitCommitConfigSchema = z\n .object({\n path: z.string().min(1),\n message: z.string().trim().min(1),\n files: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(),\n all: z.boolean().optional(),\n verbose: z.boolean().default(false),\n skipEmpty: z.boolean().default(true),\n })\n .refine((data) => (data.files !== undefined) !== (data.all === true), {\n message: \"Provide either files or all: true, not both or neither\",\n });\n\nexport type GitCommitConfig = z.infer<typeof gitCommitConfigSchema>;\n\nexport type GitCommitActionConfig = {\n path?: string;\n message?: string;\n files?: string | string[];\n all?: boolean;\n verbose?: boolean;\n skipEmpty?: boolean;\n};\n","import type { CustomActionFunction, NodePlopAPI } from \"node-plop\";\nimport { gitCommitAction } from \"./git-commit-action.js\";\nimport {\n type GitCommitActionConfig,\n type GitCommitConfig,\n gitCommitConfigSchema,\n} from \"./schemas/git-commit-config.js\";\n\nexport { gitCommitAction, gitCommitConfigSchema };\nexport type { GitCommitActionConfig, GitCommitConfig };\n\nexport default function registerGitCommitPack(plop: NodePlopAPI): void {\n plop.setDefaultInclude({ actionTypes: true });\n plop.setActionType(\"gitCommit\", gitCommitAction as CustomActionFunction);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "plop-pack-git-commit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PlopJS action pack to stage, commit, and push changes with git",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"node-plop": ">=0.25.0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"zod": "^3.24.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@biomejs/biome": "^1.9.4",
|
|
35
|
+
"@types/node": "^22.13.10",
|
|
36
|
+
"lefthook": "^1.11.3",
|
|
37
|
+
"node-plop": "^0.32.0",
|
|
38
|
+
"tsup": "^8.4.0",
|
|
39
|
+
"typescript": "^5.8.2",
|
|
40
|
+
"vitest": "^3.0.9"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/borjalofe/plop-pack-git-commit.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/borjalofe/plop-pack-git-commit/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/borjalofe/plop-pack-git-commit#readme",
|
|
54
|
+
"keywords": [
|
|
55
|
+
"plop",
|
|
56
|
+
"plopjs",
|
|
57
|
+
"git",
|
|
58
|
+
"commit",
|
|
59
|
+
"generator"
|
|
60
|
+
],
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"lint": "biome check .",
|
|
65
|
+
"format": "biome format --write .",
|
|
66
|
+
"check": "pnpm lint && pnpm test && pnpm build"
|
|
67
|
+
}
|
|
68
|
+
}
|