forge-sync 0.0.0 → 0.0.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/README.md CHANGED
@@ -1,126 +1,150 @@
1
- # forge-sync <img src="https://raw.githubusercontent.com/mayank1513/mayank1513/main/popper.png" style="height: 40px"/>
1
+ # @turboforge/sync
2
2
 
3
- [![CI](https://github.com/react18-tools/turbo-forge/actions/workflows/ci.yml/badge.svg)](https://github.com/react18-tools/turbo-forge/actions/workflows/ci.yml)
4
- [![codecov](https://codecov.io/gh/react18-tools/turbo-forge/graph/badge.svg?flag=forge-sync)](https://codecov.io/gh/react18-tools/turbo-forge/tree/main/packages/forge-sync)
5
- [![Version](https://img.shields.io/npm/v/forge-sync.svg?colorB=green)](https://www.npmjs.com/package/forge-sync)
6
- [![Downloads](https://img.jsdelivr.net/img.shields.io/npm/d18m/forge-sync.svg)](https://www.npmjs.com/package/forge-sync)
7
- ![npm bundle size](https://img.shields.io/bundlephobia/minzip/forge-sync)
3
+ Keep a real monorepo aligned with its upstream template after the repo has already diverged.
8
4
 
9
- > **The authoritative synchronization engine for Turbo-Forge monorepos.**
10
- > Keep your monorepo's tooling, configurations, and core dependencies in perfect sync with the upstream template.
5
+ <p className="flex gap-2">
6
+ <a href="https://github.com/turboforge-dev/turboforge/actions/workflows/ci.yml" rel="noopener noreferrer">
7
+ <img alt="CI" src="https://github.com/turboforge-dev/turboforge/actions/workflows/ci.yml/badge.svg" />
8
+ </a>
9
+ <a href="https://codecov.io/gh/turboforge-dev/turboforge/tree/main/packages/forge-sync" rel="noopener noreferrer">
10
+ <img alt="codecov" src="https://codecov.io/gh/turboforge-dev/turboforge/graph/badge.svg?flag=forge-sync" />
11
+ </a>
12
+ <a href="https://npmjs.com/package/forge-sync" rel="noopener noreferrer">
13
+ <img alt="npm version" src="https://img.shields.io/npm/v/forge-sync" />
14
+ </a>
15
+ <a href="https://npmjs.com/package/forge-sync" rel="noopener noreferrer">
16
+ <img alt="npm downloads" src="https://img.shields.io/npm/d18m/forge-sync" />
17
+ </a>
18
+ <a href="https://npmjs.com/package/forge-sync" rel="noopener noreferrer">
19
+ <img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/forge-sync" />
20
+ </a>
21
+ <img alt="license" src="https://img.shields.io/npm/l/forge-sync" />
22
+ </p>
11
23
 
12
- `forge-sync` automates the complex process of pulling updates from a template repository (like verified `turbo-forge` templates) into your existing project. It handles git operations, generates patches, and intelligently resolves conflicts—especially in `package.json` files.
24
+ `@turboforge/sync` exists because templates are great right up until the moment your repo becomes real. After that, every upstream improvement turns into manual diffing, selective copy-paste, and a quiet fear of breaking local customizations.
13
25
 
14
- ---
26
+ This package is the maintenance story inside Turboforge.
15
27
 
16
- ## Features
28
+ Part of the Turboforge system:
17
29
 
18
- - **🛡️ Smart Git Safety**: Automatically checks for a clean git tree before running to prevent data loss.
19
- - **🔄 Three-Way Merge**: Uses advanced 3-way merging to apply template updates while preserving your custom changes.
20
- - **📦 Intelligent Dependency Resolution**: Special logic for `package.json` to merge dependencies using SemVer rules (e.g., picking the higher version) and resolving conflicts automatically.
21
- - **🔍 Dry Run Mode**: Preview exactly what patches will be applied without making any changes.
22
- - **⚙️ Flexible Configuration**: Configure via CLI flags or a persistent `forge-sync.config.json` file.
23
- - **🚫 Exclusion Support**: Easily exclude specific files or directories from being overwritten (e.g., `docs/`, `examples/`).
30
+ - use `@turboforge/sync` to keep the repo shape current
31
+ - use [`@turboforge/cli-kit`](/c:/Users/G/web/open-source/turbo-forge/packages/cli-kit/README.md) to build the repo-aware commands around that workflow
24
32
 
25
- ---
33
+ ## Highlights
34
+
35
+ - Pull upstream template changes into a repo that has already diverged.
36
+ - Preview upgrades before applying them.
37
+ - Resolve `package.json` conflicts with package-aware merge rules.
38
+
39
+ ## Why It Exists
40
+
41
+ Templates stop helping once you have edited them.
42
+
43
+ From that point on, most teams choose one of two bad options:
44
+
45
+ - never pull improvements from the source template again
46
+ - manually replay changes and hope nothing important was missed
47
+
48
+ `@turboforge/sync` gives you a third option: treat template updates as an explicit sync workflow.
49
+
50
+ ## Real Example
51
+
52
+ Your monorepo started from an internal template six months ago.
53
+
54
+ Since then, the template added:
55
+
56
+ - a stricter Biome config
57
+ - improved release automation
58
+ - better docs generation
59
+
60
+ Your repo also added custom apps, custom package scripts, and local dependency choices.
61
+
62
+ Instead of copying files by hand, `@turboforge/sync` fetches the upstream template, computes the diff from your last sync point, applies a patch, and resolves `package.json` conflicts with package-aware rules.
63
+
64
+ ## When To Use It
65
+
66
+ - You maintain a repo that started from a template and still wants to inherit template improvements.
67
+ - You want upgrades to be repeatable, reviewable, and less dependent on one maintainer's memory.
68
+ - You need a system for "template drift," not just a one-time scaffold.
69
+
70
+ ## When Not To Use It
71
+
72
+ - Your repo has no upstream template relationship.
73
+ - You want to generate a new repo from scratch; use a starter for that.
74
+ - You need a full project migration across unrelated architectures.
26
75
 
27
76
  ## 📦 Installation
28
77
 
29
- To use it as a CLI tool in your project:
30
78
 
31
- ```bash
32
- $ pnpm add -D forge-sync
33
- ```
79
+ > [!TIP]
80
+ > **This package (forge-sync) is an official alias of [@turboforge/sync](https://npmjs.com/package/@turboforge/sync).**
34
81
 
35
- Or run it directly with `npx` / `pnpx`:
82
+ <details>
83
+ <summary>Why does this exist?</summary>
36
84
 
37
- ```bash
38
- $ pnpx forge-sync
39
- ```
85
+ We provide this package to offer shorter import paths and improved discoverability. While both packages provide identical functionality, **@turboforge/sync** is the primary source of truth.
86
+ </details>
40
87
 
41
- ---
88
+ <details>
89
+ <summary>Which one should I use?</summary>
42
90
 
43
- ## 🚀 Usage
91
+ * **Use forge-sync** if you prefer the shorter name or specific branding or ESM Only.
92
+ * **Use @turboforge/sync** for the most stable long-term reference and standard alignment.
44
93
 
45
- Run the sync command from the root of your monorepo:
94
+ | Feature | @turboforge/sync | forge-sync |
95
+ | --- | --- | --- |
96
+ | **Source Code** | ✅ Primary | 🔗 Proxy |
97
+ | **Updates** | Immediate | Synchronized (Immediately) |
98
+ | **Bundle Size** | 100% | 100% (Zero overhead) |
99
+ | **Format** | ESM + CJS | ESM Only |
100
+ | **Maintenance** | ✅ Primary | 🔗 Proxy (inherits) |
101
+ | **Security** | ✅ Primary | 🔗 Proxy (inherits) |
46
102
 
47
- ```bash
48
- $ pnpm forge-sync
49
- ```
103
+ </details>
50
104
 
51
- ### Common Options
105
+ <details>
106
+ <summary>Maintenance & Support</summary>
52
107
 
53
- | Option | Description | Default |
54
- | :--- | :--- | :--- |
55
- | `--dry-run` | Simulate the sync and show generated patches without applying changes. | `false` |
56
- | `--exclude <paths>` | Comma-separated list of paths to ignore during sync. | `[]` |
57
- | `--template-url <url>`| URL of the upstream template repository. | `.../forge-template.git` |
58
- | `--base-ref <ref>` | Base commit/tag to calculate diffs from. Auto-detected from `.forge-meta.json`. | *Auto* |
59
- | `--target-ref <ref>` | Target commit/tag/branch to update to. | `main` |
60
- | `--log-level <level>` | Set logging verbosity (`debug`, `info`, `warn`, `error`). | `info` |
61
- | `-i, --init` | Generate a default configuration file. | - |
108
+ > **Security:** Security audits are performed on the canonical package; this alias inherits all security patches automatically.
109
+ </details>
110
+
111
+ ---
62
112
 
63
- ### Examples
64
113
 
65
- **Simulate an update:**
66
- ```bash
67
- forge-sync --dry-run
68
- ```
69
114
 
70
- **Exclude functionality you've heavily customized:**
115
+ To use it as a CLI tool in your project:
116
+
71
117
  ```bash
72
- forge-sync --exclude "apps/docs,tooling/custom-script.ts"
118
+ pnpm add -D @turboforge/sync
73
119
  ```
74
120
 
75
- **Update from a specific branch:**
121
+ Or run it directly with `npx`:
122
+
76
123
  ```bash
77
- forge-sync --target-ref "v2-beta"
124
+ npx @turboforge/sync
78
125
  ```
79
126
 
80
- ---
127
+ ## Example
81
128
 
82
- ## 🔧 Configuration
83
-
84
- Create a `forge-sync.config.json` file in your root directory for persistent settings:
85
-
86
- ```json
87
- {
88
- "templateUrl": "https://github.com/my-org/my-custom-template.git",
89
- "excludePaths": [
90
- "pnpm-lock.yaml",
91
- "apps/web/public"
92
- ],
93
- "postSync": [
94
- "pnpm install",
95
- "pnpm format"
96
- ],
97
- "logLevel": "info"
98
- }
99
- ```
129
+ Preview what changed upstream before touching the repo:
100
130
 
101
- Generate this file automatically:
102
131
  ```bash
103
- forge-sync --init
132
+ npx @turboforge/sync --dry-run
104
133
  ```
105
134
 
106
- ---
135
+ Exclude heavily customized paths during sync:
107
136
 
108
- ## 🧠 How it Works
137
+ ```bash
138
+ npx @turboforge/sync --exclude "apps/web,tooling/custom"
139
+ ```
109
140
 
110
- 1. **Safety Check**: Verifies your working directory is clean.
111
- 2. **Fetch**: Adds the template as a temporary remote and fetches the target reference.
112
- 3. **Diff**: Calculates the difference between your last sync point (stored in `.forge-meta.json`) and the target.
113
- 4. **Patch**: Generates and applies a git patch using a 3-way merge strategy.
114
- 5. **Resolve**:
115
- * Standard files use git's automatic conflict markers.
116
- * `package.json` files are parsed, and dependencies are merged intelligently (e.g., `^1.0.0` vs `^1.1.0` -> `^1.1.0`).
117
- 6. **Cleanup**: Removes temporary remotes and artifacts.
141
+ ## Mental Model
118
142
 
119
- ---
143
+ `@turboforge/sync` is not a scaffolder.
120
144
 
121
- ## License
145
+ It is a bridge between:
122
146
 
123
- MIT © [Mayank Kumar Chaudhari](https://mayankchaudhari.com)
124
- <hr />
147
+ - the template you started from
148
+ - the customized repo you run today
125
149
 
126
- <p align="center" style="text-align:center">with 💖 by <a href="https://mayankchaudhari.com" target="_blank">Mayank Kumar Chaudhari</a></p>
150
+ That is the core Turboforge bet: monorepos need an upgrade path, not just a bootstrap command.
package/index.d.mts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "@turboforge/sync";
2
+ export { default } from "@turboforge/sync";
package/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from "@turboforge/sync";
2
+ export { default } from "@turboforge/sync";
package/package.json CHANGED
@@ -2,49 +2,39 @@
2
2
  "name": "forge-sync",
3
3
  "author": "Mayank Kumar Chaudhari <https://mayankchaudhari.com>",
4
4
  "private": false,
5
- "version": "0.0.0",
6
- "description": "The authoritative synchronization engine for Turbo-Forge monorepos. Align tooling, configurations, and dependencies with the upstream template.",
5
+ "version": "0.0.1",
6
+ "description": "The authoritative synchronization engine for Turboforge monorepos to align tooling, configurations, and dependencies with upstream templates.",
7
7
  "license": "MIT",
8
- "main": "./dist/index.js",
9
- "module": "./dist/index.mjs",
10
- "types": "./dist/index.d.ts",
8
+ "main": "./index.mjs",
9
+ "module": "./index.mjs",
10
+ "types": "./index.d.mts",
11
11
  "exports": {
12
12
  ".": {
13
- "import": {
14
- "types": "./dist/index.d.mts",
15
- "default": "./dist/index.mjs"
16
- },
17
- "require": {
18
- "types": "./dist/index.d.ts",
19
- "default": "./dist/index.js"
20
- }
13
+ "import": "./index.mjs",
14
+ "types": "./index.d.mts",
15
+ "default": "./index.mjs"
21
16
  },
22
17
  "./package.json": "./package.json"
23
18
  },
24
19
  "repository": {
25
20
  "type": "git",
26
- "url": "https://github.com/react18-tools/turbo-forge",
21
+ "url": "https://github.com/turboforge-dev/turboforge",
27
22
  "directory": "packages/forge-sync"
28
23
  },
29
- "bugs": "https://github.com/react18-tools/turbo-forge/issues",
30
- "homepage": "https://github.com/react18-tools/turbo-forge/blob/main/packages/forge-sync/README.md",
24
+ "bugs": "https://github.com/turboforge-dev/turboforge/issues",
25
+ "homepage": "https://github.com/turboforge-dev/turboforge/blob/main/packages/forge-sync/README.md",
31
26
  "sideEffects": false,
32
- "files": [
33
- "dist/**"
34
- ],
35
27
  "bin": {
36
- "forge-sync": "./dist/cli.mjs"
37
- },
38
- "devDependencies": {
39
- "@types/node": "latest",
40
- "tsup": "latest",
41
- "typescript": "latest",
42
- "@turbo-forge/cli-kit": "^0.0.0"
28
+ "forge-sync": "./dist/cli.mjs",
29
+ "sync": "./dist/cli.mjs",
30
+ "turboforge": "./dist/cli.mjs"
43
31
  },
32
+ "scripts": {},
33
+ "devDependencies": {},
44
34
  "funding": [
45
35
  {
46
36
  "type": "github",
47
- "url": "https://github.com/sponsors/react18-tools"
37
+ "url": "https://github.com/sponsors/turboforge-dev"
48
38
  },
49
39
  {
50
40
  "type": "github",
@@ -52,23 +42,18 @@
52
42
  }
53
43
  ],
54
44
  "keywords": [
55
- "forge-sync",
56
- "turbo-forge",
45
+ "turboforge",
57
46
  "monorepo",
47
+ "sync",
58
48
  "template-sync",
59
49
  "codemod",
60
- "typescript-tooling",
61
- "oss-maintenance",
62
- "TurboForge"
50
+ "git-patch",
51
+ "package-json-merge",
52
+ "typescript",
53
+ "tooling"
63
54
  ],
64
55
  "dependencies": {
65
- "git-json-resolver": "^1.3.7",
66
- "git-json-resolver-semver": "^1.0.0"
56
+ "@turboforge/sync": "0.0.1"
67
57
  },
68
- "scripts": {
69
- "build": "tsup",
70
- "clean": "rm -rf dist",
71
- "dev": "tsup --watch",
72
- "typecheck": "tsc --noEmit"
73
- }
58
+ "type": "module"
74
59
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 react18-tools
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.
@@ -1 +0,0 @@
1
- var g=Object.create;var f=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var m=(a=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(a,{get:(b,c)=>(typeof require!="undefined"?require:b)[c]}):a)(function(a){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var n=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var l=(a,b,c,e)=>{if(b&&typeof b=="object"||typeof b=="function")for(let d of i(b))!k.call(a,d)&&d!==c&&f(a,d,{get:()=>b[d],enumerable:!(e=h(b,d))||e.enumerable});return a};var o=(a,b,c)=>(c=a!=null?g(j(a)):{},l(b||!a||!a.__esModule?f(c,"default",{value:a,enumerable:!0}):c,a));export{m as a,n as b,o as c};
@@ -1,5 +0,0 @@
1
- import{access as re,readFile as U,writeFile as M}from"fs/promises";import{resolve as ie}from"path";import{exec as z,execFile as I}from"child_process";import R from"fs";import L from"path";import{promisify as F}from"util";var m=F(z),d=F(I),Y=(e,r)=>{let n=L.resolve(e),{root:t}=L.parse(n);for(;;){for(let o of r)if(R.existsSync(L.join(n,o)))return n;if(n===t)break;n=L.dirname(n)}return null},H=e=>{try{if(!R.existsSync(e))return null;let r=R.readFileSync(e,"utf-8");return JSON.parse(r)}catch{return null}},K=async e=>{var r;if(!R.existsSync(e))return null;try{let n=await import("./jiti-DGVRRYDD.mjs"),o=(n.createJiti?n.createJiti(process.cwd()):n.default(process.cwd()))(e);return(r=o.default)!=null?r:o}catch{try{let n=await import(e);return n.default||n}catch(n){throw/\.(ts|mts)$/.test(e)?new Error(`Failed to load TypeScript config at ${e}. Please install 'jiti' as a dev dependency to load .ts files.`):n}}},k=(e,r)=>{if(typeof e!="object"||e===null||typeof r!="object"||r===null||Array.isArray(e)&&Array.isArray(r))return r;let n={...e};for(let t of Object.keys(r))Object.hasOwn(r,t)&&(t in e?n[t]=k(e[t],r[t]):n[t]=r[t]);return n};import{appendFileSync as J}from"fs";var f="\x1B[",S={gray:e=>`${f}90m${e}${f}39m`,blue:e=>`${f}34m${e}${f}39m`,yellow:e=>`${f}33m${e}${f}39m`,red:e=>`${f}31m${e}${f}39m`},P={debug:0,info:1,warn:2,error:3},O=e=>{let r=P[e.level],n=(t,o)=>{if(P[t]<r)return;let s=`[${new Date().toISOString()}] [${t.toUpperCase()}] ${o}`,l={debug:S.gray,info:S.blue,warn:S.yellow,error:S.red},g=process.stdout.isTTY&&!process.env.NO_COLOR||!!process.env.FORCE_COLOR;console.log(g?l[t](s):s),e.logFile&&J(e.logFile,`${s}
2
- `)};return{debug:t=>n("debug",t),info:t=>n("info",t),warn:t=>n("warn",t),error:t=>n("error",t)}};import{resolveConflicts as j}from"git-json-resolver";var D=()=>Promise.all([m("git diff --quiet"),m("git diff --cached --quiet")]);var C=e=>e.replace(/[^a-zA-Z0-9]/g,""),N=e=>{let r=e.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9_-]/g,"");if(!r||!/^[a-zA-Z0-9_]/.test(r)||r.startsWith("-"))throw new Error(`Invalid remote name: "${e}". Remote names may only contain letters, numbers, underscore, and hyphen, and cannot start with '-'.`);return r},h=e=>e.replace(/[\r\n]/g,""),A=async({remoteName:e,baseRef:r,targetRef:n,exclusions:t,logger:o,maxRetries:c=3,errorLogs:s=[]},l=0)=>{var x;if(l>c){o.warn(`Max patch recursion reached (${c}), stopping`);return}let g=`git diff ${r} ${e}/main -- ${t.join(" ")} .`;o.debug(`Running: ${g}`);let{stdout:b}=await d("git",["diff",r,`${e}/${n}`,"--",...t,"."],{encoding:"utf8"});await M(".template.patch",b),o.debug(`Patch written to .template.patch (${b.length} chars)`);try{o.debug("Applying patch with 3-way merge"),await m("git apply --3way --ignore-space-change --ignore-whitespace .template.patch",{encoding:"utf8"}),o.debug("Patch applied successfully")}catch($){let u=(x=$.stderr)==null?void 0:x.split(`
3
- `).filter(i=>i.startsWith("error"));o.debug(`Patch failed with ${u.length} errors`),u.forEach(i=>{var p;let a=(p=i.split(":")[1])==null?void 0:p.trim();a&&(t.push(`:!${a}`),o.debug(`Added to exclusions: ${h(a)}`))}),s.push("Applied patch with errors: "),s.push({errorLines:u,exclusions:t}),s.push("^^^---Applied patch with errors"),u.length&&await A({remoteName:e,baseRef:r,targetRef:n,exclusions:t,logger:o,maxRetries:c,errorLogs:s},l+1)}},T=async e=>{await j({include:["package.json"],defaultStrategy:["merge","theirs"],rules:{name:["ours"],"devDependencies.*":["ignore-removed","theirs"],"dependencies.*":["ignore-removed","theirs"]},debug:e}),await j({include:["**/package.json"],exclude:["package.json","**/dist/**","**/.next/**"],defaultStrategy:["merge","non-empty","ours"],rules:{"devDependencies.*":["semver-max"],"dependencies.*":["semver-max"]},loggerConfig:{logDir:".logs2",levels:{stdout:[]}},plugins:["git-json-resolver-semver"],pluginConfig:{"git-json-resolver-semver":{preferValid:!0}},includeNonConflicted:!0,debug:e})},ae=async e=>{try{let s=await U(e,"utf8");return JSON.parse(s).lastSyncedCommit}catch{}let[{stdout:r},{stdout:n}]=await Promise.all([m("git log --reverse --format=%ai | head -n 1",{encoding:"utf8"}),m("git log --format=%H::%ai template/main",{encoding:"utf8"})]),t=new Date(r.trim()),c=n.trim().split(`
4
- `).map(s=>{let[l,g]=s.split("::");return{hash:l,date:new Date(g==null?void 0:g.trim())}}).reverse().find(s=>s.date>=t);if(c)return console.info("Applying changes from ",c.hash," dated ",c.date),c.hash};import{writeFile as q}from"fs/promises";var G={logLevel:"info",dryRun:!1,templateUrl:"https://github.com/turbo-forge/forge-template.git",excludePaths:[],remoteName:"template",maxPatchRetries:3,backupDir:".forge-backup",skipCleanCheck:!1,targetRef:"main",metaFile:".forge-meta.json",baseRef:"",postSync:["pnpm install","pnpm biome check --write --no-errors-on-unmatched $(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(ts|tsx|js|json)$' || true)"]},_=[],me=async e=>{let{logLevel:r,skipCleanCheck:n,dryRun:t,remoteName:o,templateUrl:c,backupDir:s,baseRef:l,excludePaths:g,targetRef:b,metaFile:x,postSync:$,maxPatchRetries:u}=k(G,e),i=O({level:r});if(!l){i.error("\u274C Error: Base ref is required");return}if(n)i.info("Skipping git clean check");else try{await D(),i.info("Git tree is clean")}catch{i.error("\u274C Error: Please commit or stash your changes before upgrading.");return}t&&i.info("Dry run mode - no changes will be applied");let a=N(o);try{await Promise.all([d("git",["remote","add",a,c]),m(`rm -rf ${s}`)])}catch{i.debug(`${h(a)} remote already exists`)}finally{i.debug(`Added ${h(a)} remote: ${h(c)}`)}try{await d("git",["fetch",a]),i.debug(`Fetched latest changes from ${h(a)}`);let p=C(l),y=C(b),v=[...g].map(w=>`:!${w}`);if(i.debug(`Base exclusions: ${v.length} items`),i.debug(`Generating patch from ${p} to ${y}`),i.debug(`Total exclusions: ${v.length}`),t){let{stdout:w}=await d("git",["diff",p,`${a}/${y}`,"--",...v,"."],{encoding:"utf8"});i.info("\u{1F4CB} Patch preview:"),i.info(w||"No changes to apply");return}await A({remoteName:a,baseRef:p,targetRef:y,exclusions:v,logger:i,maxRetries:u,errorLogs:_});let{stdout:E}=await d("git",["rev-parse",`${a}/${y}`],{encoding:"utf8"});await q(x,JSON.stringify({lastSyncedCommit:E.trim(),baseRef:p,targetRef:y,generatedAt:new Date().toISOString()},null,2)),await T(r==="debug"),console.log("\u2705 Upgrade applied successfully."),t||(i.info("Running post-sync commands..."),i.info($.join(`
5
- `)),await Promise.all($.map(w=>m(w))))}catch(p){console.error("\u274C Upgrade failed:",p)}try{await d("git",["remote","remove",a])}catch{}};export{Y as a,H as b,K as c,k as d,ae as e,G as f,me as g};
package/dist/cli.d.mts DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
- import { ForgeSyncOptions } from './index.mjs';
3
-
4
- interface CliOptions extends ForgeSyncOptions {
5
- help?: boolean;
6
- init?: boolean;
7
- config?: string;
8
- }
9
- declare const parseArgs: (args: string[]) => Partial<CliOptions>;
10
- declare const showHelp: () => void;
11
- declare const main: (args?: string[]) => Promise<void>;
12
-
13
- export { main, parseArgs, showHelp };
package/dist/cli.d.ts DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env node
2
- import { ForgeSyncOptions } from './index.js';
3
-
4
- interface CliOptions extends ForgeSyncOptions {
5
- help?: boolean;
6
- init?: boolean;
7
- config?: string;
8
- }
9
- declare const parseArgs: (args: string[]) => Partial<CliOptions>;
10
- declare const showHelp: () => void;
11
- declare const main: (args?: string[]) => Promise<void>;
12
-
13
- export { main, parseArgs, showHelp };