@wipzent/github-sync 1.0.3 → 1.0.5

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 CHANGED
@@ -1,21 +1,14 @@
1
- MIT License
1
+ Proprietary License
2
2
 
3
- Copyright (c) 2026 Wipzent
3
+ Copyright (c) 2026 Wipzent. All rights reserved.
4
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:
5
+ Commercial use, reproduction, or distribution of this software, in whole or in part,
6
+ is strictly prohibited without the express written permission of Wipzent.
11
7
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
8
+ You may use this software for its intended purpose as a synchronization tool,
9
+ but you are NOT permitted to:
10
+ 1. Copy the source code for redistribution.
11
+ 2. Build derivative products for resale.
12
+ 3. Remove or alter any copyright notices.
14
13
 
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.
14
+ For licensing inquiries, contact engineering@wipzent.com.
package/README.md CHANGED
@@ -36,7 +36,7 @@ npx @wipzent/github-sync sync <repo-name>
36
36
  #### 1. Sync a Repository
37
37
  Automatically sync a personal repo to an organization mirror:
38
38
  ```bash
39
- wipzent-sync sync Nick9311/my-project
39
+ wipzent-sync sync clientUsername/clientRepoName
40
40
  ```
41
41
 
42
42
  #### 2. Manual Setup
package/dist/cli/index.js CHANGED
@@ -1,44 +1,49 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import { syncRepo } from '../mcp/tools/syncRepo.js';
4
- import { createRepo } from '../mcp/tools/createRepo.js';
5
- import { autoSync } from '../mcp/tools/autoSync.js';
6
- import { pushToRemote } from '../git/sync.js';
7
- import fs from 'fs';
8
- import inquirer from 'inquirer';
9
- import chalk from 'chalk';
10
- const program = new Command();
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const syncRepo_js_1 = require("../mcp/tools/syncRepo.js");
9
+ const createRepo_js_1 = require("../mcp/tools/createRepo.js");
10
+ const autoSync_js_1 = require("../mcp/tools/autoSync.js");
11
+ const sync_js_1 = require("../git/sync.js");
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const inquirer_1 = __importDefault(require("inquirer"));
14
+ const chalk_1 = __importDefault(require("chalk"));
15
+ const program = new commander_1.Command();
11
16
  program
12
17
  .name('mcp-github-sync')
13
18
  .description('CLI for GitHub repository synchronization')
14
19
  .version('1.0.0');
