@bonvoy/plugin-git 0.1.0 → 0.1.1

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/dist/index.d.mts CHANGED
@@ -1,5 +1,23 @@
1
1
  import { BonvoyPlugin } from "@bonvoy/core";
2
2
 
3
+ //#region src/operations.d.ts
4
+ interface GitOperations {
5
+ add(files: string, cwd: string): Promise<void>;
6
+ commit(message: string, cwd: string): Promise<void>;
7
+ tag(name: string, cwd: string): Promise<void>;
8
+ push(cwd: string): Promise<void>;
9
+ pushTags(tags: string[], cwd: string): Promise<void>;
10
+ getCommitsSinceTag(tag: string | null, cwd: string): Promise<Array<{
11
+ hash: string;
12
+ message: string;
13
+ author: string;
14
+ date: string;
15
+ files: string[];
16
+ }>>;
17
+ getLastTag(cwd: string): Promise<string | null>;
18
+ }
19
+ declare const defaultGitOperations: GitOperations;
20
+ //#endregion
3
21
  //#region src/git.d.ts
4
22
  interface GitPluginConfig {
5
23
  commitMessage?: string;
@@ -9,7 +27,8 @@ interface GitPluginConfig {
9
27
  declare class GitPlugin implements BonvoyPlugin {
10
28
  name: string;
11
29
  private config;
12
- constructor(config?: GitPluginConfig);
30
+ private ops;
31
+ constructor(config?: GitPluginConfig, ops?: GitOperations);
13
32
  apply(bonvoy: {
14
33
  hooks: {
15
34
  beforePublish: any;
@@ -20,5 +39,5 @@ declare class GitPlugin implements BonvoyPlugin {
20
39
  private pushChanges;
21
40
  }
22
41
  //#endregion
23
- export { type GitPluginConfig, GitPlugin as default };
42
+ export { type GitOperations, type GitPluginConfig, GitPlugin as default, defaultGitOperations };
24
43
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,15 +1,80 @@
1
1
  import { execa } from "execa";
2
2
 
3
+ //#region src/operations.ts
4
+ const defaultGitOperations = {
5
+ async add(files, cwd) {
6
+ await execa("git", ["add", files], { cwd });
7
+ },
8
+ async commit(message, cwd) {
9
+ await execa("git", [
10
+ "commit",
11
+ "-m",
12
+ message
13
+ ], { cwd });
14
+ },
15
+ async tag(name, cwd) {
16
+ await execa("git", ["tag", name], { cwd });
17
+ },
18
+ async push(cwd) {
19
+ await execa("git", ["push"], { cwd });
20
+ },
21
+ async pushTags(tags, cwd) {
22
+ await execa("git", [
23
+ "push",
24
+ "origin",
25
+ ...tags
26
+ ], { cwd });
27
+ },
28
+ async getLastTag(cwd) {
29
+ try {
30
+ const { stdout } = await execa("git", [
31
+ "describe",
32
+ "--tags",
33
+ "--abbrev=0"
34
+ ], { cwd });
35
+ return stdout.trim() || null;
36
+ } catch {
37
+ return null;
38
+ }
39
+ },
40
+ async getCommitsSinceTag(tag, cwd) {
41
+ const { stdout } = await execa("git", [
42
+ "log",
43
+ "--pretty=format:%H|%s|%an|%aI",
44
+ "--name-only",
45
+ tag ? `${tag}..HEAD` : "HEAD"
46
+ ], { cwd });
47
+ if (!stdout.trim()) return [];
48
+ const commits = [];
49
+ const entries = stdout.split("\n\n");
50
+ for (const entry of entries) {
51
+ const [firstLine, ...fileLines] = entry.split("\n");
52
+ const [hash, message, author, date] = firstLine.split("|");
53
+ if (hash && message) commits.push({
54
+ hash,
55
+ message,
56
+ author: author || "",
57
+ date: date || "",
58
+ files: fileLines.filter((f) => f.trim())
59
+ });
60
+ }
61
+ return commits;
62
+ }
63
+ };
64
+
65
+ //#endregion
3
66
  //#region src/git.ts
4
67
  var GitPlugin = class {
5
68
  name = "git";
6
69
  config;
7
- constructor(config = {}) {
70
+ ops;
71
+ constructor(config = {}, ops) {
8
72
  this.config = {
9
- commitMessage: config.commitMessage ?? "chore: release {packages}",
73
+ commitMessage: config.commitMessage ?? "chore(release): :bookmark: {packages} [skip ci]",
10
74
  tagFormat: config.tagFormat ?? "{name}@{version}",
11
75
  push: config.push ?? true
12
76
  };
77
+ this.ops = ops ?? defaultGitOperations;
13
78
  }
14
79
  apply(bonvoy) {
15
80
  bonvoy.hooks.beforePublish.tapPromise(this.name, async (context) => {
@@ -24,40 +89,35 @@ var GitPlugin = class {
24
89
  });
25
90
  }
26
91
  async commitChanges(context) {
27
- const { packages, isDryRun } = context;
92
+ const { packages, isDryRun, rootPath } = context;
28
93
  if (packages.length === 0) return;
29
- if (!isDryRun) await execa("git", ["add", "."]);
30
94
  const packageNames = packages.map((pkg) => pkg.name).join(", ");
31
95
  const message = this.config.commitMessage.replace("{packages}", packageNames);
32
96
  console.log(` Commit message: "${message}"`);
33
- if (!isDryRun) await execa("git", [
34
- "commit",
35
- "-m",
36
- message
37
- ]);
97
+ if (!isDryRun) {
98
+ await this.ops.add(".", rootPath);
99
+ await this.ops.commit(message, rootPath);
100
+ }
38
101
  }
39
102
  async createTags(context) {
40
- const { packages, isDryRun } = context;
103
+ const { packages, isDryRun, rootPath } = context;
41
104
  for (const pkg of packages) {
42
105
  const tag = this.config.tagFormat.replace("{name}", pkg.name).replace("{version}", pkg.version);
43
106
  console.log(` Tag: ${tag}`);
44
- if (!isDryRun) await execa("git", ["tag", tag]);
107
+ if (!isDryRun) await this.ops.tag(tag, rootPath);
45
108
  }
46
109
  }
47
110
  async pushChanges(context) {
48
- const { packages, isDryRun } = context;
111
+ const { packages, isDryRun, rootPath } = context;
49
112
  console.log(" Pushing commits and tags...");
50
113
  if (!isDryRun) {
51
- await execa("git", ["push"]);
52
- await execa("git", [
53
- "push",
54
- "origin",
55
- ...packages.map((pkg) => this.config.tagFormat.replace("{name}", pkg.name).replace("{version}", pkg.version))
56
- ]);
114
+ await this.ops.push(rootPath);
115
+ const tags = packages.map((pkg) => this.config.tagFormat.replace("{name}", pkg.name).replace("{version}", pkg.version));
116
+ await this.ops.pushTags(tags, rootPath);
57
117
  }
58
118
  }
59
119
  };
60
120
 
61
121
  //#endregion
62
- export { GitPlugin as default };
122
+ export { GitPlugin as default, defaultGitOperations };
63
123
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/git.ts"],"sourcesContent":["import type { BonvoyPlugin, PublishContext } from '@bonvoy/core';\nimport { execa } from 'execa';\n\nexport interface GitPluginConfig {\n commitMessage?: string;\n tagFormat?: string;\n push?: boolean;\n}\n\nexport default class GitPlugin implements BonvoyPlugin {\n name = 'git';\n\n private config: Required<GitPluginConfig>;\n\n constructor(config: GitPluginConfig = {}) {\n this.config = {\n commitMessage: config.commitMessage ?? 'chore: release {packages}',\n tagFormat: config.tagFormat ?? '{name}@{version}',\n push: config.push ?? true,\n };\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Hook types are complex and vary by implementation\n apply(bonvoy: { hooks: { beforePublish: any } }): void {\n bonvoy.hooks.beforePublish.tapPromise(this.name, async (context: PublishContext) => {\n console.log('📝 Committing changes...');\n await this.commitChanges(context);\n console.log('🏷️ Creating git tags...');\n await this.createTags(context);\n\n if (this.config.push) {\n console.log('⬆️ Pushing to remote...');\n await this.pushChanges(context);\n }\n });\n }\n\n private async commitChanges(context: PublishContext): Promise<void> {\n const { packages, isDryRun } = context;\n\n if (packages.length === 0) return;\n\n // Add all changed files\n if (!isDryRun) {\n await execa('git', ['add', '.']);\n }\n\n // Create commit message\n const packageNames = packages.map((pkg) => pkg.name).join(', ');\n const message = this.config.commitMessage.replace('{packages}', packageNames);\n\n console.log(` Commit message: \"${message}\"`);\n\n // Commit changes\n if (!isDryRun) {\n await execa('git', ['commit', '-m', message]);\n }\n }\n\n private async createTags(context: PublishContext): Promise<void> {\n const { packages, isDryRun } = context;\n\n for (const pkg of packages) {\n const tag = this.config.tagFormat\n .replace('{name}', pkg.name)\n .replace('{version}', pkg.version);\n\n console.log(` Tag: ${tag}`);\n\n if (!isDryRun) {\n await execa('git', ['tag', tag]);\n }\n }\n }\n\n private async pushChanges(context: PublishContext): Promise<void> {\n const { packages, isDryRun } = context;\n\n console.log(' Pushing commits and tags...');\n\n if (!isDryRun) {\n // Push commits\n await execa('git', ['push']);\n\n // Push all tags at once to avoid race condition with GitHub\n const tags = packages.map((pkg) =>\n this.config.tagFormat.replace('{name}', pkg.name).replace('{version}', pkg.version),\n );\n await execa('git', ['push', 'origin', ...tags]);\n }\n }\n}\n"],"mappings":";;;AASA,IAAqB,YAArB,MAAuD;CACrD,OAAO;CAEP,AAAQ;CAER,YAAY,SAA0B,EAAE,EAAE;AACxC,OAAK,SAAS;GACZ,eAAe,OAAO,iBAAiB;GACvC,WAAW,OAAO,aAAa;GAC/B,MAAM,OAAO,QAAQ;GACtB;;CAIH,MAAM,QAAiD;AACrD,SAAO,MAAM,cAAc,WAAW,KAAK,MAAM,OAAO,YAA4B;AAClF,WAAQ,IAAI,2BAA2B;AACvC,SAAM,KAAK,cAAc,QAAQ;AACjC,WAAQ,IAAI,4BAA4B;AACxC,SAAM,KAAK,WAAW,QAAQ;AAE9B,OAAI,KAAK,OAAO,MAAM;AACpB,YAAQ,IAAI,2BAA2B;AACvC,UAAM,KAAK,YAAY,QAAQ;;IAEjC;;CAGJ,MAAc,cAAc,SAAwC;EAClE,MAAM,EAAE,UAAU,aAAa;AAE/B,MAAI,SAAS,WAAW,EAAG;AAG3B,MAAI,CAAC,SACH,OAAM,MAAM,OAAO,CAAC,OAAO,IAAI,CAAC;EAIlC,MAAM,eAAe,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK;EAC/D,MAAM,UAAU,KAAK,OAAO,cAAc,QAAQ,cAAc,aAAa;AAE7E,UAAQ,IAAI,sBAAsB,QAAQ,GAAG;AAG7C,MAAI,CAAC,SACH,OAAM,MAAM,OAAO;GAAC;GAAU;GAAM;GAAQ,CAAC;;CAIjD,MAAc,WAAW,SAAwC;EAC/D,MAAM,EAAE,UAAU,aAAa;AAE/B,OAAK,MAAM,OAAO,UAAU;GAC1B,MAAM,MAAM,KAAK,OAAO,UACrB,QAAQ,UAAU,IAAI,KAAK,CAC3B,QAAQ,aAAa,IAAI,QAAQ;AAEpC,WAAQ,IAAI,UAAU,MAAM;AAE5B,OAAI,CAAC,SACH,OAAM,MAAM,OAAO,CAAC,OAAO,IAAI,CAAC;;;CAKtC,MAAc,YAAY,SAAwC;EAChE,MAAM,EAAE,UAAU,aAAa;AAE/B,UAAQ,IAAI,gCAAgC;AAE5C,MAAI,CAAC,UAAU;AAEb,SAAM,MAAM,OAAO,CAAC,OAAO,CAAC;AAM5B,SAAM,MAAM,OAAO;IAAC;IAAQ;IAAU,GAHzB,SAAS,KAAK,QACzB,KAAK,OAAO,UAAU,QAAQ,UAAU,IAAI,KAAK,CAAC,QAAQ,aAAa,IAAI,QAAQ,CACpF;IAC6C,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/operations.ts","../src/git.ts"],"sourcesContent":["import { execa } from 'execa';\n\nexport interface GitOperations {\n add(files: string, cwd: string): Promise<void>;\n commit(message: string, cwd: string): Promise<void>;\n tag(name: string, cwd: string): Promise<void>;\n push(cwd: string): Promise<void>;\n pushTags(tags: string[], cwd: string): Promise<void>;\n getCommitsSinceTag(\n tag: string | null,\n cwd: string,\n ): Promise<\n Array<{ hash: string; message: string; author: string; date: string; files: string[] }>\n >;\n getLastTag(cwd: string): Promise<string | null>;\n}\n\nexport const defaultGitOperations: GitOperations = {\n async add(files, cwd) {\n await execa('git', ['add', files], { cwd });\n },\n\n async commit(message, cwd) {\n await execa('git', ['commit', '-m', message], { cwd });\n },\n\n async tag(name, cwd) {\n await execa('git', ['tag', name], { cwd });\n },\n\n async push(cwd) {\n await execa('git', ['push'], { cwd });\n },\n\n async pushTags(tags, cwd) {\n await execa('git', ['push', 'origin', ...tags], { cwd });\n },\n\n async getLastTag(cwd) {\n try {\n const { stdout } = await execa('git', ['describe', '--tags', '--abbrev=0'], { cwd });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n },\n\n async getCommitsSinceTag(tag, cwd) {\n const range = tag ? `${tag}..HEAD` : 'HEAD';\n const { stdout } = await execa(\n 'git',\n ['log', '--pretty=format:%H|%s|%an|%aI', '--name-only', range],\n { cwd },\n );\n\n if (!stdout.trim()) return [];\n\n const commits: Array<{\n hash: string;\n message: string;\n author: string;\n date: string;\n files: string[];\n }> = [];\n const entries = stdout.split('\\n\\n');\n\n for (const entry of entries) {\n const lines = entry.split('\\n');\n const [firstLine, ...fileLines] = lines;\n const [hash, message, author, date] = firstLine.split('|');\n if (hash && message) {\n commits.push({\n hash,\n message,\n author: author || '',\n date: date || '',\n files: fileLines.filter((f) => f.trim()),\n });\n }\n }\n\n return commits;\n },\n};\n","import type { BonvoyPlugin, PublishContext } from '@bonvoy/core';\n\nimport { defaultGitOperations, type GitOperations } from './operations.js';\n\nexport interface GitPluginConfig {\n commitMessage?: string;\n tagFormat?: string;\n push?: boolean;\n}\n\nexport default class GitPlugin implements BonvoyPlugin {\n name = 'git';\n\n private config: Required<GitPluginConfig>;\n private ops: GitOperations;\n\n constructor(config: GitPluginConfig = {}, ops?: GitOperations) {\n this.config = {\n commitMessage: config.commitMessage ?? 'chore(release): :bookmark: {packages} [skip ci]',\n tagFormat: config.tagFormat ?? '{name}@{version}',\n push: config.push ?? true,\n };\n this.ops = ops ?? defaultGitOperations;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Hook types are complex and vary by implementation\n apply(bonvoy: { hooks: { beforePublish: any } }): void {\n bonvoy.hooks.beforePublish.tapPromise(this.name, async (context: PublishContext) => {\n console.log('📝 Committing changes...');\n await this.commitChanges(context);\n console.log('🏷️ Creating git tags...');\n await this.createTags(context);\n\n if (this.config.push) {\n console.log('⬆️ Pushing to remote...');\n await this.pushChanges(context);\n }\n });\n }\n\n private async commitChanges(context: PublishContext): Promise<void> {\n const { packages, isDryRun, rootPath } = context;\n\n if (packages.length === 0) return;\n\n const packageNames = packages.map((pkg) => pkg.name).join(', ');\n const message = this.config.commitMessage.replace('{packages}', packageNames);\n\n console.log(` Commit message: \"${message}\"`);\n\n if (!isDryRun) {\n await this.ops.add('.', rootPath);\n await this.ops.commit(message, rootPath);\n }\n }\n\n private async createTags(context: PublishContext): Promise<void> {\n const { packages, isDryRun, rootPath } = context;\n\n for (const pkg of packages) {\n const tag = this.config.tagFormat\n .replace('{name}', pkg.name)\n .replace('{version}', pkg.version);\n\n console.log(` Tag: ${tag}`);\n\n if (!isDryRun) {\n await this.ops.tag(tag, rootPath);\n }\n }\n }\n\n private async pushChanges(context: PublishContext): Promise<void> {\n const { packages, isDryRun, rootPath } = context;\n\n console.log(' Pushing commits and tags...');\n\n if (!isDryRun) {\n await this.ops.push(rootPath);\n\n const tags = packages.map((pkg) =>\n this.config.tagFormat.replace('{name}', pkg.name).replace('{version}', pkg.version),\n );\n await this.ops.pushTags(tags, rootPath);\n }\n }\n}\n\nexport { defaultGitOperations, type GitOperations } from './operations.js';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonvoy/plugin-git",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Git operations plugin for bonvoy",
5
5
  "keywords": [
6
6
  "bonvoy",
@@ -27,7 +27,6 @@
27
27
  ".": "./dist/index.mjs",
28
28
  "./package.json": "./package.json"
29
29
  },
30
- "types": "./dist/index.d.mts",
31
30
  "files": [
32
31
  "dist"
33
32
  ],