@anvil-works/anvil-cli 0.3.9 → 0.3.11
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 +21 -25
- package/dist/cli.js +554 -215
- package/dist/index.js +94 -7
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -44259,7 +44259,10 @@ var __webpack_exports__ = {};
|
|
|
44259
44259
|
const handlers = this.listeners.get(event);
|
|
44260
44260
|
if (handlers) handlers.forEach((handler)=>{
|
|
44261
44261
|
try {
|
|
44262
|
-
handler(data);
|
|
44262
|
+
const result = handler(data);
|
|
44263
|
+
if (result && "function" == typeof result.catch) result.catch((error)=>{
|
|
44264
|
+
this.onError(String(event), error);
|
|
44265
|
+
});
|
|
44263
44266
|
} catch (error) {
|
|
44264
44267
|
this.onError(String(event), error);
|
|
44265
44268
|
}
|
|
@@ -44334,7 +44337,7 @@ var __webpack_exports__ = {};
|
|
|
44334
44337
|
files
|
|
44335
44338
|
})
|
|
44336
44339
|
};
|
|
44337
|
-
const
|
|
44340
|
+
const errors_createGitError = {
|
|
44338
44341
|
notInitialized: (path)=>({
|
|
44339
44342
|
type: "git_not_initialized",
|
|
44340
44343
|
path
|
|
@@ -44520,7 +44523,7 @@ var __webpack_exports__ = {};
|
|
|
44520
44523
|
if (!external_path_default().isAbsolute(gitDir)) return external_path_default().resolve(this.repoPath, gitDir);
|
|
44521
44524
|
return gitDir;
|
|
44522
44525
|
} catch (e) {
|
|
44523
|
-
throw
|
|
44526
|
+
throw errors_createGitError.commandFailed("rev-parse --git-dir", e.message);
|
|
44524
44527
|
}
|
|
44525
44528
|
}
|
|
44526
44529
|
async getCurrentBranch() {
|
|
@@ -44543,7 +44546,7 @@ var __webpack_exports__ = {};
|
|
|
44543
44546
|
])).trim();
|
|
44544
44547
|
return commitId;
|
|
44545
44548
|
} catch (e) {
|
|
44546
|
-
throw
|
|
44549
|
+
throw errors_createGitError.commandFailed("revparse", e.message);
|
|
44547
44550
|
}
|
|
44548
44551
|
}
|
|
44549
44552
|
async getCommitInfo() {
|
|
@@ -44562,7 +44565,7 @@ var __webpack_exports__ = {};
|
|
|
44562
44565
|
message
|
|
44563
44566
|
};
|
|
44564
44567
|
} catch (e) {
|
|
44565
|
-
throw
|
|
44568
|
+
throw errors_createGitError.commandFailed("log", e.message);
|
|
44566
44569
|
}
|
|
44567
44570
|
}
|
|
44568
44571
|
async getStatus() {
|
|
@@ -44582,7 +44585,7 @@ var __webpack_exports__ = {};
|
|
|
44582
44585
|
renamed: status.renamed || []
|
|
44583
44586
|
};
|
|
44584
44587
|
} catch (e) {
|
|
44585
|
-
throw
|
|
44588
|
+
throw errors_createGitError.commandFailed("status", e.message);
|
|
44586
44589
|
}
|
|
44587
44590
|
}
|
|
44588
44591
|
async hasUncommittedChanges() {
|
|
@@ -44596,7 +44599,7 @@ var __webpack_exports__ = {};
|
|
|
44596
44599
|
refSpec
|
|
44597
44600
|
]);
|
|
44598
44601
|
} catch (e) {
|
|
44599
|
-
throw
|
|
44602
|
+
throw errors_createGitError.fetchFailed(e.message);
|
|
44600
44603
|
}
|
|
44601
44604
|
}
|
|
44602
44605
|
async reset(ref, mode = "mixed") {
|
|
@@ -44606,21 +44609,45 @@ var __webpack_exports__ = {};
|
|
|
44606
44609
|
ref
|
|
44607
44610
|
]);
|
|
44608
44611
|
} catch (e) {
|
|
44609
|
-
throw
|
|
44612
|
+
throw errors_createGitError.commandFailed("reset", e.message);
|
|
44610
44613
|
}
|
|
44611
44614
|
}
|
|
44612
44615
|
async checkout(paths) {
|
|
44613
44616
|
try {
|
|
44614
44617
|
await this.git.checkout(paths);
|
|
44615
44618
|
} catch (e) {
|
|
44616
|
-
throw
|
|
44619
|
+
throw errors_createGitError.commandFailed("checkout", e.message);
|
|
44620
|
+
}
|
|
44621
|
+
}
|
|
44622
|
+
async stash(message) {
|
|
44623
|
+
try {
|
|
44624
|
+
const args = [
|
|
44625
|
+
"stash",
|
|
44626
|
+
"push",
|
|
44627
|
+
"--include-untracked"
|
|
44628
|
+
];
|
|
44629
|
+
if (message) args.push("-m", message);
|
|
44630
|
+
const result = await this.git.raw(args);
|
|
44631
|
+
return !result.includes("No local changes to save");
|
|
44632
|
+
} catch (e) {
|
|
44633
|
+
throw errors_createGitError.commandFailed("stash", e.message);
|
|
44634
|
+
}
|
|
44635
|
+
}
|
|
44636
|
+
async stashPop() {
|
|
44637
|
+
try {
|
|
44638
|
+
await this.git.raw([
|
|
44639
|
+
"stash",
|
|
44640
|
+
"pop"
|
|
44641
|
+
]);
|
|
44642
|
+
} catch (e) {
|
|
44643
|
+
throw errors_createGitError.commandFailed("stash pop", e.message);
|
|
44617
44644
|
}
|
|
44618
44645
|
}
|
|
44619
44646
|
async clean(files) {
|
|
44620
44647
|
try {
|
|
44621
44648
|
await this.git.clean(CleanOptions.FORCE, files);
|
|
44622
44649
|
} catch (e) {
|
|
44623
|
-
throw
|
|
44650
|
+
throw errors_createGitError.commandFailed("clean", e.message);
|
|
44624
44651
|
}
|
|
44625
44652
|
}
|
|
44626
44653
|
async diffNames(fromCommit, toCommit) {
|
|
@@ -44633,7 +44660,7 @@ var __webpack_exports__ = {};
|
|
|
44633
44660
|
const files = diffResult.split("\n").filter((f)=>f.trim());
|
|
44634
44661
|
return files;
|
|
44635
44662
|
} catch (e) {
|
|
44636
|
-
throw
|
|
44663
|
+
throw errors_createGitError.commandFailed("diff", e.message);
|
|
44637
44664
|
}
|
|
44638
44665
|
}
|
|
44639
44666
|
async getAheadBehind(localRef, remoteRef) {
|
|
@@ -44650,7 +44677,7 @@ var __webpack_exports__ = {};
|
|
|
44650
44677
|
behind
|
|
44651
44678
|
};
|
|
44652
44679
|
} catch (e) {
|
|
44653
|
-
throw
|
|
44680
|
+
throw errors_createGitError.commandFailed("rev-list", e.message);
|
|
44654
44681
|
}
|
|
44655
44682
|
}
|
|
44656
44683
|
async show(refPath) {
|
|
@@ -44660,7 +44687,44 @@ var __webpack_exports__ = {};
|
|
|
44660
44687
|
]);
|
|
44661
44688
|
return content;
|
|
44662
44689
|
} catch (e) {
|
|
44663
|
-
throw
|
|
44690
|
+
throw errors_createGitError.commandFailed("show", e.message);
|
|
44691
|
+
}
|
|
44692
|
+
}
|
|
44693
|
+
async push(url, refSpec, force = false) {
|
|
44694
|
+
try {
|
|
44695
|
+
const args = force ? [
|
|
44696
|
+
"push",
|
|
44697
|
+
"--force",
|
|
44698
|
+
url,
|
|
44699
|
+
refSpec
|
|
44700
|
+
] : [
|
|
44701
|
+
"push",
|
|
44702
|
+
url,
|
|
44703
|
+
refSpec
|
|
44704
|
+
];
|
|
44705
|
+
await this.git.raw(args);
|
|
44706
|
+
} catch (e) {
|
|
44707
|
+
throw errors_createGitError.commandFailed("push", e.message);
|
|
44708
|
+
}
|
|
44709
|
+
}
|
|
44710
|
+
async rebase(onto) {
|
|
44711
|
+
try {
|
|
44712
|
+
await this.git.raw([
|
|
44713
|
+
"rebase",
|
|
44714
|
+
onto
|
|
44715
|
+
]);
|
|
44716
|
+
} catch (e) {
|
|
44717
|
+
throw errors_createGitError.commandFailed("rebase", e.message);
|
|
44718
|
+
}
|
|
44719
|
+
}
|
|
44720
|
+
async rebaseAbort() {
|
|
44721
|
+
try {
|
|
44722
|
+
await this.git.raw([
|
|
44723
|
+
"rebase",
|
|
44724
|
+
"--abort"
|
|
44725
|
+
]);
|
|
44726
|
+
} catch (e) {
|
|
44727
|
+
throw errors_createGitError.commandFailed("rebase --abort", e.message);
|
|
44664
44728
|
}
|
|
44665
44729
|
}
|
|
44666
44730
|
async deleteRef(ref) {
|
|
@@ -44680,7 +44744,7 @@ var __webpack_exports__ = {};
|
|
|
44680
44744
|
fetchUrl: r.refs.fetch
|
|
44681
44745
|
}));
|
|
44682
44746
|
} catch (e) {
|
|
44683
|
-
throw
|
|
44747
|
+
throw errors_createGitError.commandFailed("remote", e.message);
|
|
44684
44748
|
}
|
|
44685
44749
|
}
|
|
44686
44750
|
async isGitInitialized() {
|
|
@@ -44741,7 +44805,7 @@ var __webpack_exports__ = {};
|
|
|
44741
44805
|
changes.push(...stagedRenames);
|
|
44742
44806
|
return changes;
|
|
44743
44807
|
} catch (e) {
|
|
44744
|
-
throw
|
|
44808
|
+
throw errors_createGitError.commandFailed("status", e.message);
|
|
44745
44809
|
}
|
|
44746
44810
|
}
|
|
44747
44811
|
function normalizeLineEndings(content) {
|
|
@@ -46521,6 +46585,11 @@ var __webpack_exports__ = {};
|
|
|
46521
46585
|
const encodedToken = encodeURIComponent(authToken);
|
|
46522
46586
|
return `${url.protocol}//git:${encodedToken}@${url.hostname}${url.port ? ":" + url.port : ""}/git/${appId}.git?no_freeze=true&q=`;
|
|
46523
46587
|
}
|
|
46588
|
+
function getGitPushUrl(appId, authToken, anvilUrl = anvil_api_getDefaultAnvilUrl()) {
|
|
46589
|
+
const url = new URL(anvilUrl);
|
|
46590
|
+
const encodedToken = encodeURIComponent(authToken);
|
|
46591
|
+
return `${url.protocol}//git:${encodedToken}@${url.hostname}${url.port ? ":" + url.port : ""}/git/${appId}.git`;
|
|
46592
|
+
}
|
|
46524
46593
|
function getWebSocketUrl(appId, authToken, anvilUrl = anvil_api_getDefaultAnvilUrl()) {
|
|
46525
46594
|
return anvilUrl.replace(/^http/, "ws") + `/ide/api/_/apps/${appId}/ws?access_token=${authToken}`;
|
|
46526
46595
|
}
|
|
@@ -46725,7 +46794,13 @@ var __webpack_exports__ = {};
|
|
|
46725
46794
|
if (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {
|
|
46726
46795
|
this.reconnectAttempts++;
|
|
46727
46796
|
logger_logger.verbose(chalk_source.gray(`WebSocket disconnected, reconnecting in ${this.RECONNECT_DELAY / 1000}s (attempt ${this.reconnectAttempts}/${this.MAX_RECONNECT_ATTEMPTS})...`));
|
|
46728
|
-
this.reconnectTimer = setTimeout(()=>
|
|
46797
|
+
this.reconnectTimer = setTimeout(()=>{
|
|
46798
|
+
this.connect().catch((error)=>{
|
|
46799
|
+
this.emit("error", {
|
|
46800
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
46801
|
+
});
|
|
46802
|
+
});
|
|
46803
|
+
}, this.RECONNECT_DELAY);
|
|
46729
46804
|
} else logger_logger.warn(chalk_source.yellow(` WebSocket reconnection failed after ${this.MAX_RECONNECT_ATTEMPTS} attempts. Real-time sync disabled.`));
|
|
46730
46805
|
});
|
|
46731
46806
|
this.ws.on("error", (error)=>{
|
|
@@ -47897,7 +47972,11 @@ var __webpack_exports__ = {};
|
|
|
47897
47972
|
this.hasPendingChanges = true;
|
|
47898
47973
|
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
47899
47974
|
if (isFirstChange) logger_logger.progress("sync", "Change detected");
|
|
47900
|
-
this.debounceTimer = setTimeout(()=>
|
|
47975
|
+
this.debounceTimer = setTimeout(()=>{
|
|
47976
|
+
this.processSaveBatchWithEvents().catch((error)=>{
|
|
47977
|
+
logger_logger.error(`Save failed: ${errors_getErrorMessage(error)}`);
|
|
47978
|
+
});
|
|
47979
|
+
}, this.SAVE_DEBOUNCE_MS);
|
|
47901
47980
|
}
|
|
47902
47981
|
async forceSave() {
|
|
47903
47982
|
if (this.debounceTimer) {
|
|
@@ -48264,8 +48343,11 @@ var __webpack_exports__ = {};
|
|
|
48264
48343
|
}
|
|
48265
48344
|
async handleConflict(json_resp, originalFilePaths, retryCount) {
|
|
48266
48345
|
if (retryCount >= this.MAX_RETRIES) {
|
|
48267
|
-
logger_logger.error(`Save failed after ${this.MAX_RETRIES} retries
|
|
48268
|
-
logger_logger.warn("
|
|
48346
|
+
logger_logger.error(`Save failed after ${this.MAX_RETRIES} retries due to version conflicts.`);
|
|
48347
|
+
logger_logger.warn("This usually means someone else is editing the app at the same time.");
|
|
48348
|
+
this.emit("max-retries-exceeded", {
|
|
48349
|
+
retries: this.MAX_RETRIES
|
|
48350
|
+
});
|
|
48269
48351
|
throw createSaveError.maxRetriesExceeded(this.MAX_RETRIES);
|
|
48270
48352
|
}
|
|
48271
48353
|
let conflictReason = "Unknown conflict";
|
|
@@ -48600,6 +48682,7 @@ var __webpack_exports__ = {};
|
|
|
48600
48682
|
this.saveProcessor.on("save-complete", (data)=>this.emit("save-complete", data));
|
|
48601
48683
|
this.saveProcessor.on("validation-failed", (data)=>this.emit("validation-failed", data));
|
|
48602
48684
|
this.saveProcessor.on("sync-conflict", (data)=>this.emit("sync-conflict", data));
|
|
48685
|
+
this.saveProcessor.on("max-retries-exceeded", (data)=>this.emit("max-retries-exceeded", data));
|
|
48603
48686
|
}
|
|
48604
48687
|
async connectWebSocket() {
|
|
48605
48688
|
this.wsClient = new WebSocketClient({
|
|
@@ -48672,7 +48755,11 @@ var __webpack_exports__ = {};
|
|
|
48672
48755
|
this.saveProcessor?.queueSave();
|
|
48673
48756
|
});
|
|
48674
48757
|
this.fileWatcher.on("file-change", async ({ event, path: filePath, relativePath })=>{
|
|
48675
|
-
|
|
48758
|
+
try {
|
|
48759
|
+
await this.handleFileChange(event, filePath, relativePath);
|
|
48760
|
+
} catch (error) {
|
|
48761
|
+
logger_logger.error(`Error handling file change for ${relativePath}: ${error.message}`);
|
|
48762
|
+
}
|
|
48676
48763
|
});
|
|
48677
48764
|
await this.fileWatcher.start(this.currentBranch);
|
|
48678
48765
|
await new Promise(()=>{});
|
|
@@ -48826,7 +48913,7 @@ var __webpack_exports__ = {};
|
|
|
48826
48913
|
logger_logger.verbose(chalk_source.green(`✔ Branch '${branchName}' is up-to-date with Anvil.`));
|
|
48827
48914
|
return null;
|
|
48828
48915
|
} catch (e) {
|
|
48829
|
-
throw
|
|
48916
|
+
throw errors_createGitError.fetchFailed(e.message);
|
|
48830
48917
|
}
|
|
48831
48918
|
}
|
|
48832
48919
|
async function validateViaAnvilServer(git, branchName, appId, anvilUrl, username) {
|
|
@@ -48838,7 +48925,7 @@ var __webpack_exports__ = {};
|
|
|
48838
48925
|
"HEAD"
|
|
48839
48926
|
])).trim();
|
|
48840
48927
|
} catch (e) {
|
|
48841
|
-
throw
|
|
48928
|
+
throw errors_createGitError.commandFailed("revparse", e.message);
|
|
48842
48929
|
}
|
|
48843
48930
|
try {
|
|
48844
48931
|
const resp = await fetch(`${anvilUrl}/ide/api/_/apps/lookup-by-commit`, {
|
|
@@ -48862,7 +48949,12 @@ var __webpack_exports__ = {};
|
|
|
48862
48949
|
}
|
|
48863
48950
|
const allBranches = data.apps?.flatMap((app)=>app.branches || []) || [];
|
|
48864
48951
|
const branchExistsOnAnvil = allBranches.some((b)=>b === branchName);
|
|
48865
|
-
if (!branchExistsOnAnvil)
|
|
48952
|
+
if (!branchExistsOnAnvil) return {
|
|
48953
|
+
behind: 0,
|
|
48954
|
+
ahead: 0,
|
|
48955
|
+
diverged: false,
|
|
48956
|
+
branchMissing: true
|
|
48957
|
+
};
|
|
48866
48958
|
throw createValidationError.invalidApp(appId, `Anvil server doesn't recognize commit ${commitId.substring(0, 8)} on branch '${branchName}'. Please pull the latest changes from Anvil before starting sync.`);
|
|
48867
48959
|
} catch (e) {
|
|
48868
48960
|
if (e.type) throw e;
|
|
@@ -48870,26 +48962,6 @@ var __webpack_exports__ = {};
|
|
|
48870
48962
|
}
|
|
48871
48963
|
}
|
|
48872
48964
|
const DEFAULT_ANVIL_URL = resolveAnvilUrl();
|
|
48873
|
-
async function checkUncommittedChanges(repoPath) {
|
|
48874
|
-
try {
|
|
48875
|
-
const git = esm_default(repoPath);
|
|
48876
|
-
const status = await git.status();
|
|
48877
|
-
const staged = status.files.filter((file)=>{
|
|
48878
|
-
const indexStatus = file.index.trim();
|
|
48879
|
-
return indexStatus.length > 0 && "?" !== indexStatus;
|
|
48880
|
-
}).map((file)=>file.path);
|
|
48881
|
-
return {
|
|
48882
|
-
hasChanges: !status.isClean(),
|
|
48883
|
-
modified: status.modified,
|
|
48884
|
-
notAdded: status.not_added,
|
|
48885
|
-
created: status.created,
|
|
48886
|
-
deleted: status.deleted,
|
|
48887
|
-
staged
|
|
48888
|
-
};
|
|
48889
|
-
} catch (e) {
|
|
48890
|
-
throw createGitError.commandFailed("status", e.message);
|
|
48891
|
-
}
|
|
48892
|
-
}
|
|
48893
48965
|
async function syncToLatest(repoPath, appId, anvilUrl, authToken, currentBranch, username) {
|
|
48894
48966
|
try {
|
|
48895
48967
|
const git = esm_default(repoPath);
|
|
@@ -48911,7 +48983,7 @@ var __webpack_exports__ = {};
|
|
|
48911
48983
|
return newCommitId;
|
|
48912
48984
|
} catch (e) {
|
|
48913
48985
|
if (isAnvilError(e)) throw e;
|
|
48914
|
-
throw
|
|
48986
|
+
throw errors_createGitError.commandFailed("sync", e instanceof Error ? e.message : String(e));
|
|
48915
48987
|
}
|
|
48916
48988
|
}
|
|
48917
48989
|
async function api_watch(repoPath, appId, anvilUrl = DEFAULT_ANVIL_URL, stagedOnly = false, username) {
|
|
@@ -48925,11 +48997,11 @@ var __webpack_exports__ = {};
|
|
|
48925
48997
|
"--abbrev-ref",
|
|
48926
48998
|
"HEAD"
|
|
48927
48999
|
]);
|
|
48928
|
-
if ("HEAD" === branchRef) throw
|
|
49000
|
+
if ("HEAD" === branchRef) throw errors_createGitError.commandFailed("revparse", "Cannot sync from detached HEAD state. Please checkout a branch first.");
|
|
48929
49001
|
currentBranch = branchRef;
|
|
48930
49002
|
} catch (e) {
|
|
48931
49003
|
if ("git_command_failed" === e.type) throw e;
|
|
48932
|
-
throw
|
|
49004
|
+
throw errors_createGitError.commandFailed("revparse", e.message);
|
|
48933
49005
|
}
|
|
48934
49006
|
let commitId;
|
|
48935
49007
|
try {
|
|
@@ -48937,7 +49009,7 @@ var __webpack_exports__ = {};
|
|
|
48937
49009
|
"HEAD"
|
|
48938
49010
|
])).trim();
|
|
48939
49011
|
} catch (e) {
|
|
48940
|
-
throw
|
|
49012
|
+
throw errors_createGitError.commandFailed("revparse", e.message);
|
|
48941
49013
|
}
|
|
48942
49014
|
logger_logger.verbose(chalk_source.cyan("Current branch: ") + chalk_source.bold(currentBranch));
|
|
48943
49015
|
logger_logger.verbose(chalk_source.cyan("Current commit ID: ") + chalk_source.gray(commitId));
|
|
@@ -48947,7 +49019,7 @@ var __webpack_exports__ = {};
|
|
|
48947
49019
|
const status = await git.status();
|
|
48948
49020
|
hasUncommittedChanges = status.files.length > 0;
|
|
48949
49021
|
} catch (e) {
|
|
48950
|
-
throw
|
|
49022
|
+
throw errors_createGitError.commandFailed("status", e.message);
|
|
48951
49023
|
}
|
|
48952
49024
|
logger_logger.verbose(chalk_source.blue("Has uncommitted changes: ") + chalk_source.bold(hasUncommittedChanges));
|
|
48953
49025
|
const session = new WatchSession(repoPath, appId, {
|
|
@@ -48978,7 +49050,7 @@ var __webpack_exports__ = {};
|
|
|
48978
49050
|
try {
|
|
48979
49051
|
await session.initialize();
|
|
48980
49052
|
} catch (e) {
|
|
48981
|
-
throw
|
|
49053
|
+
throw errors_createGitError.commandFailed("initialize", e.message);
|
|
48982
49054
|
}
|
|
48983
49055
|
if (null !== syncStatus) session.syncStatus = syncStatus;
|
|
48984
49056
|
session.hasUncommittedChanges = hasUncommittedChanges;
|
|
@@ -49074,30 +49146,328 @@ var __webpack_exports__ = {};
|
|
|
49074
49146
|
return null;
|
|
49075
49147
|
}
|
|
49076
49148
|
}
|
|
49149
|
+
async function pushToAnvil(options) {
|
|
49150
|
+
try {
|
|
49151
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
49152
|
+
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
49153
|
+
const git = new GitService(options.repoPath);
|
|
49154
|
+
const refSpec = `${options.branchName}:${options.branchName}`;
|
|
49155
|
+
logger_logger.progress("push", "Pushing to Anvil...");
|
|
49156
|
+
await git.push(pushUrl, refSpec, options.force ?? false);
|
|
49157
|
+
logger_logger.progressEnd("push", "Pushed to Anvil");
|
|
49158
|
+
return true;
|
|
49159
|
+
} catch (e) {
|
|
49160
|
+
logger_logger.progressEnd("push", "Push failed");
|
|
49161
|
+
logger_logger.error(`Failed to push: ${errors_getErrorMessage(e)}`);
|
|
49162
|
+
return false;
|
|
49163
|
+
}
|
|
49164
|
+
}
|
|
49165
|
+
async function fetchAndRebaseFromAnvil(options) {
|
|
49166
|
+
const git = new GitService(options.repoPath);
|
|
49167
|
+
const tempRef = `anvil-rebase-temp-${Date.now()}`;
|
|
49168
|
+
let didStash = false;
|
|
49169
|
+
try {
|
|
49170
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
49171
|
+
const fetchUrl = getGitFetchUrl(options.appId, authToken, options.anvilUrl);
|
|
49172
|
+
const hasChanges = await git.hasUncommittedChanges();
|
|
49173
|
+
if (hasChanges) {
|
|
49174
|
+
logger_logger.progress("rebase", "Stashing uncommitted changes...");
|
|
49175
|
+
didStash = await git.stash("anvil-sync: stash before rebase");
|
|
49176
|
+
}
|
|
49177
|
+
logger_logger.progressUpdate("rebase", "Fetching from Anvil...");
|
|
49178
|
+
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
49179
|
+
logger_logger.progressUpdate("rebase", "Rebasing...");
|
|
49180
|
+
await git.rebase(tempRef);
|
|
49181
|
+
logger_logger.progressUpdate("rebase", "Pushing rebased changes...");
|
|
49182
|
+
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
49183
|
+
await git.push(pushUrl, `${options.branchName}:${options.branchName}`, true);
|
|
49184
|
+
logger_logger.progressEnd("rebase", "Rebased and pushed to Anvil");
|
|
49185
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
49186
|
+
if (didStash) try {
|
|
49187
|
+
await git.stashPop();
|
|
49188
|
+
logger_logger.verbose(chalk_source.green("Restored uncommitted changes"));
|
|
49189
|
+
} catch (e) {
|
|
49190
|
+
logger_logger.warn("Uncommitted changes were stashed but could not be restored automatically.");
|
|
49191
|
+
logger_logger.info(chalk_source.gray(" Run: git stash pop"));
|
|
49192
|
+
}
|
|
49193
|
+
return {
|
|
49194
|
+
success: true,
|
|
49195
|
+
conflicted: false
|
|
49196
|
+
};
|
|
49197
|
+
} catch (e) {
|
|
49198
|
+
const msg = errors_getErrorMessage(e);
|
|
49199
|
+
if (msg.includes("rebase") && (msg.includes("conflict") || msg.includes("CONFLICT") || msg.includes("could not apply"))) {
|
|
49200
|
+
try {
|
|
49201
|
+
await git.rebaseAbort();
|
|
49202
|
+
} catch {}
|
|
49203
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
49204
|
+
if (didStash) try {
|
|
49205
|
+
await git.stashPop();
|
|
49206
|
+
} catch {
|
|
49207
|
+
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
49208
|
+
}
|
|
49209
|
+
logger_logger.progressEnd("rebase", "Rebase failed - conflicts");
|
|
49210
|
+
return {
|
|
49211
|
+
success: false,
|
|
49212
|
+
conflicted: true
|
|
49213
|
+
};
|
|
49214
|
+
}
|
|
49215
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
49216
|
+
if (didStash) try {
|
|
49217
|
+
await git.stashPop();
|
|
49218
|
+
} catch {
|
|
49219
|
+
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
49220
|
+
}
|
|
49221
|
+
logger_logger.progressEnd("rebase", "Rebase failed");
|
|
49222
|
+
logger_logger.error(`Failed to rebase: ${msg}`);
|
|
49223
|
+
return {
|
|
49224
|
+
success: false,
|
|
49225
|
+
conflicted: false
|
|
49226
|
+
};
|
|
49227
|
+
}
|
|
49228
|
+
}
|
|
49229
|
+
async function fetchAndHardResetFromAnvil(options) {
|
|
49230
|
+
const git = new GitService(options.repoPath);
|
|
49231
|
+
const tempRef = `anvil-reset-temp-${Date.now()}`;
|
|
49232
|
+
try {
|
|
49233
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
49234
|
+
const fetchUrl = getGitFetchUrl(options.appId, authToken, options.anvilUrl);
|
|
49235
|
+
logger_logger.progress("reset", "Fetching from Anvil...");
|
|
49236
|
+
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
49237
|
+
logger_logger.progressUpdate("reset", "Resetting to Anvil's version...");
|
|
49238
|
+
await git.reset(tempRef, "hard");
|
|
49239
|
+
logger_logger.progressEnd("reset", "Reset to Anvil's version");
|
|
49240
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
49241
|
+
return true;
|
|
49242
|
+
} catch (e) {
|
|
49243
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
49244
|
+
logger_logger.progressEnd("reset", "Reset failed");
|
|
49245
|
+
logger_logger.error(`Failed to reset: ${errors_getErrorMessage(e)}`);
|
|
49246
|
+
return false;
|
|
49247
|
+
}
|
|
49248
|
+
}
|
|
49249
|
+
function getSyncStateCategory(syncStatus) {
|
|
49250
|
+
if (syncStatus?.branchMissing) return "branch-missing";
|
|
49251
|
+
if (syncStatus?.diverged) return "diverged";
|
|
49252
|
+
if (syncStatus?.ahead && !syncStatus?.behind) return "ahead";
|
|
49253
|
+
if (syncStatus?.behind && !syncStatus?.ahead) return "behind";
|
|
49254
|
+
if (syncStatus?.ahead && syncStatus?.behind) return "diverged";
|
|
49255
|
+
return "in-sync";
|
|
49256
|
+
}
|
|
49257
|
+
async function recheckSyncStatus(previousCategory, previousBranch, options) {
|
|
49258
|
+
try {
|
|
49259
|
+
logger_logger.progress("verify", "Verifying repository status...");
|
|
49260
|
+
const freshSession = await api_watch(options.repoPath, options.appId, options.anvilUrl, options.stagedOnly, options.username);
|
|
49261
|
+
logger_logger.progressEnd("verify");
|
|
49262
|
+
const currentCategory = getSyncStateCategory(freshSession.syncStatus);
|
|
49263
|
+
const currentBranch = freshSession.getBranchName() || "master";
|
|
49264
|
+
if (currentCategory !== previousCategory || currentBranch !== previousBranch) {
|
|
49265
|
+
logger_logger.warn("Repository status has changed. Re-evaluating...");
|
|
49266
|
+
return freshSession;
|
|
49267
|
+
}
|
|
49268
|
+
freshSession.cleanup();
|
|
49269
|
+
return null;
|
|
49270
|
+
} catch (e) {
|
|
49271
|
+
logger_logger.progressEnd("verify");
|
|
49272
|
+
logger_logger.verbose(chalk_source.gray(`Could not re-verify status: ${errors_getErrorMessage(e)}`));
|
|
49273
|
+
return null;
|
|
49274
|
+
}
|
|
49275
|
+
}
|
|
49276
|
+
async function recreateSessionAndValidate(options) {
|
|
49277
|
+
logger_logger.progress("init", "Restarting watch session...");
|
|
49278
|
+
try {
|
|
49279
|
+
const newSession = await api_watch(options.repoPath, options.appId, options.anvilUrl, options.stagedOnly, options.username);
|
|
49280
|
+
logger_logger.progressEnd("init");
|
|
49281
|
+
return await checkSyncStatusAndStart(newSession, options);
|
|
49282
|
+
} catch (e) {
|
|
49283
|
+
logger_logger.progressEnd("init", "Failed");
|
|
49284
|
+
logger_logger.error(`Failed to restart: ${errors_getErrorMessage(e)}`);
|
|
49285
|
+
return false;
|
|
49286
|
+
}
|
|
49287
|
+
}
|
|
49077
49288
|
async function checkSyncStatusAndStart(session, options) {
|
|
49078
49289
|
const syncStatus = session.syncStatus;
|
|
49290
|
+
const branchName = session.getBranchName() || "master";
|
|
49291
|
+
const hasUncommitted = session.hasUncommittedChanges;
|
|
49292
|
+
const stateCategory = getSyncStateCategory(syncStatus);
|
|
49293
|
+
if (syncStatus?.branchMissing) {
|
|
49294
|
+
logger_logger.warn(`Branch '${branchName}' doesn't exist on Anvil yet.`);
|
|
49295
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
49296
|
+
let shouldPush = options.autoMode;
|
|
49297
|
+
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-pushing new branch to Anvil..."));
|
|
49298
|
+
else {
|
|
49299
|
+
shouldPush = await logger_logger.confirm("Would you like to push this branch to Anvil?", true);
|
|
49300
|
+
if (shouldPush) {
|
|
49301
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
49302
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
49303
|
+
}
|
|
49304
|
+
}
|
|
49305
|
+
if (!shouldPush) {
|
|
49306
|
+
logger_logger.warn("Watch cancelled. Push your branch to Anvil, then try again.");
|
|
49307
|
+
session.cleanup();
|
|
49308
|
+
return false;
|
|
49309
|
+
}
|
|
49310
|
+
session.cleanup();
|
|
49311
|
+
const pushed = await pushToAnvil({
|
|
49312
|
+
repoPath: options.repoPath,
|
|
49313
|
+
appId: options.appId,
|
|
49314
|
+
anvilUrl: options.anvilUrl,
|
|
49315
|
+
branchName,
|
|
49316
|
+
username: options.username
|
|
49317
|
+
});
|
|
49318
|
+
if (!pushed) return false;
|
|
49319
|
+
return await recreateSessionAndValidate(options);
|
|
49320
|
+
}
|
|
49079
49321
|
if (syncStatus?.behind || syncStatus?.ahead) if (syncStatus.ahead && !syncStatus.behind) {
|
|
49080
|
-
logger_logger.
|
|
49081
|
-
logger_logger.
|
|
49082
|
-
|
|
49083
|
-
logger_logger.
|
|
49322
|
+
logger_logger.warn(`Your local repository is ${syncStatus.ahead} commit(s) ahead of Anvil.`);
|
|
49323
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
49324
|
+
let shouldPush = options.autoMode;
|
|
49325
|
+
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-pushing to Anvil..."));
|
|
49326
|
+
else {
|
|
49327
|
+
const action = await logger_logger.select("What would you like to do?", [
|
|
49328
|
+
{
|
|
49329
|
+
name: "Push your changes to Anvil (recommended)",
|
|
49330
|
+
value: "push"
|
|
49331
|
+
},
|
|
49332
|
+
{
|
|
49333
|
+
name: "Exit and handle manually",
|
|
49334
|
+
value: "exit"
|
|
49335
|
+
}
|
|
49336
|
+
], "push");
|
|
49337
|
+
shouldPush = "push" === action;
|
|
49338
|
+
if (shouldPush) {
|
|
49339
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
49340
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
49341
|
+
}
|
|
49342
|
+
}
|
|
49343
|
+
if (!shouldPush) {
|
|
49344
|
+
logger_logger.warn("Watch cancelled.");
|
|
49345
|
+
session.cleanup();
|
|
49346
|
+
return false;
|
|
49347
|
+
}
|
|
49084
49348
|
session.cleanup();
|
|
49085
|
-
|
|
49349
|
+
const pushed = await pushToAnvil({
|
|
49350
|
+
repoPath: options.repoPath,
|
|
49351
|
+
appId: options.appId,
|
|
49352
|
+
anvilUrl: options.anvilUrl,
|
|
49353
|
+
branchName,
|
|
49354
|
+
username: options.username
|
|
49355
|
+
});
|
|
49356
|
+
if (!pushed) return false;
|
|
49357
|
+
return await recreateSessionAndValidate(options);
|
|
49086
49358
|
} else if (syncStatus.diverged) {
|
|
49087
|
-
logger_logger.
|
|
49088
|
-
logger_logger.
|
|
49089
|
-
logger_logger.
|
|
49090
|
-
logger_logger.verbose(chalk_source.gray(" Option 1: Pull from Anvil and rebase your changes (git pull --rebase)"));
|
|
49091
|
-
logger_logger.verbose(chalk_source.gray(" Option 2: Reset to Anvil's version (you'll lose local commits)"));
|
|
49092
|
-
logger_logger.verbose(chalk_source.gray(" Option 3: Push your changes to Anvil (if you want to keep them)"));
|
|
49359
|
+
logger_logger.warn("Your local repository has diverged from Anvil.");
|
|
49360
|
+
logger_logger.info(chalk_source.gray(` You are ${syncStatus.ahead} commit(s) ahead and ${syncStatus.behind} commit(s) behind.`));
|
|
49361
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
49093
49362
|
session.cleanup();
|
|
49094
|
-
|
|
49363
|
+
if (options.autoMode) {
|
|
49364
|
+
logger_logger.info(chalk_source.cyan("→ Auto-rebasing onto Anvil's version..."));
|
|
49365
|
+
const result = await fetchAndRebaseFromAnvil({
|
|
49366
|
+
repoPath: options.repoPath,
|
|
49367
|
+
appId: options.appId,
|
|
49368
|
+
anvilUrl: options.anvilUrl,
|
|
49369
|
+
branchName,
|
|
49370
|
+
username: options.username
|
|
49371
|
+
});
|
|
49372
|
+
if (result.conflicted) {
|
|
49373
|
+
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
49374
|
+
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
49375
|
+
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
49376
|
+
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
49377
|
+
return false;
|
|
49378
|
+
}
|
|
49379
|
+
if (!result.success) return false;
|
|
49380
|
+
return await recreateSessionAndValidate(options);
|
|
49381
|
+
}
|
|
49382
|
+
const action = await logger_logger.select("How would you like to resolve this?", [
|
|
49383
|
+
{
|
|
49384
|
+
name: "Pull from Anvil and rebase your changes on top (recommended)",
|
|
49385
|
+
value: "rebase"
|
|
49386
|
+
},
|
|
49387
|
+
{
|
|
49388
|
+
name: "Discard your local commits and use Anvil's version",
|
|
49389
|
+
value: "reset"
|
|
49390
|
+
},
|
|
49391
|
+
{
|
|
49392
|
+
name: "Push your version to Anvil (overwrites remote)",
|
|
49393
|
+
value: "push"
|
|
49394
|
+
},
|
|
49395
|
+
{
|
|
49396
|
+
name: "Exit and handle manually",
|
|
49397
|
+
value: "exit"
|
|
49398
|
+
}
|
|
49399
|
+
], "rebase");
|
|
49400
|
+
if ("exit" === action) {
|
|
49401
|
+
logger_logger.warn("Watch cancelled.");
|
|
49402
|
+
return false;
|
|
49403
|
+
}
|
|
49404
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
49405
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
49406
|
+
if ("rebase" === action) {
|
|
49407
|
+
const result = await fetchAndRebaseFromAnvil({
|
|
49408
|
+
repoPath: options.repoPath,
|
|
49409
|
+
appId: options.appId,
|
|
49410
|
+
anvilUrl: options.anvilUrl,
|
|
49411
|
+
branchName,
|
|
49412
|
+
username: options.username
|
|
49413
|
+
});
|
|
49414
|
+
if (result.conflicted) {
|
|
49415
|
+
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
49416
|
+
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
49417
|
+
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
49418
|
+
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
49419
|
+
return false;
|
|
49420
|
+
}
|
|
49421
|
+
if (!result.success) return false;
|
|
49422
|
+
return await recreateSessionAndValidate(options);
|
|
49423
|
+
}
|
|
49424
|
+
if ("reset" === action) {
|
|
49425
|
+
const resetWarning = hasUncommitted ? `This will discard ${syncStatus.ahead} local commit(s) and your uncommitted changes. Are you sure?` : `This will discard ${syncStatus.ahead} local commit(s). Are you sure?`;
|
|
49426
|
+
const confirmed = await logger_logger.confirm(resetWarning, false);
|
|
49427
|
+
if (!confirmed) {
|
|
49428
|
+
logger_logger.warn("Watch cancelled.");
|
|
49429
|
+
return false;
|
|
49430
|
+
}
|
|
49431
|
+
const reset = await fetchAndHardResetFromAnvil({
|
|
49432
|
+
repoPath: options.repoPath,
|
|
49433
|
+
appId: options.appId,
|
|
49434
|
+
anvilUrl: options.anvilUrl,
|
|
49435
|
+
branchName,
|
|
49436
|
+
username: options.username
|
|
49437
|
+
});
|
|
49438
|
+
if (!reset) return false;
|
|
49439
|
+
return await recreateSessionAndValidate(options);
|
|
49440
|
+
}
|
|
49441
|
+
if ("push" === action) {
|
|
49442
|
+
const confirmed = await logger_logger.confirm("This will overwrite Anvil's version. Are you sure?", false);
|
|
49443
|
+
if (!confirmed) {
|
|
49444
|
+
logger_logger.warn("Watch cancelled.");
|
|
49445
|
+
return false;
|
|
49446
|
+
}
|
|
49447
|
+
const pushed = await pushToAnvil({
|
|
49448
|
+
repoPath: options.repoPath,
|
|
49449
|
+
appId: options.appId,
|
|
49450
|
+
anvilUrl: options.anvilUrl,
|
|
49451
|
+
branchName,
|
|
49452
|
+
username: options.username,
|
|
49453
|
+
force: true
|
|
49454
|
+
});
|
|
49455
|
+
if (!pushed) return false;
|
|
49456
|
+
return await recreateSessionAndValidate(options);
|
|
49457
|
+
}
|
|
49095
49458
|
} else {
|
|
49096
49459
|
logger_logger.warn(`Your local repository is ${syncStatus.behind} commit(s) behind Anvil.`);
|
|
49097
49460
|
logger_logger.verbose(chalk_source.gray(" You need to sync to the latest version before watching."));
|
|
49461
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
49098
49462
|
let shouldSync = options.autoMode;
|
|
49099
49463
|
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-syncing to latest version..."));
|
|
49100
|
-
else
|
|
49464
|
+
else {
|
|
49465
|
+
shouldSync = await logger_logger.confirm("Would you like to sync to the latest version from Anvil now?", true);
|
|
49466
|
+
if (shouldSync) {
|
|
49467
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
49468
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
49469
|
+
}
|
|
49470
|
+
}
|
|
49101
49471
|
if (!shouldSync) {
|
|
49102
49472
|
logger_logger.warn("Watch cancelled. Please sync manually before watching.");
|
|
49103
49473
|
session.cleanup();
|
|
@@ -49113,23 +49483,14 @@ var __webpack_exports__ = {};
|
|
|
49113
49483
|
}
|
|
49114
49484
|
logger_logger.progress("sync-latest", "Syncing to latest version from Anvil...");
|
|
49115
49485
|
try {
|
|
49116
|
-
const newCommitId = await syncToLatest(options.repoPath, options.appId, options.anvilUrl, authToken,
|
|
49486
|
+
const newCommitId = await syncToLatest(options.repoPath, options.appId, options.anvilUrl, authToken, branchName, options.username);
|
|
49117
49487
|
logger_logger.progressEnd("sync-latest", `Synced to latest version: ${newCommitId.substring(0, 8)}`);
|
|
49118
49488
|
} catch (e) {
|
|
49119
49489
|
logger_logger.progressEnd("sync-latest", "Failed");
|
|
49120
49490
|
logger_logger.error(`Failed to sync: ${errors_getErrorMessage(e)}`);
|
|
49121
49491
|
process.exit(1);
|
|
49122
49492
|
}
|
|
49123
|
-
|
|
49124
|
-
try {
|
|
49125
|
-
const newSession = await api_watch(options.repoPath, options.appId, options.anvilUrl, options.stagedOnly, options.username);
|
|
49126
|
-
logger_logger.progressEnd("init");
|
|
49127
|
-
return await checkSyncStatusAndStart(newSession, options);
|
|
49128
|
-
} catch (e) {
|
|
49129
|
-
logger_logger.progressEnd("init", "Failed");
|
|
49130
|
-
logger_logger.error(`Failed to start watch: ${errors_getErrorMessage(e)}`);
|
|
49131
|
-
process.exit(1);
|
|
49132
|
-
}
|
|
49493
|
+
return await recreateSessionAndValidate(options);
|
|
49133
49494
|
}
|
|
49134
49495
|
await startWatchingWithEventHandlers(session, options);
|
|
49135
49496
|
return true;
|
|
@@ -49137,64 +49498,30 @@ var __webpack_exports__ = {};
|
|
|
49137
49498
|
async function startWatchingWithEventHandlers(session, options) {
|
|
49138
49499
|
const { autoMode, repoPath, appId, anvilUrl, stagedOnly } = options;
|
|
49139
49500
|
session.on("branch-changed", async ({ oldBranch, newBranch })=>{
|
|
49140
|
-
|
|
49141
|
-
|
|
49142
|
-
|
|
49143
|
-
logger_logger.info(chalk_source.cyan("→
|
|
49501
|
+
try {
|
|
49502
|
+
session.cleanup();
|
|
49503
|
+
logger_logger.warn(`Branch changed: ${chalk_source.bold(oldBranch)} → ${chalk_source.bold(newBranch)}`);
|
|
49504
|
+
logger_logger.info(chalk_source.cyan("→ Restarting watch on new branch..."));
|
|
49144
49505
|
const git = esm_default(repoPath);
|
|
49145
49506
|
const actualBranch = (await git.revparse([
|
|
49146
49507
|
"--abbrev-ref",
|
|
49147
49508
|
"HEAD"
|
|
49148
49509
|
])).trim();
|
|
49149
49510
|
if (actualBranch !== newBranch) logger_logger.verbose(chalk_source.yellow(`Branch changed again to ${chalk_source.bold(actualBranch)}, using that instead`));
|
|
49150
|
-
logger_logger.verbose(chalk_source.blue(`Restarting watch on branch: ${chalk_source.bold(actualBranch)}`));
|
|
49151
49511
|
logger_logger.progress("init", "Initializing watch session...");
|
|
49152
49512
|
try {
|
|
49153
49513
|
const newSession = await api_watch(repoPath, appId, anvilUrl, stagedOnly, options.username);
|
|
49154
49514
|
logger_logger.progressEnd("init");
|
|
49155
49515
|
const started = await checkSyncStatusAndStart(newSession, options);
|
|
49156
|
-
if (!started) process.exit(
|
|
49516
|
+
if (!started) process.exit(0);
|
|
49157
49517
|
} catch (e) {
|
|
49158
49518
|
logger_logger.progressEnd("init", "Failed");
|
|
49159
49519
|
logger_logger.error("Failed to restart watch: " + errors_getErrorMessage(e));
|
|
49160
49520
|
process.exit(1);
|
|
49161
49521
|
}
|
|
49162
|
-
}
|
|
49163
|
-
logger_logger.
|
|
49164
|
-
|
|
49165
|
-
{
|
|
49166
|
-
name: "Restart watch on new branch (recommended)",
|
|
49167
|
-
value: "restart"
|
|
49168
|
-
},
|
|
49169
|
-
{
|
|
49170
|
-
name: "Exit",
|
|
49171
|
-
value: "exit"
|
|
49172
|
-
}
|
|
49173
|
-
], "restart");
|
|
49174
|
-
if ("restart" === action) {
|
|
49175
|
-
logger_logger.info(chalk_source.cyan("→ Restarting watch..."));
|
|
49176
|
-
const git = esm_default(repoPath);
|
|
49177
|
-
const actualBranch = (await git.revparse([
|
|
49178
|
-
"--abbrev-ref",
|
|
49179
|
-
"HEAD"
|
|
49180
|
-
])).trim();
|
|
49181
|
-
if (actualBranch !== newBranch) logger_logger.verbose(chalk_source.yellow(`Branch changed to ${chalk_source.bold(actualBranch)} while prompting`));
|
|
49182
|
-
logger_logger.verbose(chalk_source.blue(`Starting watch on branch: ${chalk_source.bold(actualBranch)}`));
|
|
49183
|
-
logger_logger.progress("init", "Initializing watch session...");
|
|
49184
|
-
try {
|
|
49185
|
-
const newSession = await api_watch(repoPath, appId, anvilUrl, stagedOnly, options.username);
|
|
49186
|
-
logger_logger.progressEnd("init");
|
|
49187
|
-
const started = await checkSyncStatusAndStart(newSession, options);
|
|
49188
|
-
if (!started) process.exit(1);
|
|
49189
|
-
} catch (e) {
|
|
49190
|
-
logger_logger.progressEnd("init", "Failed");
|
|
49191
|
-
logger_logger.error("Failed to restart watch: " + errors_getErrorMessage(e));
|
|
49192
|
-
process.exit(1);
|
|
49193
|
-
}
|
|
49194
|
-
} else {
|
|
49195
|
-
logger_logger.info("Exiting...");
|
|
49196
|
-
process.exit(0);
|
|
49197
|
-
}
|
|
49522
|
+
} catch (error) {
|
|
49523
|
+
logger_logger.error(`Error handling branch change: ${error.message}`);
|
|
49524
|
+
process.exit(1);
|
|
49198
49525
|
}
|
|
49199
49526
|
});
|
|
49200
49527
|
session.on("validation-failed", ({ reason, currentBranch })=>{
|
|
@@ -49204,8 +49531,31 @@ var __webpack_exports__ = {};
|
|
|
49204
49531
|
session.cleanup();
|
|
49205
49532
|
process.exit(1);
|
|
49206
49533
|
});
|
|
49534
|
+
session.on("max-retries-exceeded", async ()=>{
|
|
49535
|
+
if (autoMode) {
|
|
49536
|
+
logger_logger.info(chalk_source.cyan("→ Auto-restarting watch session..."));
|
|
49537
|
+
session.cleanup();
|
|
49538
|
+
const restarted = await recreateSessionAndValidate(options);
|
|
49539
|
+
if (!restarted) process.exit(1);
|
|
49540
|
+
} else {
|
|
49541
|
+
const shouldRestart = await logger_logger.confirm("Would you like to restart the watch session?", true);
|
|
49542
|
+
if (shouldRestart) {
|
|
49543
|
+
session.cleanup();
|
|
49544
|
+
const restarted = await recreateSessionAndValidate(options);
|
|
49545
|
+
if (!restarted) process.exit(1);
|
|
49546
|
+
}
|
|
49547
|
+
}
|
|
49548
|
+
});
|
|
49207
49549
|
if (session.hasUncommittedChanges) {
|
|
49208
|
-
|
|
49550
|
+
if (!autoMode) {
|
|
49551
|
+
const shouldContinue = await logger_logger.confirm("Continue? Your uncommitted changes will be synced to Anvil.", true);
|
|
49552
|
+
if (!shouldContinue) {
|
|
49553
|
+
logger_logger.warn("Watch cancelled. Commit, stash, or discard your changes, then try again.");
|
|
49554
|
+
session.cleanup();
|
|
49555
|
+
process.exit(0);
|
|
49556
|
+
}
|
|
49557
|
+
}
|
|
49558
|
+
logger_logger.progress("save", "Saving uncommitted changes to Anvil...");
|
|
49209
49559
|
try {
|
|
49210
49560
|
await session.forceSave();
|
|
49211
49561
|
logger_logger.progressEnd("save");
|
|
@@ -49216,7 +49566,12 @@ var __webpack_exports__ = {};
|
|
|
49216
49566
|
}
|
|
49217
49567
|
await session.startWatching();
|
|
49218
49568
|
}
|
|
49219
|
-
async function
|
|
49569
|
+
async function handleWatchCommand(options) {
|
|
49570
|
+
const invoked = process.argv[2];
|
|
49571
|
+
if ("sync" === invoked) {
|
|
49572
|
+
logger_logger.error("'sync' has been renamed to 'watch'. Please use 'anvil watch' instead.");
|
|
49573
|
+
process.exit(1);
|
|
49574
|
+
}
|
|
49220
49575
|
const { path: repoPath = process.cwd(), appid: explicitAppId, useFirst = false, stagedOnly = false, autoMode = false, url: explicitUrl, user: explicitUsername } = options;
|
|
49221
49576
|
try {
|
|
49222
49577
|
const validationResult = await validateAnvilApp(repoPath);
|
|
@@ -49281,7 +49636,7 @@ var __webpack_exports__ = {};
|
|
|
49281
49636
|
const detectedAppIds = detectedFromAllRemotes.filter((c)=>c.detectedUrl && normalizeAnvilUrl(c.detectedUrl) === detectedUrl).map((c)=>c.appId);
|
|
49282
49637
|
logger_logger.warn(chalk_source.yellow("Git remotes point to ") + chalk_source.bold(detectedUrl) + chalk_source.yellow(", but you specified: ") + chalk_source.bold(normalizedSelected));
|
|
49283
49638
|
if (detectedAppIds.length > 0) logger_logger.info(chalk_source.gray(" Detected app IDs on remote URL: ") + chalk_source.bold(detectedAppIds.join(", ")));
|
|
49284
|
-
logger_logger.info(chalk_source.gray(" To use the remote URL instead, run: ") + chalk_source.cyan(`anvil
|
|
49639
|
+
logger_logger.info(chalk_source.gray(" To use the remote URL instead, run: ") + chalk_source.cyan(`anvil watch --url ${detectedUrl}`));
|
|
49285
49640
|
}
|
|
49286
49641
|
const candidatesForSelectedUrl = detectedFromAllRemotes.filter((c)=>c.detectedUrl && normalizeAnvilUrl(c.detectedUrl) === normalizedSelected);
|
|
49287
49642
|
if (candidatesForSelectedUrl.length > 0) for (const candidate of candidatesForSelectedUrl){
|
|
@@ -49366,31 +49721,6 @@ var __webpack_exports__ = {};
|
|
|
49366
49721
|
}
|
|
49367
49722
|
logger_logger.verbose(chalk_source.green(`✔ App ID validated successfully`));
|
|
49368
49723
|
if (appIdValidation.app_name) logger_logger.verbose(chalk_source.gray(` App name: ${appIdValidation.app_name}`));
|
|
49369
|
-
const changeStatus = await checkUncommittedChanges(repoPath);
|
|
49370
|
-
if (changeStatus.hasChanges) {
|
|
49371
|
-
const skipPromptReasons = [];
|
|
49372
|
-
if (autoMode) skipPromptReasons.push("Auto mode enabled - continuing without confirmation.");
|
|
49373
|
-
if (stagedOnly && 0 === changeStatus.staged.length) skipPromptReasons.push("Staged-only mode with no staged changes - continuing without confirmation.");
|
|
49374
|
-
logger_logger.warn("Repository has uncommitted changes");
|
|
49375
|
-
if (changeStatus.modified.length > 0) logger_logger.verbose(chalk_source.gray(` Modified: ${changeStatus.modified.join(", ")}`));
|
|
49376
|
-
if (changeStatus.created.length > 0 || changeStatus.notAdded.length > 0) {
|
|
49377
|
-
const newFiles = [
|
|
49378
|
-
...changeStatus.created,
|
|
49379
|
-
...changeStatus.notAdded
|
|
49380
|
-
];
|
|
49381
|
-
logger_logger.verbose(chalk_source.gray(` New files: ${newFiles.join(", ")}`));
|
|
49382
|
-
}
|
|
49383
|
-
if (changeStatus.deleted.length > 0) logger_logger.verbose(chalk_source.gray(` Deleted: ${changeStatus.deleted.join(", ")}`));
|
|
49384
|
-
if (changeStatus.staged.length > 0) logger_logger.verbose(chalk_source.gray(` Staged: ${changeStatus.staged.join(", ")}`));
|
|
49385
|
-
if (skipPromptReasons.length > 0) skipPromptReasons.forEach((reason)=>logger_logger.verbose(chalk_source.gray(` ${reason}`)));
|
|
49386
|
-
else {
|
|
49387
|
-
const shouldContinue = await logger_logger.confirm("Do you want to continue watching anyway?", true);
|
|
49388
|
-
if (!shouldContinue) {
|
|
49389
|
-
logger_logger.warn("Watch cancelled. Please commit or stash your changes first.");
|
|
49390
|
-
process.exit(0);
|
|
49391
|
-
}
|
|
49392
|
-
}
|
|
49393
|
-
}
|
|
49394
49724
|
if (stagedOnly) logger_logger.info(chalk_source.yellow("▸ Staged-only mode: Only staged changes will be synced"));
|
|
49395
49725
|
if (autoMode) logger_logger.info(chalk_source.cyan("▸ Auto mode: Will automatically restart on branch changes and sync when behind"));
|
|
49396
49726
|
logger_logger.progress("init", "Initializing watch session...");
|
|
@@ -49411,10 +49741,10 @@ var __webpack_exports__ = {};
|
|
|
49411
49741
|
process.exit(1);
|
|
49412
49742
|
}
|
|
49413
49743
|
}
|
|
49414
|
-
function
|
|
49415
|
-
const
|
|
49744
|
+
function registerWatchCommand(program) {
|
|
49745
|
+
const watchCommand = program.command("watch [path]").description("Watch for file changes and sync to Anvil").alias("sync").alias("w").option("-A, --appid <APP_ID>", "Specify app ID directly").option("-f, --first", "Auto-select first detected app ID without confirmation").option("-s, --staged-only", "Only sync staged changes (use git add to stage files)").option("-a, --auto", "Auto mode: restart on branch changes and sync when behind").option("-V, --verbose", "Show detailed output").option("-u, --url <ANVIL_URL>", "Specify Anvil server URL (e.g., anvil.works, localhost)").option("-U, --user <USERNAME>", "Specify which user account to use").action(async (path, options)=>{
|
|
49416
49746
|
if (void 0 !== options.verbose && logger_logger instanceof CLILogger) logger_logger.setVerbose(options.verbose);
|
|
49417
|
-
await
|
|
49747
|
+
await handleWatchCommand({
|
|
49418
49748
|
path,
|
|
49419
49749
|
appid: options.appid,
|
|
49420
49750
|
useFirst: options.first,
|
|
@@ -49425,7 +49755,7 @@ var __webpack_exports__ = {};
|
|
|
49425
49755
|
user: options.user
|
|
49426
49756
|
});
|
|
49427
49757
|
});
|
|
49428
|
-
return
|
|
49758
|
+
return watchCommand;
|
|
49429
49759
|
}
|
|
49430
49760
|
var external_http_ = __webpack_require__("http");
|
|
49431
49761
|
const external_node_url_namespaceObject = require("node:url");
|
|
@@ -50177,83 +50507,88 @@ var __webpack_exports__ = {};
|
|
|
50177
50507
|
}
|
|
50178
50508
|
function registerLogoutCommand(program) {
|
|
50179
50509
|
const logoutCommand = program.command("logout [anvil-server-url]").description("Logout from Anvil (optionally specify URL to logout from specific installation)").option("-u, --url <ANVIL_URL>", "Specify Anvil server URL to logout from").option("-U, --user <USERNAME>", "Specify which user account to logout from").alias("lo").action(async (anvilUrl, options)=>{
|
|
50180
|
-
|
|
50181
|
-
|
|
50182
|
-
|
|
50183
|
-
|
|
50184
|
-
|
|
50185
|
-
|
|
50186
|
-
|
|
50187
|
-
|
|
50188
|
-
|
|
50189
|
-
const availableUrls = getAvailableAnvilUrls();
|
|
50190
|
-
if (0 === availableUrls.length) logger_logger.warn("No logged-in accounts found.");
|
|
50191
|
-
else if (1 === availableUrls.length) {
|
|
50192
|
-
const result = await logout();
|
|
50193
|
-
if (result.loggedOut) logger_logger.success("Logged out.");
|
|
50510
|
+
try {
|
|
50511
|
+
const urlToLogout = options?.url || anvilUrl;
|
|
50512
|
+
const usernameToLogout = options?.user;
|
|
50513
|
+
if (urlToLogout) {
|
|
50514
|
+
const normalized = normalizeAnvilUrl(urlToLogout);
|
|
50515
|
+
const result = await logout(normalized, usernameToLogout);
|
|
50516
|
+
if (result.loggedOut) if (usernameToLogout) logger_logger.success(`Logged out from ${normalized} as ${usernameToLogout}`);
|
|
50517
|
+
else logger_logger.success(`Logged out from ${normalized}`);
|
|
50518
|
+
else logger_logger.info(result.message || `Not logged in to ${normalized}. No action needed.`);
|
|
50194
50519
|
} else {
|
|
50195
|
-
const
|
|
50196
|
-
|
|
50197
|
-
|
|
50198
|
-
value: "one"
|
|
50199
|
-
},
|
|
50200
|
-
{
|
|
50201
|
-
name: "Logout from all accounts",
|
|
50202
|
-
value: "all"
|
|
50203
|
-
},
|
|
50204
|
-
{
|
|
50205
|
-
name: "Cancel",
|
|
50206
|
-
value: "cancel"
|
|
50207
|
-
}
|
|
50208
|
-
];
|
|
50209
|
-
const action = await logger_logger.select(`You have ${availableUrls.length} logged-in accounts. What would you like to do?`, choices, "one");
|
|
50210
|
-
if ("cancel" === action) return void logger_logger.info("Logout cancelled.");
|
|
50211
|
-
if ("all" === action) {
|
|
50520
|
+
const availableUrls = getAvailableAnvilUrls();
|
|
50521
|
+
if (0 === availableUrls.length) logger_logger.warn("No logged-in accounts found.");
|
|
50522
|
+
else if (1 === availableUrls.length) {
|
|
50212
50523
|
const result = await logout();
|
|
50213
|
-
if (result.loggedOut) logger_logger.success("Logged out
|
|
50524
|
+
if (result.loggedOut) logger_logger.success("Logged out.");
|
|
50214
50525
|
} else {
|
|
50215
|
-
const
|
|
50216
|
-
|
|
50217
|
-
|
|
50218
|
-
|
|
50219
|
-
|
|
50220
|
-
|
|
50221
|
-
|
|
50222
|
-
});
|
|
50223
|
-
const selectedUrl = await logger_logger.select("Which URL would you like to logout from?", urlChoices, availableUrls[0]);
|
|
50224
|
-
if (null === selectedUrl) return void logger_logger.info("Logout cancelled.");
|
|
50225
|
-
const accounts = auth_getAccountsForUrl(selectedUrl);
|
|
50226
|
-
if (accounts.length > 1) {
|
|
50227
|
-
const accountChoices = accounts.map((acc)=>({
|
|
50228
|
-
name: acc,
|
|
50229
|
-
value: acc
|
|
50230
|
-
}));
|
|
50231
|
-
accountChoices.push({
|
|
50232
|
-
name: "All accounts for this URL",
|
|
50526
|
+
const choices = [
|
|
50527
|
+
{
|
|
50528
|
+
name: "Logout from one account",
|
|
50529
|
+
value: "one"
|
|
50530
|
+
},
|
|
50531
|
+
{
|
|
50532
|
+
name: "Logout from all accounts",
|
|
50233
50533
|
value: "all"
|
|
50234
|
-
}
|
|
50235
|
-
|
|
50534
|
+
},
|
|
50535
|
+
{
|
|
50536
|
+
name: "Cancel",
|
|
50537
|
+
value: "cancel"
|
|
50538
|
+
}
|
|
50539
|
+
];
|
|
50540
|
+
const action = await logger_logger.select(`You have ${availableUrls.length} logged-in accounts. What would you like to do?`, choices, "one");
|
|
50541
|
+
if ("cancel" === action) return void logger_logger.info("Logout cancelled.");
|
|
50542
|
+
if ("all" === action) {
|
|
50543
|
+
const result = await logout();
|
|
50544
|
+
if (result.loggedOut) logger_logger.success("Logged out from all accounts.");
|
|
50545
|
+
} else {
|
|
50546
|
+
const urlChoices = availableUrls.map((url)=>({
|
|
50547
|
+
name: url,
|
|
50548
|
+
value: url
|
|
50549
|
+
}));
|
|
50550
|
+
urlChoices.push({
|
|
50236
50551
|
name: "Cancel",
|
|
50237
50552
|
value: null
|
|
50238
50553
|
});
|
|
50239
|
-
const
|
|
50240
|
-
if (null ===
|
|
50241
|
-
|
|
50554
|
+
const selectedUrl = await logger_logger.select("Which URL would you like to logout from?", urlChoices, availableUrls[0]);
|
|
50555
|
+
if (null === selectedUrl) return void logger_logger.info("Logout cancelled.");
|
|
50556
|
+
const accounts = auth_getAccountsForUrl(selectedUrl);
|
|
50557
|
+
if (accounts.length > 1) {
|
|
50558
|
+
const accountChoices = accounts.map((acc)=>({
|
|
50559
|
+
name: acc,
|
|
50560
|
+
value: acc
|
|
50561
|
+
}));
|
|
50562
|
+
accountChoices.push({
|
|
50563
|
+
name: "All accounts for this URL",
|
|
50564
|
+
value: "all"
|
|
50565
|
+
});
|
|
50566
|
+
accountChoices.push({
|
|
50567
|
+
name: "Cancel",
|
|
50568
|
+
value: null
|
|
50569
|
+
});
|
|
50570
|
+
const selectedAccount = await logger_logger.select(`Which account would you like to logout from ${selectedUrl}?`, accountChoices, accounts[0]);
|
|
50571
|
+
if (null === selectedAccount) return void logger_logger.info("Logout cancelled.");
|
|
50572
|
+
if ("all" === selectedAccount) {
|
|
50573
|
+
const result = await logout(selectedUrl);
|
|
50574
|
+
if (result.loggedOut) logger_logger.success(`Logged out from all accounts on ${selectedUrl}.`);
|
|
50575
|
+
else logger_logger.info(result.message || `Not logged in to ${selectedUrl}. No action needed.`);
|
|
50576
|
+
} else {
|
|
50577
|
+
const result = await logout(selectedUrl, selectedAccount);
|
|
50578
|
+
if (result.loggedOut) logger_logger.success(`Logged out from ${selectedUrl} as ${selectedAccount}.`);
|
|
50579
|
+
else logger_logger.info(result.message || `Not logged in to ${selectedUrl} as ${selectedAccount}. No action needed.`);
|
|
50580
|
+
}
|
|
50581
|
+
} else {
|
|
50242
50582
|
const result = await logout(selectedUrl);
|
|
50243
|
-
if (result.loggedOut) logger_logger.success(`Logged out from
|
|
50583
|
+
if (result.loggedOut) logger_logger.success(`Logged out from ${selectedUrl}.`);
|
|
50244
50584
|
else logger_logger.info(result.message || `Not logged in to ${selectedUrl}. No action needed.`);
|
|
50245
|
-
} else {
|
|
50246
|
-
const result = await logout(selectedUrl, selectedAccount);
|
|
50247
|
-
if (result.loggedOut) logger_logger.success(`Logged out from ${selectedUrl} as ${selectedAccount}.`);
|
|
50248
|
-
else logger_logger.info(result.message || `Not logged in to ${selectedUrl} as ${selectedAccount}. No action needed.`);
|
|
50249
50585
|
}
|
|
50250
|
-
} else {
|
|
50251
|
-
const result = await logout(selectedUrl);
|
|
50252
|
-
if (result.loggedOut) logger_logger.success(`Logged out from ${selectedUrl}.`);
|
|
50253
|
-
else logger_logger.info(result.message || `Not logged in to ${selectedUrl}. No action needed.`);
|
|
50254
50586
|
}
|
|
50255
50587
|
}
|
|
50256
50588
|
}
|
|
50589
|
+
} catch (error) {
|
|
50590
|
+
logger_logger.error(`Logout failed: ${error.message}`);
|
|
50591
|
+
process.exit(1);
|
|
50257
50592
|
}
|
|
50258
50593
|
});
|
|
50259
50594
|
logoutCommand.addHelpText("after", "\n" + chalk_source.bold("Examples:") + "\n anvil logout Logout from all accounts (or prompt if multiple)\n anvil logout anvil.works Logout from anvil.works\n anvil logout -u anvil.works Logout from anvil.works (using option)\n anvil logout -u anvil.works -U user@example.com Logout specific user\n");
|
|
@@ -50354,6 +50689,10 @@ var __webpack_exports__ = {};
|
|
|
50354
50689
|
setLogger(new CLILogger({
|
|
50355
50690
|
verbose: false
|
|
50356
50691
|
}));
|
|
50692
|
+
process.on("unhandledRejection", (reason)=>{
|
|
50693
|
+
logger_logger.error(`Unexpected error: ${reason}`);
|
|
50694
|
+
process.exit(1);
|
|
50695
|
+
});
|
|
50357
50696
|
function showBetaBanner() {
|
|
50358
50697
|
console.log();
|
|
50359
50698
|
console.log(chalk_source.yellow("┌────────────────────────────────────────────────────────┐"));
|
|
@@ -50420,7 +50759,7 @@ var __webpack_exports__ = {};
|
|
|
50420
50759
|
if ("update" !== commandName) checkVersionAndWarn();
|
|
50421
50760
|
}
|
|
50422
50761
|
});
|
|
50423
|
-
const
|
|
50762
|
+
const cli_watchCommand = registerWatchCommand(cli_program);
|
|
50424
50763
|
registerLoginCommand(cli_program);
|
|
50425
50764
|
registerLogoutCommand(cli_program);
|
|
50426
50765
|
registerConfigCommand(cli_program);
|
|
@@ -50428,13 +50767,13 @@ var __webpack_exports__ = {};
|
|
|
50428
50767
|
cli_program.command("update").description("Update anvil to the latest version").alias("u").action(async ()=>{
|
|
50429
50768
|
await handleUpdateCommand();
|
|
50430
50769
|
});
|
|
50431
|
-
if (
|
|
50432
|
-
const
|
|
50770
|
+
if (cli_watchCommand) {
|
|
50771
|
+
const watchOptions = cli_watchCommand.options.map((opt)=>{
|
|
50433
50772
|
const flags = opt.flags;
|
|
50434
50773
|
const description = opt.description || "";
|
|
50435
50774
|
return ` ${flags.padEnd(30)} ${description}`;
|
|
50436
50775
|
}).join("\n");
|
|
50437
|
-
if (
|
|
50776
|
+
if (watchOptions) cli_program.addHelpText("after", "\n" + chalk_source.bold("Watch Command Options:") + "\n" + chalk_source.gray(" (These options apply to the 'watch' command)") + "\n" + watchOptions + "\n");
|
|
50438
50777
|
}
|
|
50439
50778
|
cli_program.parse();
|
|
50440
50779
|
})();
|