15
20
  async function promptRewrite() {
16
- const { shouldRewrite } = await inquirer.prompt([
21
+ const { shouldRewrite } = await inquirer_1.default.prompt([
17
22
  {
18
23
  type: 'confirm',
19
24
  name: 'shouldRewrite',
20
- message: chalk.yellow('Do you want to normalize Git history/author to your personal account?'),
25
+ message: chalk_1.default.yellow('Do you want to normalize Git history/author to your personal account?'),
21
26
  default: false
22
27
  }
23
28
  ]);
24
29
  return shouldRewrite;
25
30
  }
26
31
  async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync = true) {
27
- const { action } = await inquirer.prompt([
32
+ const { action } = await inquirer_1.default.prompt([
28
33
  {
29
34
  type: 'list',
30
35
  name: 'action',
31
- message: chalk.red.bold('Conflict: ') + chalk.white('The organization repository contains changes not in your local/personal repo. How to proceed?'),
36
+ message: chalk_1.default.red.bold('Conflict: ') + chalk_1.default.white('The organization repository contains changes not in your local/personal repo. How to proceed?'),
32
37
  choices: [
33
- { name: chalk.green('Pull & Merge: ') + 'Integrate org changes and resolve locally (Safest)', value: 'merge' },
34
- { name: chalk.red('Overwrite Organization: ') + 'Force push local repo to organization (USE WITH CAUTION)', value: 'force' },
35
- { name: chalk.magenta('Overwrite Personal: ') + 'Force push org content to personal repo (Sync Org -> Personal)', value: 'overwrite-personal' },
38
+ { name: chalk_1.default.green('Pull & Merge: ') + 'Integrate org changes and resolve locally (Safest)', value: 'merge' },
39
+ { name: chalk_1.default.red('Overwrite Organization: ') + 'Force push local repo to organization (USE WITH CAUTION)', value: 'force' },
40
+ { name: chalk_1.default.magenta('Overwrite Personal: ') + 'Force push org content to personal repo (Sync Org -> Personal)', value: 'overwrite-personal' },
36
41
  { name: 'Abort', value: 'abort' }
37
42
  ]
38
43
  }
39
44
  ]);
40
45
  if (action === 'abort') {
41
- console.log(chalk.gray('Sync aborted by user.'));
46
+ console.log(chalk_1.default.gray('Sync aborted by user.'));
42
47
  return;
43
48
  }
44
49
  const forcePush = action === 'force';
@@ -46,7 +51,7 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
46
51
  const overwriteSource = action === 'overwrite-personal';
47
52
  if (isAutoSync) {
48
53
  console.log(`🚀 Continuing auto-sync with resolution: ${action}...`);
49
- const result = await autoSync(personal, shouldRewrite, forcePush, pullChanges, overwriteSource, true);
54
+ const result = await (0, autoSync_js_1.autoSync)(personal, shouldRewrite, forcePush, pullChanges, overwriteSource, true);
50
55
  if (result.success && result.pendingPushes?.length) {
51
56
  await handlePushes(result.localPath, result.pendingPushes);
52
57
  }
@@ -56,7 +61,7 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
56
61
  }
57
62
  else {
58
63
  console.log(`🚀 Continuing sync with resolution: ${action}...`);
59
- const result = await syncRepo(personal, org, shouldRewrite, forcePush, overwriteSource, true);
64
+ const result = await (0, syncRepo_js_1.syncRepo)(personal, org, shouldRewrite, forcePush, overwriteSource, true);
60
65
  if (result.success && result.pendingPushes?.length) {
61
66
  await handlePushes(result.localPath, result.pendingPushes);
62
67
  }
@@ -67,20 +72,20 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
67
72
  }
68
73
  async function handlePushes(localPath, pushes) {
69
74
  if (pushes.length === 0) {
70
- console.log(chalk.gray('No pushes pending.'));
75
+ console.log(chalk_1.default.gray('No pushes pending.'));
71
76
  cleanLocal(localPath);
72
77
  return;
73
78
  }
74
- const { selectedPushes } = await inquirer.prompt([
79
+ const { selectedPushes } = await inquirer_1.default.prompt([
75
80
  {
76
81
  type: 'checkbox',
77
82
  name: 'selectedPushes',
78
- message: chalk.cyan.bold('Review and Select Push Targets') + chalk.gray(' (SPACE to select, ENTER to confirm):'),
83
+ message: chalk_1.default.cyan.bold('Review and Select Push Targets') + chalk_1.default.gray(' (SPACE to select, ENTER to confirm):'),
79
84
  choices: pushes.map(p => {
80
85
  const isOrg = p.description.includes('Organization');
81
86
  const isDanger = p.description.includes('HISTORY REWRITE');
82
- const remoteLabel = isOrg ? chalk.magenta.bold('ORG') : chalk.blue.bold('SRC');
83
- const forceLabel = p.force ? chalk.red.bold(' [FORCE]') : '';
87
+ const remoteLabel = isOrg ? chalk_1.default.magenta.bold('ORG') : chalk_1.default.blue.bold('SRC');
88
+ const forceLabel = p.force ? chalk_1.default.red.bold(' [FORCE]') : '';
84
89
  return {
85
90
  name: `${remoteLabel} | ${p.description}${forceLabel}`,
86
91
  value: p,
@@ -92,20 +97,20 @@ async function handlePushes(localPath, pushes) {
92
97
  }
93
98
  ]);
94
99
  if (selectedPushes.length === 0) {
95
- console.log(chalk.yellow('Pushes cancelled by user.'));
100
+ console.log(chalk_1.default.yellow('Pushes cancelled by user.'));
96
101
  }
97
102
  else {
98
103
  for (const push of selectedPushes) {
99
- await pushToRemote(localPath, push.remote, push.branch, push.force);
104
+ await (0, sync_js_1.pushToRemote)(localPath, push.remote, push.branch, push.force);
100
105
  }
101
- console.log(chalk.green.bold('\nSync completed successfully!'));
106
+ console.log(chalk_1.default.green.bold('\nSync completed successfully!'));
102
107
  }
103
108
  cleanLocal(localPath);
104
109
  }
105
110
  function cleanLocal(localPath) {
106
- if (fs.existsSync(localPath)) {
111
+ if (fs_1.default.existsSync(localPath)) {
107
112
  try {
108
- fs.rmSync(localPath, { recursive: true, force: true });
113
+ fs_1.default.rmSync(localPath, { recursive: true, force: true });
109
114
  }
110
115
  catch (e) {
111
116
  // Ignore
@@ -122,7 +127,7 @@ program
122
127
  const shouldRewrite = await promptRewrite();
123
128
  if (org) {
124
129
  console.log(`🚀 Starting sync: ${personal} -> ${org}`);
125
- const result = await syncRepo(personal, org, shouldRewrite, false, false, true);
130
+ const result = await (0, syncRepo_js_1.syncRepo)(personal, org, shouldRewrite, false, false, true);
126
131
  if (result.isDiverged) {
127
132
  await handleDivergence(personal, org, '', shouldRewrite, false);
128
133
  }
@@ -137,7 +142,7 @@ program
137
142
  }
138
143
  else {
139
144
  console.log(`🚀 Starting auto-sync for: ${personal}`);
140
- const result = await autoSync(personal, shouldRewrite, false, false, false, true);
145
+ const result = await (0, autoSync_js_1.autoSync)(personal, shouldRewrite, false, false, false, true);
141
146
  if (result.isDiverged) {
142
147
  await handleDivergence(personal, '', '', shouldRewrite, true);
143
148
  }
@@ -165,7 +170,7 @@ program
165
170
  try {
166
171
  const shouldRewrite = await promptRewrite();
167
172
  console.log(`🚀 Starting setup: ${personal} -> ${org}`);
168
- const result = await createRepo(personal, org, owner, shouldRewrite, false, false, true);
173
+ const result = await (0, createRepo_js_1.createRepo)(personal, org, owner, shouldRewrite, false, false, true);
169
174
  if (result.isDiverged) {
170
175
  await handleDivergence(personal, org, owner, shouldRewrite, false);
171
176
  }
@@ -1,6 +1,12 @@
1
- import inquirer from 'inquirer';
2
- export async function promptForConflictResolution(fileName) {
3
- const answers = await inquirer.prompt([
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.promptForConflictResolution = promptForConflictResolution;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ async function promptForConflictResolution(fileName) {
9
+ const answers = await inquirer_1.default.prompt([
4
10
  {
5
11
  type: 'list',
6
12
  name: 'resolution',
@@ -1,4 +1,7 @@
1
- export const defaults = {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaults = void 0;
4
+ exports.defaults = {
2
5
  syncInterval: 300, // seconds
3
6
  conflictStrategy: 'ask', // 'ask' | 'personal' | 'org'
4
7
  logLevel: 'info',
@@ -1,5 +1,11 @@
1
- import dotenv from 'dotenv';
2
- dotenv.config();
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.config = void 0;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ dotenv_1.default.config();
3
9
  const requiredEnvVars = [
4
10
  'GITHUB_PERSONAL_PAT',
5
11
  'GITHUB_ORG_PAT',
@@ -13,7 +19,7 @@ requiredEnvVars.forEach((varName) => {
13
19
  throw new Error(`Environment variable ${varName} is missing or has a placeholder value in .env`);
14
20
  }
15
21
  });
16
- export const config = {
22
+ exports.config = {
17
23
  personalPat: process.env.GITHUB_PERSONAL_PAT,
18
24
  orgPat: process.env.GITHUB_ORG_PAT,
19
25
  orgName: process.env.GITHUB_ORG_NAME,
@@ -1,14 +1,18 @@
1
- import { Octokit } from 'octokit';
2
- import { config } from './env.js';
3
- export const personalOctokit = new Octokit({
4
- auth: config.personalPat,
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.orgOctokit = exports.personalOctokit = void 0;
4
+ exports.getOctokit = getOctokit;
5
+ const octokit_1 = require("octokit");
6
+ const env_js_1 = require("./env.js");
7
+ exports.personalOctokit = new octokit_1.Octokit({
8
+ auth: env_js_1.config.personalPat,
5
9
  });
6
- export const orgOctokit = new Octokit({
7
- auth: config.orgPat,
10
+ exports.orgOctokit = new octokit_1.Octokit({
11
+ auth: env_js_1.config.orgPat,
8
12
  });
9
13
  /**
10
14
  * Utility to get Octokit client based on context
11
15
  */
12
- export function getOctokit(context) {
13
- return context === 'personal' ? personalOctokit : orgOctokit;
16
+ function getOctokit(context) {
17
+ return context === 'personal' ? exports.personalOctokit : exports.orgOctokit;
14
18
  }
package/dist/git/clone.js CHANGED
@@ -1,5 +1,8 @@
1
- import { simpleGit } from 'simple-git';
2
- import { config } from '../config/env.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cloneRepo = cloneRepo;
4
+ const simple_git_1 = require("simple-git");
5
+ const env_js_1 = require("../config/env.js");
3
6
  /**
4
7
  * Clones a repository using an authenticated URL.
5
8
  *
@@ -7,9 +10,9 @@ import { config } from '../config/env.js';
7
10
  * @param repo Repository name
8
11
  * @param destination Local directory path to clone into
9
12
  */
10
- export async function cloneRepo(owner, repo, destination) {
11
- const git = simpleGit();
13
+ async function cloneRepo(owner, repo, destination) {
14
+ const git = (0, simple_git_1.simpleGit)();
12
15
  // Construct authenticated URL: https://<token>@github.com/<owner>/<repo>.git
13
- const authUrl = `https://${config.personalPat}@github.com/${owner}/${repo}.git`;
16
+ const authUrl = `https://${env_js_1.config.personalPat}@github.com/${owner}/${repo}.git`;
14
17
  await git.clone(authUrl, destination);
15
18
  }
@@ -1,4 +1,7 @@
1
- import { simpleGit } from 'simple-git';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rewriteHistory = rewriteHistory;
4
+ const simple_git_1 = require("simple-git");
2
5
  /**
3
6
  * Rewrites the entire git history of a repository to a single author/email.
4
7
  * USES git filter-branch --env-filter.
@@ -7,8 +10,8 @@ import { simpleGit } from 'simple-git';
7
10
  * @param name New author name
8
11
  * @param email New author email
9
12
  */
10
- export async function rewriteHistory(path, name, email) {
11
- const git = simpleGit(path);
13
+ async function rewriteHistory(path, name, email) {
14
+ const git = (0, simple_git_1.simpleGit)(path);
12
15
  console.log(`Rewriting history in ${path} to author: ${name} <${email}>...`);
13
16
  // Using git filter-branch --env-filter to rewrite all commits
14
17
  // This script replaces GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, and GIT_COMMITTER_EMAIL for every commit.
package/dist/git/sync.js CHANGED
@@ -1,15 +1,19 @@
1
- import { simpleGit } from 'simple-git';
2
- import { config } from '../config/env.js';
3
- import { rewriteHistory } from './rewriteAuthor.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncBetweenRemotes = syncBetweenRemotes;
4
+ exports.pushToRemote = pushToRemote;
5
+ const simple_git_1 = require("simple-git");
6
+ const env_js_1 = require("../config/env.js");
7
+ const rewriteAuthor_js_1 = require("./rewriteAuthor.js");
4
8
  /**
5
9
  * Performs a safe two-way synchronization between two remotes.
6
10
  * 1. Fetches both sources.
7
11
  * 2. Attempts a clean merge from source into local (target).
8
12
  * 3. Reports conflicts instead of auto-committing messy code.
9
13
  */
10
- export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
11
- const git = simpleGit(localPath);
12
- const branch = config.defaultBranch;
14
+ async function syncBetweenRemotes(localPath, sourceRemote, targetRemote, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
15
+ const git = (0, simple_git_1.simpleGit)(localPath);
16
+ const branch = env_js_1.config.defaultBranch;
13
17
  // 1. Fetch latest from both remotes to see state
14
18
  await git.fetch(sourceRemote, branch);
15
19
  await git.fetch(targetRemote, branch);
@@ -36,8 +40,8 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
36
40
  await git.reset(['--hard', `${targetRemote}/${branch}`]);
37
41
  // 4. Set local author identity for the synchronization commit
38
42
  // This is ALWAYS set to ensure the merge commit is correctly attributed
39
- await git.addConfig('user.name', config.authorName);
40
- await git.addConfig('user.email', config.authorEmail);
43
+ await git.addConfig('user.name', env_js_1.config.authorName);
44
+ await git.addConfig('user.email', env_js_1.config.authorEmail);
41
45
  // 5. Try to merge changes from sourceRemote unless we are overwriting it
42
46
  try {
43
47
  if (!overwriteSource) {
@@ -55,7 +59,7 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
55
59
  }
56
60
  // REWRITE HISTORY AFTER MERGE COMMIT
57
61
  if (shouldRewrite) {
58
- await rewriteHistory(localPath, config.authorName, config.authorEmail);
62
+ await (0, rewriteAuthor_js_1.rewriteHistory)(localPath, env_js_1.config.authorName, env_js_1.config.authorEmail);
59
63
  // Force push is REQUIRED if we rewrite history as SHAs change
60
64
  forcePush = true;
61
65
  }
@@ -134,8 +138,8 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
134
138
  /**
135
139
  * Executes a Git push to a specific remote and branch.
136
140
  */
137
- export async function pushToRemote(localPath, remote, branch, force = false) {
138
- const git = simpleGit(localPath);
141
+ async function pushToRemote(localPath, remote, branch, force = false) {
142
+ const git = (0, simple_git_1.simpleGit)(localPath);
139
143
  console.log(`Pushing to ${remote}/${branch}${force ? ' (FORCE)' : ''}...`);
140
144
  await git.push(remote, branch, force ? ['--force'] : []);
141
145
  }
@@ -1,13 +1,17 @@
1
- import { Octokit } from 'octokit';
2
- import { config } from '../../config/env.js';
3
- export class GitHubClient {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitHubClient = void 0;
4
+ const octokit_1 = require("octokit");
5
+ const env_js_1 = require("../../config/env.js");
6
+ class GitHubClient {
4
7
  personalOctokit;
5
8
  orgOctokit;
6
9
  constructor() {
7
- this.personalOctokit = new Octokit({ auth: config.personalPat });
8
- this.orgOctokit = new Octokit({ auth: config.orgPat });
10
+ this.personalOctokit = new octokit_1.Octokit({ auth: env_js_1.config.personalPat });
11
+ this.orgOctokit = new octokit_1.Octokit({ auth: env_js_1.config.orgPat });
9
12
  }
10
13
  async getRepo(owner, repo) {
11
14
  // API call
12
15
  }
13
16
  }
17
+ exports.GitHubClient = GitHubClient;
@@ -1,7 +1,9 @@
1
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
4
- const server = new Server({
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
4
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
5
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
6
+ const server = new index_js_1.Server({
5
7
  name: "mcp-github-sync",
6
8
  version: "1.0.0",
7
9
  }, {
@@ -9,10 +11,10 @@ const server = new Server({
9
11
  tools: {},
10
12
  },
11
13
  });
12
- import { createRepo } from './tools/createRepo.js';
13
- import { syncRepo } from './tools/syncRepo.js';
14
- import { autoSync } from './tools/autoSync.js';
15
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
14
+ const createRepo_js_1 = require("./tools/createRepo.js");
15
+ const syncRepo_js_1 = require("./tools/syncRepo.js");
16
+ const autoSync_js_1 = require("./tools/autoSync.js");
17
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
16
18
  tools: [
17
19
  {
18
20
  name: "auto_sync",
@@ -52,26 +54,26 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
52
54
  },
53
55
  ],
54
56
  }));
55
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
57
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
56
58
  try {
57
59
  switch (request.params.name) {
58
60
  case "auto_sync": {
59
61
  const args = request.params.arguments;
60
- const result = await autoSync(args.personalRepoName);
62
+ const result = await (0, autoSync_js_1.autoSync)(args.personalRepoName);
61
63
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
62
64
  }
63
65
  case "create_repo": {
64
66
  const args = request.params.arguments;
65
- const result = await createRepo(args.personalRepoName, args.orgRepoName, args.owner);
67
+ const result = await (0, createRepo_js_1.createRepo)(args.personalRepoName, args.orgRepoName, args.owner);
66
68
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
67
69
  }
68
70
  case "sync_repo": {
69
71
  const args = request.params.arguments;
70
- const result = await syncRepo(args.personalRepoName, args.orgRepoName);
72
+ const result = await (0, syncRepo_js_1.syncRepo)(args.personalRepoName, args.orgRepoName);
71
73
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
72
74
  }
73
75
  default:
74
- throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
76
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
75
77
  }
76
78
  }
77
79
  catch (error) {
@@ -82,7 +84,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
82
84
  }
83
85
  });
84
86
  async function main() {
85
- const transport = new StdioServerTransport();
87
+ const transport = new stdio_js_1.StdioServerTransport();
86
88
  await server.connect(transport);
87
89
  console.error("MCP GitHub Sync Server running on stdio");
88
90
  }
@@ -1,22 +1,28 @@
1
- import { orgOctokit, personalOctokit } from '../../config/octokit.js';
2
- import { config } from '../../config/env.js';
3
- import { createRepo } from './createRepo.js';
4
- import { syncRepo } from './syncRepo.js';
5
- import fs from 'fs';
6
- import path from 'path';
7
- import chalk from 'chalk';
8
- import ora from 'ora';
9
- import boxen from 'boxen';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.autoSync = autoSync;
7
+ const octokit_js_1 = require("../../config/octokit.js");
8
+ const env_js_1 = require("../../config/env.js");
9
+ const createRepo_js_1 = require("./createRepo.js");
10
+ const syncRepo_js_1 = require("./syncRepo.js");
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const chalk_1 = __importDefault(require("chalk"));
14
+ const ora_1 = __importDefault(require("ora"));
15
+ const boxen_1 = __importDefault(require("boxen"));
10
16
  /**
11
17
  * Automatically handles the check-create-sync workflow for personal or collaborator repos.
12
18
  *
13
19
  * @param fullRepoName The name of the repository (e.g., 'my-repo' or 'client-owner/client-repo')
14
20
  */
15
- export async function autoSync(fullRepoName, shouldRewrite = false, forcePush = false, pullChanges = false, overwriteSource = false, skipPush = false) {
16
- const spinner = ora();
21
+ async function autoSync(fullRepoName, shouldRewrite = false, forcePush = false, pullChanges = false, overwriteSource = false, skipPush = false) {
22
+ const spinner = (0, ora_1.default)();
17
23
  // Header for the action
18
- console.log(boxen(chalk.cyan.bold('WIPZENT SYNC') + ' ' + chalk.gray('v1.0.1') + '\n' +
19
- chalk.gray('Source: ') + chalk.white.bold(fullRepoName), { padding: 1, margin: { top: 1, bottom: 0 }, borderStyle: 'round', borderColor: 'cyan' }));
24
+ console.log((0, boxen_1.default)(chalk_1.default.cyan.bold('WIPZENT SYNC') + ' ' + chalk_1.default.gray('v1.0.1') + '\n' +
25
+ chalk_1.default.gray('Source: ') + chalk_1.default.white.bold(fullRepoName), { padding: 1, margin: { top: 1, bottom: 0 }, borderStyle: 'round', borderColor: 'cyan' }));
20
26
  // Handle 'owner/repo' format for collaborators/clients
21
27
  let owner;
22
28
  let repoName;
@@ -27,7 +33,7 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
27
33
  }
28
34
  else {
29
35
  // Fallback to authenticated user if only name provided
30
- const { data: user } = await personalOctokit.rest.users.getAuthenticated();
36
+ const { data: user } = await octokit_js_1.personalOctokit.rest.users.getAuthenticated();
31
37
  owner = user.login;
32
38
  repoName = parts[0] || fullRepoName;
33
39
  }
@@ -35,36 +41,36 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
35
41
  repoName = repoName.replace(/\.git$/, '').replace(/\/$/, '');
36
42
  const orgRepoName = repoName;
37
43
  const localDirName = repoName; // Local storage name
38
- const localPath = path.join(process.cwd(), 'temp', localDirName);
44
+ const localPath = path_1.default.join(process.cwd(), 'temp', localDirName);
39
45
  try {
40
46
  // 1. Check if repo exists in the organization
41
- spinner.start(`Verifying ${chalk.bold(orgRepoName)} in ${chalk.bold(config.orgName)}...`);
47
+ spinner.start(`Verifying ${chalk_1.default.bold(orgRepoName)} in ${chalk_1.default.bold(env_js_1.config.orgName)}...`);
42
48
  let exists = false;
43
49
  try {
44
- await orgOctokit.rest.repos.get({
45
- owner: config.orgName,
50
+ await octokit_js_1.orgOctokit.rest.repos.get({
51
+ owner: env_js_1.config.orgName,
46
52
  repo: orgRepoName,
47
53
  });
48
54
  exists = true;
49
- spinner.succeed(chalk.green(`Repository found in organization.`));
55
+ spinner.succeed(chalk_1.default.green(`Repository found in organization.`));
50
56
  }
51
57
  catch (error) {
52
58
  // If it's private and we don't have access, it might return 404
53
59
  // but we'll try to proceed anyway and let createRepo handle the collision
54
- spinner.info(chalk.yellow(`Could not verify existence (may be private or missing).`));
60
+ spinner.info(chalk_1.default.yellow(`Could not verify existence (may be private or missing).`));
55
61
  }
56
62
  // 2. Create/Initialize if needed
57
- if (!exists || !fs.existsSync(localPath)) {
58
- spinner.start(`Initializing mirror: ${chalk.blue(owner + '/' + repoName)} → ${chalk.blue(config.orgName + '/' + orgRepoName)}...`);
59
- const result = await createRepo(repoName, orgRepoName, owner, shouldRewrite, forcePush, pullChanges, skipPush);
63
+ if (!exists || !fs_1.default.existsSync(localPath)) {
64
+ spinner.start(`Initializing mirror: ${chalk_1.default.blue(owner + '/' + repoName)} → ${chalk_1.default.blue(env_js_1.config.orgName + '/' + orgRepoName)}...`);
65
+ const result = await (0, createRepo_js_1.createRepo)(repoName, orgRepoName, owner, shouldRewrite, forcePush, pullChanges, skipPush);
60
66
  if (!result.success && (result.isDiverged || result.requiresManualResolution)) {
61
- spinner.warn(chalk.yellow(`Remote changes detected or conflicts found.`));
67
+ spinner.warn(chalk_1.default.yellow(`Remote changes detected or conflicts found.`));
62
68
  return result;
63
69
  }
64
- spinner.succeed(chalk.green(result.message));
70
+ spinner.succeed(chalk_1.default.green(result.message));
65
71
  // Re-sync if we just created it and skipPush is true
66
72
  if (skipPush && result.success) {
67
- const syncResult = await syncRepo(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
73
+ const syncResult = await (0, syncRepo_js_1.syncRepo)(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
68
74
  // Deduplicate pushes by remote
69
75
  const pushMap = new Map();
70
76
  const allPushes = [...(result.pendingPushes || []), ...(syncResult.pendingPushes || [])];
@@ -85,32 +91,32 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
85
91
  }
86
92
  }
87
93
  else {
88
- spinner.info(chalk.blue(`Using existing local mirror for ${repoName}.`));
94
+ spinner.info(chalk_1.default.blue(`Using existing local mirror for ${repoName}.`));
89
95
  }
90
96
  // 3. Perform the sync
91
97
  spinner.start(`Performing two-way synchronization...`);
92
- const syncResult = await syncRepo(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
98
+ const syncResult = await (0, syncRepo_js_1.syncRepo)(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
93
99
  if (syncResult.success) {
94
- spinner.succeed(chalk.green.bold(`Sync Success!`));
100
+ spinner.succeed(chalk_1.default.green.bold(`Sync Success!`));
95
101
  if (!skipPush) {
96
- console.log(chalk.gray(`\nRemotes updated: origin (client) and upstream (org)\n`));
102
+ console.log(chalk_1.default.gray(`\nRemotes updated: origin (client) and upstream (org)\n`));
97
103
  }
98
104
  return { ...syncResult, localPath };
99
105
  }
100
106
  else if (syncResult.requiresManualResolution) {
101
- spinner.warn(chalk.yellow.bold(`Action Required: Merge Conflicts!`));
102
- console.log(chalk.red(`\nConflicts detected in:`));
103
- syncResult.conflicts.forEach((f) => console.log(chalk.red(` • ${f}`)));
104
- console.log(chalk.white(`\nPlease resolve manually in: `) + chalk.cyan(localPath));
107
+ spinner.warn(chalk_1.default.yellow.bold(`Action Required: Merge Conflicts!`));
108
+ console.log(chalk_1.default.red(`\nConflicts detected in:`));
109
+ syncResult.conflicts.forEach((f) => console.log(chalk_1.default.red(` • ${f}`)));
110
+ console.log(chalk_1.default.white(`\nPlease resolve manually in: `) + chalk_1.default.cyan(localPath));
105
111
  return syncResult;
106
112
  }
107
113
  else {
108
- spinner.fail(chalk.red(`Sync Failed: ${syncResult.message}`));
114
+ spinner.fail(chalk_1.default.red(`Sync Failed: ${syncResult.message}`));
109
115
  return syncResult;
110
116
  }
111
117
  }
112
118
  catch (error) {
113
- spinner.fail(chalk.red(`Error: ${error.message}`));
119
+ spinner.fail(chalk_1.default.red(`Error: ${error.message}`));
114
120
  return {
115
121
  success: false,
116
122
  message: `Auto-sync failed: ${error.message}`,
@@ -118,9 +124,9 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
118
124
  };
119
125
  }
120
126
  finally {
121
- if (fs.existsSync(localPath) && !skipPush) {
127
+ if (fs_1.default.existsSync(localPath) && !skipPush) {
122
128
  try {
123
- fs.rmSync(localPath, { recursive: true, force: true });
129
+ fs_1.default.rmSync(localPath, { recursive: true, force: true });
124
130
  }
125
131
  catch (cleanupError) {
126
132
  // Silently ignore cleanup errors or optionally log them
@@ -1,21 +1,27 @@
1
- import { orgOctokit } from '../../config/octokit.js';
2
- import { config } from '../../config/env.js';
3
- import { cloneRepo } from '../../git/clone.js';
4
- import { rewriteHistory } from '../../git/rewriteAuthor.js';
5
- import { simpleGit } from 'simple-git';
6
- import { pushToRemote } from '../../git/sync.js';
7
- import path from 'path';
8
- import fs from 'fs';
9
- import chalk from 'chalk';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createRepo = createRepo;
7
+ const octokit_js_1 = require("../../config/octokit.js");
8
+ const env_js_1 = require("../../config/env.js");
9
+ const clone_js_1 = require("../../git/clone.js");
10
+ const rewriteAuthor_js_1 = require("../../git/rewriteAuthor.js");
11
+ const simple_git_1 = require("simple-git");
12
+ const sync_js_1 = require("../../git/sync.js");
13
+ const path_1 = __importDefault(require("path"));
14
+ const fs_1 = __importDefault(require("fs"));
15
+ const chalk_1 = __importDefault(require("chalk"));
10
16
  /**
11
17
  * Creates an organization repository and pushes the content of a personal repository to it.
12
18
  */
13
- export async function createRepo(personalRepoName, orgRepoName, owner, shouldRewrite = false, forcePush = false, pullChanges = false, skipPush = false) {
19
+ async function createRepo(personalRepoName, orgRepoName, owner, shouldRewrite = false, forcePush = false, pullChanges = false, skipPush = false) {
14
20
  // 1. Create the repository in the organization
15
21
  let repoCreated = false;
16
22
  try {
17
- await orgOctokit.rest.repos.createInOrg({
18
- org: config.orgName,
23
+ await octokit_js_1.orgOctokit.rest.repos.createInOrg({
24
+ org: env_js_1.config.orgName,
19
25
  name: orgRepoName,
20
26
  private: true,
21
27
  });
@@ -31,31 +37,31 @@ export async function createRepo(personalRepoName, orgRepoName, owner, shouldRew
31
37
  }
32
38
  }
33
39
  // 2. Clone the personal repo locally
34
- const tempDir = path.join(process.cwd(), 'temp', personalRepoName);
35
- if (fs.existsSync(tempDir)) {
36
- fs.rmSync(tempDir, { recursive: true, force: true });
40
+ const tempDir = path_1.default.join(process.cwd(), 'temp', personalRepoName);
41
+ if (fs_1.default.existsSync(tempDir)) {
42
+ fs_1.default.rmSync(tempDir, { recursive: true, force: true });
37
43
  }
38
- await cloneRepo(owner, personalRepoName, tempDir);
44
+ await (0, clone_js_1.cloneRepo)(owner, personalRepoName, tempDir);
39
45
  // 3. Set local author identity for the initial push/clones
40
46
  // This is ALWAYS set to ensure correct attribution for any new actions
41
- const git = simpleGit(tempDir);
42
- await git.addConfig('user.name', config.authorName);
43
- await git.addConfig('user.email', config.authorEmail);
47
+ const git = (0, simple_git_1.simpleGit)(tempDir);
48
+ await git.addConfig('user.name', env_js_1.config.authorName);
49
+ await git.addConfig('user.email', env_js_1.config.authorEmail);
44
50
  if (shouldRewrite) {
45
- await rewriteHistory(tempDir, config.authorName, config.authorEmail);
51
+ await (0, rewriteAuthor_js_1.rewriteHistory)(tempDir, env_js_1.config.authorName, env_js_1.config.authorEmail);
46
52
  // Force push is REQUIRED if we rewrite history as SHAs change
47
53
  forcePush = true;
48
54
  }
49
55
  // 4. Add org repo as remote and push
50
- const orgUrl = `https://${config.orgPat}@github.com/${config.orgName}/${orgRepoName}.git`;
56
+ const orgUrl = `https://${env_js_1.config.orgPat}@github.com/${env_js_1.config.orgName}/${orgRepoName}.git`;
51
57
  try {
52
58
  await git.addRemote('upstream', orgUrl);
53
59
  if (pullChanges) {
54
- console.log(chalk.blue(`Pulling and merging changes from ${orgUrl}...`));
55
- await git.fetch('upstream', config.defaultBranch);
60
+ console.log(chalk_1.default.blue(`Pulling and merging changes from ${orgUrl}...`));
61
+ await git.fetch('upstream', env_js_1.config.defaultBranch);
56
62
  // Attempt a merge
57
63
  try {
58
- await git.merge([`upstream/${config.defaultBranch}`, '--no-commit', '--no-ff']);
64
+ await git.merge([`upstream/${env_js_1.config.defaultBranch}`, '--no-commit', '--no-ff']);
59
65
  const status = await git.status();
60
66
  if (status.conflicted.length > 0) {
61
67
  return {
@@ -89,12 +95,12 @@ export async function createRepo(personalRepoName, orgRepoName, owner, shouldRew
89
95
  const pendingPushes = [];
90
96
  pendingPushes.push({
91
97
  remote: 'upstream',
92
- branch: config.defaultBranch,
98
+ branch: env_js_1.config.defaultBranch,
93
99
  force: forcePush,
94
100
  description: `Organization Repository (upstream)`
95
101
  });
96
102
  if (!skipPush) {
97
- await pushToRemote(tempDir, 'upstream', config.defaultBranch, forcePush);
103
+ await (0, sync_js_1.pushToRemote)(tempDir, 'upstream', env_js_1.config.defaultBranch, forcePush);
98
104
  }
99
105
  return {
100
106
  success: true,
@@ -1,4 +1,7 @@
1
- export async function resolveConflict(fileName, strategy) {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConflict = resolveConflict;
4
+ async function resolveConflict(fileName, strategy) {
2
5
  console.log(`Resolving conflict in ${fileName} using strategy: ${strategy}`);
3
6
  // Conflict resolution logic
4
7
  }
@@ -1,12 +1,18 @@
1
- import { syncBetweenRemotes } from '../../git/sync.js';
2
- import path from 'path';
3
- import fs from 'fs';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.syncRepo = syncRepo;
7
+ const sync_js_1 = require("../../git/sync.js");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
4
10
  /**
5
11
  * Syncs changes between a personal/client repository and an organization repository.
6
12
  */
7
- export async function syncRepo(personalRepoName, orgRepoName, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
8
- const localPath = path.join(process.cwd(), 'temp', personalRepoName);
9
- if (!fs.existsSync(localPath)) {
13
+ async function syncRepo(personalRepoName, orgRepoName, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
14
+ const localPath = path_1.default.join(process.cwd(), 'temp', personalRepoName);
15
+ if (!fs_1.default.existsSync(localPath)) {
10
16
  return {
11
17
  success: false,
12
18
  message: `The repository ${personalRepoName} has not been set up yet.`,
@@ -17,5 +23,5 @@ export async function syncRepo(personalRepoName, orgRepoName, shouldRewrite = fa
17
23
  };
18
24
  }
19
25
  // Perform the safe two-way sync
20
- return await syncBetweenRemotes(localPath, 'origin', 'upstream', shouldRewrite, forcePush, overwriteSource, skipPush);
26
+ return await (0, sync_js_1.syncBetweenRemotes)(localPath, 'origin', 'upstream', shouldRewrite, forcePush, overwriteSource, skipPush);
21
27
  }
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@wipzent/github-sync",
3
- "version": "1.0.3",
4
- "description": "Professional Git history normalization and repository synchronization tool",
5
- "type": "module",
6
- "main": "dist/mcp/server.js",
3
+ "version": "1.0.5",
4
+ "description": "Wipzent Sync: Professional Git history normalization and repository synchronization engine.",
7
5
  "bin": {
8
- "github-sync": "dist/cli/index.js"
6
+ "github-sync": "dist/cli/index.js",
7
+ "wipzent-sync": "dist/cli/index.js"
9
8
  },
10
9
  "files": [
11
10
  "dist",
@@ -13,15 +12,17 @@
13
12
  "LICENSE"
14
13
  ],
15
14
  "keywords": [
16
- "git",
17
- "sync",
18
- "github",
19
- "mcp",
15
+ "wipzent",
16
+ "wipzent-sync",
17
+ "git-sync",
18
+ "github-sync",
20
19
  "history-rewrite",
20
+ "author-normalization",
21
+ "mcp-server",
21
22
  "white-label"
22
23
  ],
23
24
  "author": "Wipzent",
24
- "license": "MIT",
25
+ "license": "Proprietary",
25
26
  "scripts": {
26
27
  "build": "tsc",
27
28
  "start": "node dist/mcp/server.js",