Skip to content

Commit c8ef489

Browse files
committed
build: update dist files after logging improvements
1 parent 3c00ceb commit c8ef489

File tree

5 files changed

+258
-20
lines changed

5 files changed

+258
-20
lines changed

dist/chunk-EMG7656X.js

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// src/core.ts
2+
import fs2 from "fs";
3+
import cp from "child_process";
4+
5+
// src/config.ts
6+
import fs from "fs";
7+
import path from "path";
8+
var DEFAULTS = {
9+
includePatterns: ["*"],
10+
format: "[${ticket}] ${msg}",
11+
fallbackFormat: "[${seg0}] ${msg}",
12+
exclude: ["merge", "squash", "revert"]
13+
};
14+
function loadConfig(cwd) {
15+
try {
16+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf-8"));
17+
const pkgCfg = pkg.commitFromBranch;
18+
const cfg = pkgCfg ?? {};
19+
const include = cfg.includePattern ?? "*";
20+
return {
21+
includePatterns: Array.isArray(include) ? include : [include],
22+
format: cfg.format ?? DEFAULTS.format,
23+
fallbackFormat: cfg.fallbackFormat ?? DEFAULTS.fallbackFormat,
24+
exclude: (cfg.exclude ?? DEFAULTS.exclude).map(String)
25+
};
26+
} catch {
27+
return { ...DEFAULTS };
28+
}
29+
}
30+
31+
// src/tokens.ts
32+
function renderTemplate(tpl, ctx) {
33+
let out = String(tpl);
34+
out = out.replace(/\$\{prefix:(\d+)\}/g, (_m, n) => {
35+
const k = Math.max(0, parseInt(n, 10) || 0);
36+
return ctx.segs.slice(0, k).join("/") || "";
37+
});
38+
out = out.replace(/\$\{seg(\d+)\}/g, (_m, i) => {
39+
const idx = parseInt(i, 10) || 0;
40+
return ctx.segs[idx] || "";
41+
});
42+
return out.replace(/\$\{ticket\}/g, ctx.ticket || "").replace(/\$\{branch\}/g, ctx.branch || "").replace(/\$\{segments\}/g, ctx.segs.join("/")).replace(/\$\{msg\}/g, ctx.msg || "").replace(/\$\{body\}/g, ctx.body || "");
43+
}
44+
45+
// src/core.ts
46+
var createRegexPattern = (pattern) => new RegExp("^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$", "i");
47+
var matchesAnyPattern = (value, patterns) => patterns.some((pattern) => createRegexPattern(pattern).test(value));
48+
var parseEnvironmentFlag = (env, key) => /^(1|true|yes)$/i.test(String(env[key] || ""));
49+
var extractTicketFromBranch = (branch) => (branch.match(/([A-Z]+-\d+)/i)?.[1] || "").toUpperCase();
50+
var getCurrentBranch = () => {
51+
try {
52+
return cp.execSync("git rev-parse --abbrev-ref HEAD", {
53+
stdio: ["ignore", "pipe", "ignore"]
54+
}).toString().trim();
55+
} catch {
56+
return "";
57+
}
58+
};
59+
var escapeRegexSpecialChars = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
60+
var createLogger = (debug) => (...args) => {
61+
if (debug) console.log("[cfb]", ...args);
62+
};
63+
var createInitialState = (opts = {}) => {
64+
const argv = opts.argv ?? process.argv;
65+
const env = opts.env ?? process.env;
66+
const cwd = opts.cwd ?? process.cwd();
67+
const [, , commitMsgPath, source] = argv;
68+
if (!commitMsgPath) return null;
69+
const config = loadConfig(cwd);
70+
const branch = getCurrentBranch();
71+
const ticket = extractTicketFromBranch(branch);
72+
const debug = parseEnvironmentFlag(env, "BRANCH_PREFIX_DEBUG");
73+
const isDryRun = parseEnvironmentFlag(env, "BRANCH_PREFIX_DRYRUN");
74+
let originalMessage = "";
75+
let lines = [];
76+
try {
77+
const body = fs2.readFileSync(commitMsgPath, "utf8");
78+
lines = body.split("\n");
79+
originalMessage = lines[0] ?? "";
80+
} catch {
81+
}
82+
const segs = branch.split("/");
83+
const template = ticket ? config.format : config.fallbackFormat;
84+
const context = { branch, segs, ticket, msg: originalMessage, body: lines.join("\n") };
85+
const renderedMessage = renderTemplate(template, context);
86+
return {
87+
commitMsgPath,
88+
source,
89+
config,
90+
branch,
91+
ticket,
92+
originalMessage,
93+
lines,
94+
context,
95+
template,
96+
renderedMessage,
97+
shouldSkip: false,
98+
isDryRun,
99+
debug
100+
};
101+
};
102+
var validationRules = [
103+
{
104+
name: "source-exclusion",
105+
check: (state) => !state.source || !state.config.exclude.some(
106+
(pattern) => new RegExp(pattern, "i").test(String(state.source))
107+
),
108+
reason: "excluded by source"
109+
},
110+
{
111+
name: "branch-existence",
112+
check: (state) => Boolean(state.branch && state.branch !== "HEAD"),
113+
reason: "no branch or detached HEAD"
114+
},
115+
{
116+
name: "include-pattern-match",
117+
check: (state) => matchesAnyPattern(state.branch, state.config.includePatterns),
118+
reason: "includePattern mismatch"
119+
}
120+
];
121+
var messageProcessors = [
122+
{
123+
name: "template-replacement",
124+
shouldApply: (state) => /\$\{msg\}|\$\{body\}/.test(state.template),
125+
process: (state) => {
126+
if (state.originalMessage === state.renderedMessage) {
127+
return { ...state, shouldSkip: true, skipReason: "message already matches template" };
128+
}
129+
return {
130+
...state,
131+
lines: [state.renderedMessage, ...state.lines.slice(1)]
132+
};
133+
}
134+
},
135+
{
136+
name: "prefix-addition",
137+
shouldApply: (state) => !/\$\{msg\}|\$\{body\}/.test(state.template),
138+
process: (state) => {
139+
const escaped = escapeRegexSpecialChars(state.renderedMessage);
140+
if (new RegExp("^\\s*" + escaped, "i").test(state.originalMessage)) {
141+
return { ...state, shouldSkip: true, skipReason: "prefix already exists" };
142+
}
143+
if (state.ticket) {
144+
const ticketRegex = new RegExp(`\\b${escapeRegexSpecialChars(state.ticket)}\\b`, "i");
145+
if (ticketRegex.test(state.originalMessage)) {
146+
return { ...state, shouldSkip: true, skipReason: "ticket already in message" };
147+
}
148+
}
149+
const firstSeg = state.context.segs[0];
150+
if (firstSeg && firstSeg !== "HEAD") {
151+
const segRegex = new RegExp(`\\b${escapeRegexSpecialChars(firstSeg)}\\b`, "i");
152+
if (segRegex.test(state.originalMessage)) {
153+
return { ...state, shouldSkip: true, skipReason: "branch segment already in message" };
154+
}
155+
}
156+
return {
157+
...state,
158+
lines: [state.renderedMessage + state.originalMessage, ...state.lines.slice(1)]
159+
};
160+
}
161+
}
162+
];
163+
var applyValidationRules = (state) => {
164+
const log = createLogger(state.debug);
165+
log("config", state.config);
166+
for (const rule of validationRules) {
167+
if (!rule.check(state)) {
168+
const contextInfo = state.ticket || state.branch || "unknown";
169+
log(`exit: ${rule.reason}`, `[${rule.name}]`, `context: ${contextInfo}`);
170+
return { ...state, shouldSkip: true, skipReason: rule.reason };
171+
}
172+
}
173+
return state;
174+
};
175+
var logProcessingInfo = (state) => {
176+
const log = createLogger(state.debug);
177+
const hasMsgToken = /\$\{msg\}|\$\{body\}/.test(state.template);
178+
log("branch", `${state.branch}`, "ticket", `${state.ticket || "(none)"}`, "segs", `[${state.context.segs.join(", ")}]`);
179+
log("tpl", `"${state.template}"`);
180+
log("rendered", `"${state.renderedMessage}"`);
181+
log("mode", hasMsgToken ? "replace-line" : "prefix-only", `msg: "${state.originalMessage}"`);
182+
return state;
183+
};
184+
var processMessage = (state) => {
185+
if (state.shouldSkip) return state;
186+
const applicableProcessor = messageProcessors.find(
187+
(processor) => processor.shouldApply(state)
188+
);
189+
if (!applicableProcessor) {
190+
return { ...state, shouldSkip: true, skipReason: "no applicable processor" };
191+
}
192+
return applicableProcessor.process(state);
193+
};
194+
var writeResult = (state) => {
195+
const log = createLogger(state.debug);
196+
if (state.shouldSkip) {
197+
const contextInfo = state.ticket || state.context.segs[0] || "unknown";
198+
log(`skip: ${state.skipReason}`, `[${contextInfo}]`);
199+
return state;
200+
}
201+
if (state.isDryRun) {
202+
log("dry-run: not writing", `[${state.context.branch}]`);
203+
return state;
204+
}
205+
try {
206+
fs2.writeFileSync(state.commitMsgPath, state.lines.join("\n"), "utf8");
207+
log("write ok", `[${state.context.branch}]`, `-> "${state.lines[0]}"`);
208+
} catch (error) {
209+
log("write error:", error, `[${state.context.branch}]`);
210+
}
211+
return state;
212+
};
213+
var pipe = (...functions) => (value) => functions.reduce((acc, fn) => fn(acc), value);
214+
function run(opts = {}) {
215+
const initialState = createInitialState(opts);
216+
if (!initialState) return 0;
217+
const pipeline = pipe(
218+
applyValidationRules,
219+
logProcessingInfo,
220+
processMessage,
221+
writeResult
222+
);
223+
pipeline(initialState);
224+
return 0;
225+
}
226+
227+
export {
228+
createInitialState,
229+
validationRules,
230+
messageProcessors,
231+
applyValidationRules,
232+
processMessage,
233+
run
234+
};

