new-branch 0.4.0 → 0.5.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/README.md CHANGED
@@ -102,6 +102,35 @@ Example:
102
102
  - `date` → YYYY-MM-DD
103
103
  - `dateCompact` → YYYYMMDD
104
104
 
105
+ ### Git Built-ins (derived from current Git repository)
106
+
107
+ - `currentBranch` → Current Git branch name (e.g. `main`, `feature/PROJ-123`)
108
+ - `shortSha` → Short SHA of `HEAD` (e.g. `a1b2c3d`)
109
+ - `repoName` → Repository directory name
110
+ - `userName` → Git user name (`git config user.name`)
111
+ - `lastTag` → Most recent Git tag (`git describe --tags --abbrev=0`)
112
+
113
+ > Note:
114
+ >
115
+ > - Git built-ins are resolved lazily and only when referenced in the pattern.
116
+ > - They are never prompted interactively.
117
+ > - When unavailable (e.g. outside a Git repository), they resolve to an empty string.
118
+
119
+ #### Example with Git built-ins
120
+
121
+ ```bash
122
+ new-branch \
123
+ --pattern "{currentBranch}-{shortSha}-{type}-{title:slugify}" \
124
+ --type feat \
125
+ --title "Improve logging"
126
+ ```
127
+
128
+ Example output:
129
+
130
+ ```
131
+ main-a1b2c3d-feat-improve-logging
132
+ ```
133
+
105
134
  ---
106
135
 
107
136
  ## Built-in Transforms
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import { resolveMissingValues } from "./runtime/resolveMissingValues.js";
7
7
  import { getBuiltinValues } from "./runtime/builtins.js";
8
8
  import { loadProjectConfig } from "./config/loadProjectConfig.js";
9
9
  import { getGitConfig } from "./git/gitConfig.js";
10
+ import { extractGitBuiltinKeysFromPattern, getGitBuiltins, patternNeedsGitBuiltins, } from "./git/gitBuiltins.js";
10
11
  import { sanitizeGitRef } from "./git/sanitizeGitRef.js";
11
12
  import { validateBranchName } from "./git/validateBranchName.js";
12
13
  import { createBranch } from "./git/createBranch.js";
@@ -76,9 +77,21 @@ export async function run() {
76
77
  const astRes = safe(() => parsePattern(patternRes.value));
77
78
  if (!isOk(astRes))
78
79
  fail("Invalid pattern.", astRes.error);
80
+ // Runtime built-ins (date, etc.)
79
81
  const builtinValues = getBuiltinValues();
82
+ // Git built-ins (only if the pattern references them)
83
+ let gitValues = {};
84
+ if (patternNeedsGitBuiltins(patternRes.value)) {
85
+ const gitKeys = extractGitBuiltinKeysFromPattern(patternRes.value);
86
+ const gitRes = await safeAsync(() => getGitBuiltins(gitKeys));
87
+ if (!isOk(gitRes))
88
+ fail("Failed to resolve git builtins.", gitRes.error);
89
+ // GitBuiltins is compatible with RenderValues (string | undefined)
90
+ gitValues = gitRes.value;
91
+ }
80
92
  const initialValues = {
81
93
  ...builtinValues,
94
+ ...gitValues,
82
95
  ...toInitialValues(args),
83
96
  };
84
97
  const valuesRes = await safeAsync(() => resolveMissingValues(astRes.value, initialValues, {
@@ -0,0 +1,79 @@
1
+ import { execa } from "execa";
2
+ import { getGitConfig } from "../git/gitConfig.js";
3
+ export const GIT_BUILTIN_KEYS = [
4
+ "shortSha",
5
+ "currentBranch",
6
+ "userName",
7
+ "repoName",
8
+ "lastTag",
9
+ ];
10
+ function uniqueKeys(keys) {
11
+ return Array.from(new Set(keys));
12
+ }
13
+ function pickAllKeysIfUndefined(keys) {
14
+ return keys?.length ? uniqueKeys(keys) : GIT_BUILTIN_KEYS;
15
+ }
16
+ async function safeExec(args) {
17
+ try {
18
+ const { stdout } = await execa("git", args);
19
+ const value = stdout.trim();
20
+ return value.length ? value : undefined;
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ }
26
+ function deriveRepoName(repoRoot) {
27
+ const parts = repoRoot.split(/[\\/]/).filter(Boolean);
28
+ return parts.length ? parts[parts.length - 1] : undefined;
29
+ }
30
+ const RESOLVERS = {
31
+ shortSha: () => safeExec(["rev-parse", "--short", "HEAD"]),
32
+ currentBranch: async () => {
33
+ const value = await safeExec(["rev-parse", "--abbrev-ref", "HEAD"]);
34
+ return value === "HEAD" ? undefined : value;
35
+ },
36
+ repoName: async () => {
37
+ const repoRoot = await safeExec(["rev-parse", "--show-toplevel"]);
38
+ return repoRoot ? deriveRepoName(repoRoot) : undefined;
39
+ },
40
+ lastTag: () => safeExec(["describe", "--tags", "--abbrev=0"]),
41
+ userName: async () => {
42
+ const value = await getGitConfig("user.name");
43
+ return value ?? process.env.USER ?? process.env.USERNAME ?? undefined;
44
+ },
45
+ };
46
+ async function resolveGitBuiltins(keys) {
47
+ const wanted = pickAllKeysIfUndefined(keys);
48
+ const entries = await Promise.all(wanted.map(async (key) => {
49
+ const value = await RESOLVERS[key]();
50
+ return [key, value];
51
+ }));
52
+ return entries.reduce((acc, [key, value]) => {
53
+ acc[key] = value;
54
+ return acc;
55
+ }, {});
56
+ }
57
+ /**
58
+ * Resolves git-based built-in variables.
59
+ *
60
+ * - If `keys` is omitted, resolves all supported git builtins.
61
+ * - If `keys` is provided, resolves only those keys.
62
+ */
63
+ export async function getGitBuiltins(keys) {
64
+ return resolveGitBuiltins(keys);
65
+ }
66
+ /**
67
+ * Returns true if the pattern contains at least one git builtin key.
68
+ * (Call this before `getGitBuiltins()` if you want to avoid running git at all.)
69
+ */
70
+ export function patternNeedsGitBuiltins(pattern) {
71
+ return GIT_BUILTIN_KEYS.some((key) => pattern.includes(key));
72
+ }
73
+ /**
74
+ * Extracts which git builtin keys are present in the pattern.
75
+ * (Use the returned keys to resolve only what you need.)
76
+ */
77
+ export function extractGitBuiltinKeysFromPattern(pattern) {
78
+ return GIT_BUILTIN_KEYS.filter((key) => pattern.includes(key));
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "new-branch",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Generate and create standardized git branch names from a pattern.",
5
5
  "keywords": [
6
6
  "git",
@@ -26,8 +26,9 @@
26
26
  "lint": "eslint src --ext .ts"
27
27
  },
28
28
  "bin": {
29
- "new-branch": "./dist/cli.js",
30
- "git-nb": "./dist/cli.js"
29
+ "new-branch": "dist/cli.js",
30
+ "git-new-branch": "dist/cli.js",
31
+ "git-nb": "dist/cli.js"
31
32
  },
32
33
  "author": "Teles <github.com/teles>",
33
34
  "license": "MIT",