dist/cli.cjs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ var applyValidationRules = (state) => {
190190
log("config", state.config);
191191
for (const rule of validationRules) {
192192
if (!rule.check(state)) {
193-
log(`exit: ${rule.reason}`, rule.name);
193+
const contextInfo = state.ticket || state.branch || "unknown";
194+
log(`exit: ${rule.reason}`, `[${rule.name}]`, `context: ${contextInfo}`);
194195
return { ...state, shouldSkip: true, skipReason: rule.reason };
195196
}
196197
}
@@ -199,10 +200,10 @@ var applyValidationRules = (state) => {
199200
var logProcessingInfo = (state) => {
200201
const log = createLogger(state.debug);
201202
const hasMsgToken = /\$\{msg\}|\$\{body\}/.test(state.template);
202-
log("branch", state.branch, "ticket", state.ticket || "(none)");
203-
log("tpl", state.template);
204-
log("rendered", state.renderedMessage);
205-
log("mode", hasMsgToken ? "replace-line" : "prefix-only");
203+
log("branch", `${state.branch}`, "ticket", `${state.ticket || "(none)"}`, "segs", `[${state.context.segs.join(", ")}]`);
204+
log("tpl", `"${state.template}"`);
205+
log("rendered", `"${state.renderedMessage}"`);
206+
log("mode", hasMsgToken ? "replace-line" : "prefix-only", `msg: "${state.originalMessage}"`);
206207
return state;
207208
};
208209
var processMessage = (state) => {
@@ -218,18 +219,19 @@ var processMessage = (state) => {
218219
var writeResult = (state) => {
219220
const log = createLogger(state.debug);
220221
if (state.shouldSkip) {
221-
log(`skip: ${state.skipReason}`);
222+
const contextInfo = state.ticket || state.context.segs[0] || "unknown";
223+
log(`skip: ${state.skipReason}`, `[${contextInfo}]`);
222224
return state;
223225
}
224226
if (state.isDryRun) {
225-
log("dry-run: not writing");
227+
log("dry-run: not writing", `[${state.context.branch}]`);
226228
return state;
227229
}
228230
try {
229231
import_fs2.default.writeFileSync(state.commitMsgPath, state.lines.join("\n"), "utf8");
230-
log("write ok");
232+
log("write ok", `[${state.context.branch}]`, `-> "${state.lines[0]}"`);
231233
} catch (error) {
232-
log("write error:", error);
234+
log("write error:", error, `[${state.context.branch}]`);
233235
}
234236
return state;
235237
};

dist/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22
import {
33
run
4-
} from "./chunk-NKJYIWBD.js";
4+
} from "./chunk-EMG7656X.js";
55
import {
66
initHusky
77
} from "./chunk-4EHHYCRE.js";

dist/core.cjs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ var applyValidationRules = (state) => {
204204
log("config", state.config);
205205
for (const rule of validationRules) {
206206
if (!rule.check(state)) {
207-
log(`exit: ${rule.reason}`, rule.name);
207+
const contextInfo = state.ticket || state.branch || "unknown";
208+
log(`exit: ${rule.reason}`, `[${rule.name}]`, `context: ${contextInfo}`);
208209
return { ...state, shouldSkip: true, skipReason: rule.reason };
209210
}
210211
}
@@ -213,10 +214,10 @@ var applyValidationRules = (state) => {
213214
var logProcessingInfo = (state) => {
214215
const log = createLogger(state.debug);
215216
const hasMsgToken = /\$\{msg\}|\$\{body\}/.test(state.template);
216-
log("branch", state.branch, "ticket", state.ticket || "(none)");
217-
log("tpl", state.template);
218-
log("rendered", state.renderedMessage);
219-
log("mode", hasMsgToken ? "replace-line" : "prefix-only");
217+
log("branch", `${state.branch}`, "ticket", `${state.ticket || "(none)"}`, "segs", `[${state.context.segs.join(", ")}]`);
218+
log("tpl", `"${state.template}"`);
219+
log("rendered", `"${state.renderedMessage}"`);
220+
log("mode", hasMsgToken ? "replace-line" : "prefix-only", `msg: "${state.originalMessage}"`);
220221
return state;
221222
};
222223
var processMessage = (state) => {
@@ -232,18 +233,19 @@ var processMessage = (state) => {
232233
var writeResult = (state) => {
233234
const log = createLogger(state.debug);
234235
if (state.shouldSkip) {
235-
log(`skip: ${state.skipReason}`);
236+
const contextInfo = state.ticket || state.context.segs[0] || "unknown";
237+
log(`skip: ${state.skipReason}`, `[${contextInfo}]`);
236238
return state;
237239
}
238240
if (state.isDryRun) {
239-
log("dry-run: not writing");
241+
log("dry-run: not writing", `[${state.context.branch}]`);
240242
return state;
241243
}
242244
try {
243245
import_fs2.default.writeFileSync(state.commitMsgPath, state.lines.join("\n"), "utf8");
244-
log("write ok");
246+
log("write ok", `[${state.context.branch}]`, `-> "${state.lines[0]}"`);
245247
} catch (error) {
246-
log("write error:", error);
248+
log("write error:", error, `[${state.context.branch}]`);
247249
}
248250
return state;
249251
};

dist/core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
processMessage,
66
run,
77
validationRules
8-
} from "./chunk-NKJYIWBD.js";
8+
} from "./chunk-EMG7656X.js";
99
export {
1010
applyValidationRules,
1111
createInitialState,

0 commit comments

Comments
 (0)